My goal is to use goroutines and channel, i want to learn how to communicate between different goroutines and i want to avoid deadlock. I managed to use sync.WaitGroup
and it is working just fine.
However I received an error saying that
1 panic: sync: negative WaitGroup counter
goroutine 19 [running]:
The goal of this program is simple.
- Create a developer
- Assign him/her to create a website
- Depends on the number of the websites
- Once website is done then append it to the array
- Let there are 20 websites and 5 developers
- Each developer will take create 4 websites and append it to the websites array
- I want to do it concurrently so that other developers don't have to wait
The code:
package main
import (
"fmt"
"sync"
"time"
)
type developer struct {
name string
setTimeForWebsite time.Time
}
type website struct {
owner string
created time.Time
}
var developers []developer
var websites []website
// A function to create a developer
func hireDeveloper(wg *sync.WaitGroup, workNumber int,
developerCreatedc chan developer, devs []developer) {
defer wg.Done()
developerNumber := fmt.Sprintf("developer_%d", workNumber)
d := developer{name: developerNumber}
fmt.Println("Hired", d.name)
developerCreatedc <- d
}
// A function to create a website
func createComputer(wg *sync.WaitGroup, developerCreatedc chan developer, websitePerComputer int, websites []website) {
defer wg.Done()
// Assign the developer to the website creation // N number of the website
d := <-developerCreatedc
for i := 0; i <= websitePerComputer; i++ {
fmt.Println("Delegate", d.name, "to set the time to start
building the website")
d.setTimeForWebsite = time.Now()
fmt.Println(d.name, "Finish calculating to build the website", d.setTimeForWebsite)
web := website{owner: d.name, created: d.setTimeForWebsite}
websites = append(websites, web)
fmt.Println(len(websites))
time.Sleep(time.Second * 2)
fmt.Println(d.name, "Created website at", web.created)
}
}
func main() {
// Make a channel for when developer is hired
developerCreatedC := make(chan developer)
// create a sync group
wg := &sync.WaitGroup{}
// Assume that number of websites are 20
numberOfWebsites := 20
// Assume that number of developers are 5
numberOfDevelopers := 5
// Divide the websites to 5 developers
websitePerDeveloper := numberOfWebsites / numberOfDevelopers
// add the sync
wg.Add(1)
for i := 1; i <= numberOfDevelopers; i++ {
go func(producerNumber int) {
hireDeveloper(wg, producerNumber, developerCreatedC,
developers)
}(i)
}
wg.Add(1)
for i := 1; i <= websitePerDeveloper; i++ {
createComputer(wg, developerCreatedC, 5, websites)
}
wg.Wait()
}
The playground https://play.golang.org/p/QSOv5jp3T94
The behaviour is a bit sometimes, one developer created more than 4 websites, even though it is supposed to create only 4
Thanks