Golang - 哪些情况可以出现panic错误(开发中遇到了哪些坑)

一、除数为0

    a := 1
    b := 0
    c := a / b
    fmt.Println(c)

二、调用接口未实现的方法

三、数组下标越界、字符串越界(运行时错误,对于静态类型语言,数组下标越界是致命错误)

1)数组下标越界

package main
import "fmt"
func main() {
    var s []string
    fmt.Println(s)
    fmt.Println(s[0])
}

2)字符串越界

字符串是不可变的值类型,内部用指针指向UTF-8字节数组。

    a := "123"
    b := a[2]
    fmt.Println(b) // 51,数字3的ASCII码十进制数为51
    c := a[3]      //发生panic,字符串数组下标超界了
    fmt.Println(c)    

四、空指针引用(访问未初始化的指针或 nil 指针)

直接引用空指针结构体的字段会引发panic,但调用成员方法里如果没引用结构体的字段不会引发panic,有引用到字段还是会panic

package main

import "fmt"

type Person struct {
    Name string
    Age  int
}

func (p *Person) getName() string {
    fmt.Println(p.Name)
    return ""
}

func (p *Person) doNothing() string {
    fmt.Println("doNothing")
    return ""
}

func main() {
    var p *Person
    fmt.Println(p)      //nil
    fmt.Println(p.Name) //panic
    p.getName()         //会panic
    p.doNothing()       //不会panic
}

五、类型断言失败(接口转换异常)

    a := UserPb{}
    var b interface{}
    b = a
    c := b.(string)
    fmt.Println(c)

六、channel操作错误

1)试图往已经 close 的 chanel 里发送数据

正常关闭之后,写入会panic,读取元素是channel的零值(因为元素已经取完,如果没有取完,正常还是读到里面的元素)

ch := make(chan int)
fmt.Println(ch) //0xc00004c060

close(ch) //可以正常关闭,此时不会panic
go func() {
ch <- 1 //已经关闭之后再写入,会panic
//a := <-ch
//fmt.Println(a) //如果是读取元素会打印channel int的零值:0
}()
time.Sleep(time.Second)

2)关闭为nil的channel

new 的作用是初始化一个指向类型的指针(*T),使用new函数来分配空间,返回值是指向这个新分配的零值的指针。

ch := new(chan int)
fmt.Println(*ch) //nil
if *ch == nil {
fmt.Println("ch 为nil")
} else {
fmt.Println("ch 不为nil")
}
close(*ch) //nil,会panic

make 的作用是为slice,map或chan初始化并返回引用对象(T),返回一个有初始值的对象【注意不是指针】。

ch := make(chan int)
fmt.Println(ch) //0xc00009a000
if ch == nil {
fmt.Println("ch 为nil")
} else {
fmt.Println("ch 不为nil")
}
close(ch) //可以正常关闭,不会panic

3)关闭一个已经关闭的channel

    ch := make(chan int)
    fmt.Println(ch) //0xc00009a000

    close(ch) //可以正常关闭,不会panic
    close(ch) //重复关闭,会panic

七、死锁,所有线程睡眠(致命错误)

线程不安全(slice、map)的数据结构,多线程并发操作
八、给空map赋值

map未初始化,可读不可写。

map的value如果是结构体指针,使用时先判空。

即nil map写数据会panic,可以读

var map1 map[string]int
if map1 == nil {
fmt.Println("map1为nil")
}
fmt.Println("第1次打印map1:", map1) //可以读
map1["test"] = 1   //写会发生panic
fmt.Println("第2次打印map1:", map1)

九、并发读写相同的map(对于并发读写 map 的地方,应该对 map 加锁)
十、递归死循环或者超出栈空间

posted @ 2023-12-30 14:28  李若盛开  阅读(626)  评论(0)    收藏  举报