Golang Go语言中两份代码对比,为什么第一份代码不会panic,第二份代码会panic
第一份代码如下
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
}
Golang Go语言中两份代码对比,为什么第一份代码不会panic,第二份代码会panic
更多关于Golang Go语言中两份代码对比,为什么第一份代码不会panic,第二份代码会panic的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
第一份代码也是有 panic 的潜力的,建议读 https://tour.go-zh.org/concurrency/2
更多关于Golang Go语言中两份代码对比,为什么第一份代码不会panic,第二份代码会panic的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
所有线程都阻塞就 panic 了
第二个没有运行中的协程,编译器直接判断死锁了,随便加一个就可以了
说错 不是编译器判断 是运行中判断的
能写出第二个代码,有一个基本的原则你没有弄明白。即 channel 的用途:在不同的协程之间进行消耗的传递,而第二份代码,即对 channel 没有初始化,也没有额外的协程存在。
#1 emmm 抱歉看错了
chan 不是要 make 来创建吗,var **也行?
第二个没懂先看基础文档吧。。。。。
var 是声明
明白了,panic 会发生在所有的协程都被阻塞的情况下。把第一个程序简化为这样之后,也不会 panic 。因为 go 启动的一个协程在不断的运行,所以不会 panic
package main
func main() {
go func() {
for {
}
}()
var c chan bool
<-c
}
明白了,多谢多谢
感谢感谢
我看 op 的贴,把第二段代码加了个放东西的协程,感觉就不会出错了,然而还是报错,OP 知道啥原因吗?
package main
import (
“fmt”
)
func main() {
var c chan bool
go func() {
c <- true
}()
fmt.Println(<-c)
}
对 nil chan 做 send 或 recv 都会导致永远阻塞
你把代码改成这样,就不会 panic 了
原因就是 channel 没有初始化,只是做了 var 的声明
package main
import (
“fmt”
)
func main() {
//var c chan bool
c := make(chan bool)
go func() {
c <- true
}()
fmt.Println(<-c)
}
go 允许对一个 nil chan 进行读操作,这会导致阻塞。第二个例子会监测到死锁 panic 的原因是程序中没有其他 goroutine 正在运行。值得说明的是,这里不仅仅是要求有其他 goroutine 在运行,而且也不能全部同时阻塞,此时 go 运行时会监测到程序无法解除阻塞状态,从而再次导致死锁 panic 。
下面的代码说明了 [其他 goroutine 不能全部同时阻塞的情况] :<br> go func() {<br> var cc = make(chan bool)<br> <-cc<br> }()<br> var c = make(chan bool)<br> <-c<br>
最后:通过第二段代码(无论 chan 是否通过 make 创建)来阻塞主程序不是合理的实践,原因上面说了,当程序中只剩下一个 goroutine (主)在运行时,这种代码会死锁 panic 并退出。
把 “var c chan bool” 改成 “var c = make(chan bool)”就可以了,未初始化的 chan 变量并没有分配任何内存空间,因此无法进行读写操作
import 一个"net"也不会 panic🤣🤣🤣
求明说,或者给一个去验证的方向
在Golang中,代码是否会导致panic通常取决于多个因素,包括变量使用前的初始化状态、对空指针或nil值的解引用、数组越界访问等。针对你提到的两份代码对比,以下是一些可能的原因分析:
-
变量初始化:第一份代码可能在使用变量前进行了适当的初始化,确保变量在使用时不是nil或未定义状态。而第二份代码可能遗漏了某些变量的初始化,导致在运行时尝试访问未初始化的变量,从而引发panic。
-
空指针解引用:在第二份代码中,可能存在对nil指针的解引用操作,如调用nil对象的方法或访问nil指针指向的内存。而在第一份代码中,这种操作可能被避免了,或者相关的指针在使用前被正确赋值。
-
数组/切片越界:如果第二份代码中涉及到数组或切片的访问,可能存在索引越界的情况,这在Golang中会导致运行时panic。而第一份代码在处理数组或切片时,可能确保了索引的有效性。
-
并发问题:在涉及并发编程时,如果第二份代码中的goroutine或channel使用不当(如向已关闭的channel发送数据),也可能导致panic。第一份代码则可能正确地管理了并发资源。
为了更准确地诊断问题,建议检查两份代码的具体实现,特别是上述提到的潜在问题点。如果可能,使用Go的静态分析工具(如golint、go vet)或运行时调试器(如Delve)来帮助识别潜在问题。