今天我正在学习围棋的频道和套路。我遇到了一些让我感到困惑的现象。
我的 go 文件如下所示:
package main
import (
"fmt"
)
func testRoutine(number int, channel chan int) {
channel <- number
}
func main() {
// var a chan int
a := make(chan int)
b := make(chan int)
go testRoutine(1, a)
go testRoutine(2, b)
c, d := <-a, <-b
fmt.Printf("%d %dn", c, d)
}
当我使用语法a := make(chan int)
时,它运行良好。
但是当我把a := make(chan int)
改成var a chan int
时,我得到了恐慌报告:
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan receive (nil chan)]:
main.main()
/Users/marioluisgarcia/Local/practice/go/cache/var_make_diff.go:19 +0xc7
goroutine 18 [chan send (nil chan)]:
main.testRoutine(0x1, 0x0)
/Users/marioluisgarcia/Local/practice/go/cache/var_make_diff.go:8 +0x3f
created by main.main
/Users/marioluisgarcia/Local/practice/go/cache/var_make_diff.go:16 +0x7c
goroutine 19 [chan send]:
main.testRoutine(0x2, 0xc42008a060)
/Users/marioluisgarcia/Local/practice/go/cache/var_make_diff.go:8 +0x3f
created by main.main
/Users/marioluisgarcia/Local/practice/go/cache/var_make_diff.go:17 +0xa7
那么,var a chan int
和a := make(chan int)
之间有什么区别,为什么会引发这种恐慌现象呢?
a := make(chan int)
创建无缓冲通道。该通道具有零缓冲区。您可以通过它发送数据。
var a chan int
创建通道变量并将其设置为默认值 nil。并且 nil 通道总是阻塞,这就是您的程序死锁的原因。您不能在 nil 通道中发送数据。
如果打印值,您将看到差异。
package main
import (
"fmt"
)
func main() {
var i chan int
fmt.Println(i)
a := make(chan int)
fmt.Println(a)
}
去游乐场链接:https://play.golang.org/p/Bxr6qRfNqZd
回想一下,var name type
会创建一个名为 name
的变量,该变量的类型type
设置为该类型的默认值。 这意味着var a chan int
创建了一个通道,以便a == nil
.
然而,var a chan int = make(chan int)
和a := make(chan int)
是相同的。
var x chan int
只是 'x' 的声明,您只在堆栈中创建一个 val,而堆中没有实际的内存 malloc。
var x chan int
x = make(chan int, 0)
这种方式实际上可以在这个 X 的堆中 malloc 一些内存。
顺便说一下,在堆栈或堆中构建的 val 是在 golang 中模糊区分的。对于那些引用类型,如map,slice,chan type,它们都应该在使用之前make()
,否则它会因为零点错误而死