
第一份代码如下
package main import ( "fmt" "time" ) func main() { var ball = make(chan string) kickBall := func(playerName string) { for { fmt.Print(<-ball, "传球", "\n") time.Sleep(1 * time.Second) ball <- playerName } } go kickBall("张三") go kickBall("李四") go kickBall("王五") go kickBall("赵六") ball <- "裁判" var c chan bool <-c } 分界线
第二份代码如下
package main func main() { var c chan bool <-c } 1 0o0O0o0O0o 2023-07-06 08:44:51 +08:00 via iPhone 第一份代码也是有 panic 的潜力的,建议读 https://tour.go-zh.org/concurrency/2 |
2 aarontian 2023-07-06 08:45:29 +08:00 via Android 所有线程都阻塞就 panic 了 |
3 rekulas 2023-07-06 08:48:14 +08:00 第二个没有运行中的协程,编译器直接判断死锁了,随便加一个就可以了 |
4 rekulas 2023-07-06 08:49:45 +08:00 说错 不是编译器判断 是运行中判断的 |
5 Rooger 2023-07-06 09:01:27 +08:00 能写出第二个代码,有一个基本的原则你没有弄明白。即 channel 的用途:在不同的协程之间进行消耗的传递,而第二份代码,即对 channel 没有初始化,也没有额外的协程存在。 |
6 0o0O0o0O0o 2023-07-06 09:17:17 +08:00 @0o0O0o0O0o #1 emmm 抱歉看错了 |
7 Seanfuck 2023-07-06 09:24:10 +08:00 chan 不是要 make 来创建吗,var **也行? |
8 8355 2023-07-06 09:29:40 +08:00 第二个没懂先看基础文档吧。。。。。 |
9 paceewang1 2023-07-06 09:48:52 +08:00 @Seanfuck var 是声明 |
10 hsfzxjy 2023-07-06 09:59:00 +08:00 via Android 所有 goroutine 都睡了就会 panic |
11 CarrieBauch OP @aarontian 明白了,panic 会发生在所有的协程都被阻塞的情况下。把第一个程序简化为这样之后,也不会 panic 。因为 go 启动的一个协程在不断的运行,所以不会 panic package main func main() { go func() { for { } }() var c chan bool <-c } |
12 CarrieBauch OP @rekulas 明白了,多谢多谢 |
13 CarrieBauch OP @hsfzxjy 感谢感谢 |
14 Richard14 2023-07-06 10:15:56 +08:00 我看 op 的贴,把第二段代码加了个放东西的协程,感觉就不会出错了,然而还是报错,OP 知道啥原因吗? package main import ( "fmt" ) func main() { var c chan bool go func() { c <- true }() fmt.Println(<-c) } |
16 CarrieBauch OP @Richard14 你把代码改成这样,就不会 panic 了 原因就是 channel 没有初始化,只是做了 var 的声明 package main import ( "fmt" ) func main() { //var c chan bool c := make(chan bool) go func() { c <- true }() fmt.Println(<-c) } |
17 lasuar 2023-07-06 10:45:20 +08:00 go 允许对一个 nil chan 进行读操作,这会导致阻塞。第二个例子会监测到死锁 panic 的原因是程序中没有其他 goroutine 正在运行。值得说明的是,这里不仅仅是要求有其他 goroutine 在运行,而且也不能全部同时阻塞,此时 go 运行时会监测到程序无法解除阻塞状态,从而再次导致死锁 panic 。 下面的代码说明了 [其他 goroutine 不能全部同时阻塞的情况] : ``` go func() { var cc = make(chan bool) <-cc }() var c = make(chan bool) <-c ``` 最后:通过第二段代码(无论 chan 是否通过 make 创建)来阻塞主程序不是合理的实践,原因上面说了,当程序中只剩下一个 goroutine (主)在运行时,这种代码会死锁 panic 并退出。 |
18 crescentBLADE 2023-07-06 10:48:30 +08:00 @Richard14 把 “var c chan bool” 改成 “var c = make(chan bool)”就可以了,未初始化的 chan 变量并没有分配任何内存空间,因此无法进行读写操作 |
19 codehz 2023-07-06 13:40:50 +08:00 import 一个"net"也不会 panic |
20 /div> BinaryDH 2023-07-06 17:47:57 +08:00 唉,问了一个问题,还得到了一份错误的答案!好好看看 channel 和 groutine 的文档吧,每一次阅读和编写 demo ,相信你都能有不同的提升。 |
21 CarrieBauch OP @BinaryDH 求明说,或者给一个去验证的方向 |