Reputation: 119
This is my code, where have I gone wrong?
func main() {
intChan := make(chan int)
wg := sync.WaitGroup{}
for i := 0;i<5;i++{
wg.Add(1)
go send(intChan,i,&wg)
}
wg.Add(1)
go get(intChan,&wg)
wg.Wait()
time.Sleep(5*time.Second)
close(intChan)
}
func send(c chan int,index int,wg *sync.WaitGroup){
defer func() {
wg.Done()
}()
c <- index
}
func get(c chan int,wg *sync.WaitGroup){
defer func() {
wg.Done()
}()
for i := range c{
fmt.Printf("%d\n",i)
}
}
When I run this I get the error fatal error: all goroutines are asleep - deadlock!
Here is error info:
goroutine 1 [semacquire]:
sync.runtime_Semacquire(0xc0000120d8)
C:/Go/src/runtime/sema.go:56 +0x40
sync.(*WaitGroup).Wait(0xc0000120d0)
C:/Go/src/sync/waitgroup.go:130 +0x6b
main.main()
F:/go/src/demo/channel.go:94 +0xf9
goroutine 10 [chan receive]:
main.get(0xc00001c120, 0xc0000120d0)
F:/go/src/demo/channel.go:112 +0xe0
created by main.main
F:/go/src/demo/channel.go:92 +0xeb
thanks for all,this is my first question.
Upvotes: 3
Views: 773
Reputation: 3394
As Andy says in the comments you will only exit the get
function when all of the inputs have been received and the channel is closed. As you know there are five things to be received you could have a similar for
loop to in the send:
func main() {
intChan := make(chan int)
wg := sync.WaitGroup{}
for i := 0; i < 5; i++ {
wg.Add(1)
go send(intChan, i, &wg)
}
wg.Add(1)
go get(intChan, &wg)
wg.Wait()
close(intChan)
}
func send(c chan int, index int, wg *sync.WaitGroup) {
defer func() {
wg.Done()
}()
c <- index
}
func get(c chan int, wg *sync.WaitGroup) {
defer func() {
wg.Done()
}()
for i := 0; i < 5; i++ {
input := <- c
fmt.Printf("%d\n", input)
}
}
https://play.golang.org/p/CB8HUKPBu2I
If you want to stick with ranging over the channel then you will have to close it when all of the messages have been sent which I would do by adding a second wait group:
func main() {
intChan := make(chan int)
allSent := sync.WaitGroup{}
for i := 0; i < 5; i++ {
allSent.Add(1)
go send(intChan, i, &allSent)
}
allReceived := sync.WaitGroup{}
allReceived.Add(1)
go get(intChan, &allReceived)
allSent.Wait()
close(intChan)
allReceived.Wait()
}
func send(c chan int, index int, wg *sync.WaitGroup) {
defer func() {
wg.Done()
}()
c <- index
}
func get(c chan int, wg *sync.WaitGroup) {
defer func() {
wg.Done()
}()
for i := range c {
fmt.Printf("%d\n", i)
}
}
https://play.golang.org/p/svFVrBdwmAc
Upvotes: 1
Reputation: 119
this can work!
func main() {
intChan := make(chan int)
wg := sync.WaitGroup{}
for i := 0;i<5;i++{
wg.Add(1)
go send(intChan,i,&wg)
}
wg.Add(1)
go get(intChan,&wg)
wg.Wait()
close(intChan)
}
func send(c chan int,index int,wg *sync.WaitGroup){
defer func() {
wg.Done()
}()
c <- index
}
func get(c chan int,wg *sync.WaitGroup){
defer func() {
wg.Done()
}()
for {
select {
case i := <-c:
fmt.Printf("%d\n",i)
default:
return
}
}
}
Upvotes: 0