panic: sync: negative WaitGroup counter











up vote
0
down vote

favorite












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.




  1. Create a developer

  2. Assign him/her to create a website

  3. Depends on the number of the websites

  4. Once website is done then append it to the array

  5. Let there are 20 websites and 5 developers

  6. Each developer will take create 4 websites and append it to the websites array

  7. 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










share|improve this question




























    up vote
    0
    down vote

    favorite












    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.




    1. Create a developer

    2. Assign him/her to create a website

    3. Depends on the number of the websites

    4. Once website is done then append it to the array

    5. Let there are 20 websites and 5 developers

    6. Each developer will take create 4 websites and append it to the websites array

    7. 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










    share|improve this question


























      up vote
      0
      down vote

      favorite









      up vote
      0
      down vote

      favorite











      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.




      1. Create a developer

      2. Assign him/her to create a website

      3. Depends on the number of the websites

      4. Once website is done then append it to the array

      5. Let there are 20 websites and 5 developers

      6. Each developer will take create 4 websites and append it to the websites array

      7. 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










      share|improve this question















      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.




      1. Create a developer

      2. Assign him/her to create a website

      3. Depends on the number of the websites

      4. Once website is done then append it to the array

      5. Let there are 20 websites and 5 developers

      6. Each developer will take create 4 websites and append it to the websites array

      7. 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







      go concurrency






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 22 at 15:09









      Shudipta Sharma

      1,071312




      1,071312










      asked Nov 22 at 14:52









      sinusGob

      24131141




      24131141
























          2 Answers
          2






          active

          oldest

          votes

















          up vote
          1
          down vote



          accepted










          wg.Add() should be equal to the number number of go routine you are running. Also createComputer(wg, developerCreatedC, websitePerDeveloper, websites) should be per developer basis.



          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()
          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

          for i := 1; i <= numberOfDevelopers; i++ {
          // add the sync
          wg.Add(1)
          go func(producerNumber int) {
          hireDeveloper(wg, producerNumber, developerCreatedC, developers)
          }(i)

          wg.Add(1)
          go createComputer(wg, developerCreatedC, websitePerDeveloper, websites)
          }

          wg.Wait()
          }





          share|improve this answer





















          • why is the length of websites is 0?
            – sinusGob
            Nov 22 at 15:24










          • After i added it to the websites to the array?
            – sinusGob
            Nov 22 at 15:24












          • @sinusGob you send websites as call by value in the functions.
            – nightfury1204
            Nov 22 at 15:31












          • How do I send by reference? *websites?
            – sinusGob
            Nov 22 at 15:37










          • can you give me example?
            – sinusGob
            Nov 22 at 15:37


















          up vote
          0
          down vote













          You receive the error because you do wg.Add(1) before the loop.
          Every call to hireDeveloper() and createComputer() calls wg.Done(), so already in the first for loop wg wants to count down till -4 which is not possible thus the panic.



          A possible solution would be:



          wg.Add(numberOfDevelopers)
          for i := 1; i <= numberOfDevelopers; i++ {...}
          ....
          wg.Add(websitePerDeveloper)
          for i := 1; i <= websitePerDeveloper; i++ {...}


          or you pull wg.Add into the for loop:



                for i := 1; i <= numberOfDevelopers; i++ {
          wg.Add(1)
          go func(producerNumber int) {
          hireDeveloper(wg, producerNumber, developerCreatedC,
          developers)
          }(i)
          }





          share|improve this answer





















          • I receive fatal error: all goroutines are asleep - deadlock!
            – sinusGob
            Nov 22 at 15:07










          • The reason probably lays in your channels. Now it correctly blocks at wg.wait and your main go routine waits for ever instead of exiting early. I will update the answer in case I find something.
            – Nordiii
            Nov 22 at 15:12










          • @sinusGob so you receive a deadlock because you call 'createComputer' 20 times. In 'createComputer' you ask for a Developer (20 times because you called it 20x) but you only created 5. As ' d := <-developerCreatedc' is a blocking action you end up in a deadlock because this line waits for input
            – Nordiii
            Nov 22 at 15:22











          Your Answer






          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "1"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53433501%2fpanic-sync-negative-waitgroup-counter%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          2 Answers
          2






          active

          oldest

          votes








          2 Answers
          2






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes








          up vote
          1
          down vote



          accepted










          wg.Add() should be equal to the number number of go routine you are running. Also createComputer(wg, developerCreatedC, websitePerDeveloper, websites) should be per developer basis.



          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()
          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

          for i := 1; i <= numberOfDevelopers; i++ {
          // add the sync
          wg.Add(1)
          go func(producerNumber int) {
          hireDeveloper(wg, producerNumber, developerCreatedC, developers)
          }(i)

          wg.Add(1)
          go createComputer(wg, developerCreatedC, websitePerDeveloper, websites)
          }

          wg.Wait()
          }





          share|improve this answer





















          • why is the length of websites is 0?
            – sinusGob
            Nov 22 at 15:24










          • After i added it to the websites to the array?
            – sinusGob
            Nov 22 at 15:24












          • @sinusGob you send websites as call by value in the functions.
            – nightfury1204
            Nov 22 at 15:31












          • How do I send by reference? *websites?
            – sinusGob
            Nov 22 at 15:37










          • can you give me example?
            – sinusGob
            Nov 22 at 15:37















          up vote
          1
          down vote



          accepted










          wg.Add() should be equal to the number number of go routine you are running. Also createComputer(wg, developerCreatedC, websitePerDeveloper, websites) should be per developer basis.



          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()
          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

          for i := 1; i <= numberOfDevelopers; i++ {
          // add the sync
          wg.Add(1)
          go func(producerNumber int) {
          hireDeveloper(wg, producerNumber, developerCreatedC, developers)
          }(i)

          wg.Add(1)
          go createComputer(wg, developerCreatedC, websitePerDeveloper, websites)
          }

          wg.Wait()
          }





          share|improve this answer





















          • why is the length of websites is 0?
            – sinusGob
            Nov 22 at 15:24










          • After i added it to the websites to the array?
            – sinusGob
            Nov 22 at 15:24












          • @sinusGob you send websites as call by value in the functions.
            – nightfury1204
            Nov 22 at 15:31












          • How do I send by reference? *websites?
            – sinusGob
            Nov 22 at 15:37










          • can you give me example?
            – sinusGob
            Nov 22 at 15:37













          up vote
          1
          down vote



          accepted







          up vote
          1
          down vote



          accepted






          wg.Add() should be equal to the number number of go routine you are running. Also createComputer(wg, developerCreatedC, websitePerDeveloper, websites) should be per developer basis.



          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()
          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

          for i := 1; i <= numberOfDevelopers; i++ {
          // add the sync
          wg.Add(1)
          go func(producerNumber int) {
          hireDeveloper(wg, producerNumber, developerCreatedC, developers)
          }(i)

          wg.Add(1)
          go createComputer(wg, developerCreatedC, websitePerDeveloper, websites)
          }

          wg.Wait()
          }





          share|improve this answer












          wg.Add() should be equal to the number number of go routine you are running. Also createComputer(wg, developerCreatedC, websitePerDeveloper, websites) should be per developer basis.



          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()
          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

          for i := 1; i <= numberOfDevelopers; i++ {
          // add the sync
          wg.Add(1)
          go func(producerNumber int) {
          hireDeveloper(wg, producerNumber, developerCreatedC, developers)
          }(i)

          wg.Add(1)
          go createComputer(wg, developerCreatedC, websitePerDeveloper, websites)
          }

          wg.Wait()
          }






          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Nov 22 at 15:13









          nightfury1204

          1,41248




          1,41248












          • why is the length of websites is 0?
            – sinusGob
            Nov 22 at 15:24










          • After i added it to the websites to the array?
            – sinusGob
            Nov 22 at 15:24












          • @sinusGob you send websites as call by value in the functions.
            – nightfury1204
            Nov 22 at 15:31












          • How do I send by reference? *websites?
            – sinusGob
            Nov 22 at 15:37










          • can you give me example?
            – sinusGob
            Nov 22 at 15:37


















          • why is the length of websites is 0?
            – sinusGob
            Nov 22 at 15:24










          • After i added it to the websites to the array?
            – sinusGob
            Nov 22 at 15:24












          • @sinusGob you send websites as call by value in the functions.
            – nightfury1204
            Nov 22 at 15:31












          • How do I send by reference? *websites?
            – sinusGob
            Nov 22 at 15:37










          • can you give me example?
            – sinusGob
            Nov 22 at 15:37
















          why is the length of websites is 0?
          – sinusGob
          Nov 22 at 15:24




          why is the length of websites is 0?
          – sinusGob
          Nov 22 at 15:24












          After i added it to the websites to the array?
          – sinusGob
          Nov 22 at 15:24






          After i added it to the websites to the array?
          – sinusGob
          Nov 22 at 15:24














          @sinusGob you send websites as call by value in the functions.
          – nightfury1204
          Nov 22 at 15:31






          @sinusGob you send websites as call by value in the functions.
          – nightfury1204
          Nov 22 at 15:31














          How do I send by reference? *websites?
          – sinusGob
          Nov 22 at 15:37




          How do I send by reference? *websites?
          – sinusGob
          Nov 22 at 15:37












          can you give me example?
          – sinusGob
          Nov 22 at 15:37




          can you give me example?
          – sinusGob
          Nov 22 at 15:37












          up vote
          0
          down vote













          You receive the error because you do wg.Add(1) before the loop.
          Every call to hireDeveloper() and createComputer() calls wg.Done(), so already in the first for loop wg wants to count down till -4 which is not possible thus the panic.



          A possible solution would be:



          wg.Add(numberOfDevelopers)
          for i := 1; i <= numberOfDevelopers; i++ {...}
          ....
          wg.Add(websitePerDeveloper)
          for i := 1; i <= websitePerDeveloper; i++ {...}


          or you pull wg.Add into the for loop:



                for i := 1; i <= numberOfDevelopers; i++ {
          wg.Add(1)
          go func(producerNumber int) {
          hireDeveloper(wg, producerNumber, developerCreatedC,
          developers)
          }(i)
          }





          share|improve this answer





















          • I receive fatal error: all goroutines are asleep - deadlock!
            – sinusGob
            Nov 22 at 15:07










          • The reason probably lays in your channels. Now it correctly blocks at wg.wait and your main go routine waits for ever instead of exiting early. I will update the answer in case I find something.
            – Nordiii
            Nov 22 at 15:12










          • @sinusGob so you receive a deadlock because you call 'createComputer' 20 times. In 'createComputer' you ask for a Developer (20 times because you called it 20x) but you only created 5. As ' d := <-developerCreatedc' is a blocking action you end up in a deadlock because this line waits for input
            – Nordiii
            Nov 22 at 15:22















          up vote
          0
          down vote













          You receive the error because you do wg.Add(1) before the loop.
          Every call to hireDeveloper() and createComputer() calls wg.Done(), so already in the first for loop wg wants to count down till -4 which is not possible thus the panic.



          A possible solution would be:



          wg.Add(numberOfDevelopers)
          for i := 1; i <= numberOfDevelopers; i++ {...}
          ....
          wg.Add(websitePerDeveloper)
          for i := 1; i <= websitePerDeveloper; i++ {...}


          or you pull wg.Add into the for loop:



                for i := 1; i <= numberOfDevelopers; i++ {
          wg.Add(1)
          go func(producerNumber int) {
          hireDeveloper(wg, producerNumber, developerCreatedC,
          developers)
          }(i)
          }





          share|improve this answer





















          • I receive fatal error: all goroutines are asleep - deadlock!
            – sinusGob
            Nov 22 at 15:07










          • The reason probably lays in your channels. Now it correctly blocks at wg.wait and your main go routine waits for ever instead of exiting early. I will update the answer in case I find something.
            – Nordiii
            Nov 22 at 15:12










          • @sinusGob so you receive a deadlock because you call 'createComputer' 20 times. In 'createComputer' you ask for a Developer (20 times because you called it 20x) but you only created 5. As ' d := <-developerCreatedc' is a blocking action you end up in a deadlock because this line waits for input
            – Nordiii
            Nov 22 at 15:22













          up vote
          0
          down vote










          up vote
          0
          down vote









          You receive the error because you do wg.Add(1) before the loop.
          Every call to hireDeveloper() and createComputer() calls wg.Done(), so already in the first for loop wg wants to count down till -4 which is not possible thus the panic.



          A possible solution would be:



          wg.Add(numberOfDevelopers)
          for i := 1; i <= numberOfDevelopers; i++ {...}
          ....
          wg.Add(websitePerDeveloper)
          for i := 1; i <= websitePerDeveloper; i++ {...}


          or you pull wg.Add into the for loop:



                for i := 1; i <= numberOfDevelopers; i++ {
          wg.Add(1)
          go func(producerNumber int) {
          hireDeveloper(wg, producerNumber, developerCreatedC,
          developers)
          }(i)
          }





          share|improve this answer












          You receive the error because you do wg.Add(1) before the loop.
          Every call to hireDeveloper() and createComputer() calls wg.Done(), so already in the first for loop wg wants to count down till -4 which is not possible thus the panic.



          A possible solution would be:



          wg.Add(numberOfDevelopers)
          for i := 1; i <= numberOfDevelopers; i++ {...}
          ....
          wg.Add(websitePerDeveloper)
          for i := 1; i <= websitePerDeveloper; i++ {...}


          or you pull wg.Add into the for loop:



                for i := 1; i <= numberOfDevelopers; i++ {
          wg.Add(1)
          go func(producerNumber int) {
          hireDeveloper(wg, producerNumber, developerCreatedC,
          developers)
          }(i)
          }






          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Nov 22 at 15:04









          Nordiii

          1261110




          1261110












          • I receive fatal error: all goroutines are asleep - deadlock!
            – sinusGob
            Nov 22 at 15:07










          • The reason probably lays in your channels. Now it correctly blocks at wg.wait and your main go routine waits for ever instead of exiting early. I will update the answer in case I find something.
            – Nordiii
            Nov 22 at 15:12










          • @sinusGob so you receive a deadlock because you call 'createComputer' 20 times. In 'createComputer' you ask for a Developer (20 times because you called it 20x) but you only created 5. As ' d := <-developerCreatedc' is a blocking action you end up in a deadlock because this line waits for input
            – Nordiii
            Nov 22 at 15:22


















          • I receive fatal error: all goroutines are asleep - deadlock!
            – sinusGob
            Nov 22 at 15:07










          • The reason probably lays in your channels. Now it correctly blocks at wg.wait and your main go routine waits for ever instead of exiting early. I will update the answer in case I find something.
            – Nordiii
            Nov 22 at 15:12










          • @sinusGob so you receive a deadlock because you call 'createComputer' 20 times. In 'createComputer' you ask for a Developer (20 times because you called it 20x) but you only created 5. As ' d := <-developerCreatedc' is a blocking action you end up in a deadlock because this line waits for input
            – Nordiii
            Nov 22 at 15:22
















          I receive fatal error: all goroutines are asleep - deadlock!
          – sinusGob
          Nov 22 at 15:07




          I receive fatal error: all goroutines are asleep - deadlock!
          – sinusGob
          Nov 22 at 15:07












          The reason probably lays in your channels. Now it correctly blocks at wg.wait and your main go routine waits for ever instead of exiting early. I will update the answer in case I find something.
          – Nordiii
          Nov 22 at 15:12




          The reason probably lays in your channels. Now it correctly blocks at wg.wait and your main go routine waits for ever instead of exiting early. I will update the answer in case I find something.
          – Nordiii
          Nov 22 at 15:12












          @sinusGob so you receive a deadlock because you call 'createComputer' 20 times. In 'createComputer' you ask for a Developer (20 times because you called it 20x) but you only created 5. As ' d := <-developerCreatedc' is a blocking action you end up in a deadlock because this line waits for input
          – Nordiii
          Nov 22 at 15:22




          @sinusGob so you receive a deadlock because you call 'createComputer' 20 times. In 'createComputer' you ask for a Developer (20 times because you called it 20x) but you only created 5. As ' d := <-developerCreatedc' is a blocking action you end up in a deadlock because this line waits for input
          – Nordiii
          Nov 22 at 15:22


















          draft saved

          draft discarded




















































          Thanks for contributing an answer to Stack Overflow!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.





          Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


          Please pay close attention to the following guidance:


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53433501%2fpanic-sync-negative-waitgroup-counter%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          What visual should I use to simply compare current year value vs last year in Power BI desktop

          How to ignore python UserWarning in pytest?

          Alexandru Averescu