首页 > 解决方案 > go中如何使用通道?

问题描述

我有一个函数,它接受一个 int 数组并将它们转储到一个通道中。

func Dump(a []int, ch chan int) {
    for i := range a {
        ch <- i
    }
    close(ch)
}

这个主要不建立:

func main() {
    ch := make(chan int)
    arr := []int{1, 2, 3, 4, 5}
    Dump(arr, ch)
    for i := range ch {
        fmt.Printf("Got %v\n", i)
    }
}

抛出此错误:

fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan send]:
main.Dump(0xc000078f48, 0x5, 0x5, 0xc00006e060)
        /Users/300041738/go-workspace/src/test.go:7 +0x43
main.main()
        /Users/300041738/go-workspace/src/test.go:15 +0x9b
exit status 2

但是,这会构建:

func main() {
    ch := make(chan int)
    arr := []int{1, 2, 3, 4, 5}
    go Dump(arr, ch)
    for i := range ch {
        fmt.Printf("Got %v\n", i)
    }
}

为什么我必须在 Dump 前面写 go?我不希望异步转储数组的内容。

标签: go

解决方案


通道有缓冲区。默认情况下,缓冲区的大小为 0。换句话说,如果要将元素插入到非缓冲通道中,插入的 goroutine 将停止,直到另一个 goroutine 从通道中检索值。

所以为了好玩,试试这个:

import "fmt"

func Dump(a []int, ch chan int) {
    for i := range a {
        ch <- i
    }
    close(ch)
}

func main() {
    arr := []int{1, 2, 3, 4, 5}
    ch := make(chan int, len(arr)) //specify channel buffer length equal to arr size
    Dump(arr, ch)
    for {
        i, ok := <- ch
        if ok {
            fmt.Println("received a number !", i)
        } else {
            fmt.Println("channel is closed, we're done here")
        }
    }
}

推荐阅读