MST
星途 面试题库

面试题:Go中并发场景下panic的常见触发原因

在Go语言的并发编程中,列举至少3种可能导致panic的常见情况,并简单说明原因。
50.1万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试
  1. 空指针引用
    • 原因:当代码尝试对一个值为nil的指针进行解引用操作时会发生panic。例如,定义一个指向结构体的指针,但没有对其初始化就访问结构体的字段。
    type Person struct {
        Name string
    }
    var p *Person
    fmt.Println(p.Name) // 这里会panic,因为p是nil
    
  2. 数组或切片越界
    • 原因:访问数组或切片时,如果索引超出了其有效范围,就会触发panic。Go语言的数组和切片都是基于零索引的,且索引必须在0长度 - 1之间。
    arr := [3]int{1, 2, 3}
    fmt.Println(arr[3]) // 这里会panic,因为索引3超出了数组长度
    
  3. 向关闭的通道发送数据
    • 原因:一旦通道被关闭,就不能再向其发送数据,否则会导致panic。这是Go语言运行时为了避免数据竞争和未定义行为所做的限制。
    ch := make(chan int)
    close(ch)
    ch <- 1 // 这里会panic,因为通道已关闭
    
  4. 从空且已关闭的通道接收数据
    • 原因:从已关闭且没有数据的通道接收数据时,会立即接收到通道元素类型的零值,并且第二个返回值(表示通道是否关闭的布尔值)为false。但如果依赖于通道持续提供数据而不检查通道关闭状态,可能会导致逻辑错误,虽然不会直接panic,但后续基于这个零值的不当处理可能会引发panic。如果使用range循环从已关闭且空的通道接收数据,range会正常结束,但如果直接接收并假设通道始终有数据,可能会引发问题。
    ch := make(chan int)
    close(ch)
    data, ok := <-ch
    if!ok {
        // 这里应该处理通道关闭的情况,否则可能后续对data的不当处理引发panic
    }
    
  5. 调用recover函数时不在defer函数中
    • 原因recover函数只有在defer函数内部调用才会起作用,用于捕获panic并恢复程序正常执行流程。如果在defer函数外部调用,recover总是返回nil,并且不会对panic进行处理,程序依然会崩溃。
    func main() {
        recover() // 这里调用recover不会捕获panic,程序依然会按原流程处理panic
        panic("test panic")
    }