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