nil)是一个常见且需要小心处理的问题。它不仅可能导致程序崩溃,还会使代码逻辑变得难以维护。文章目录
nil,如果尝试解引用,将触发runtime panic。代码示例var ptr *int
fmt.Println(*ptr) // panic: invalid memory address or nil pointer dereference正确的处理方法var ptr = new(int)
*ptr = 42
fmt.Println(*ptr) // 输出 42nil判断nil但动态类型不为nil时,接口本身不为nil。代码示例var err error = (*MyError)(nil)
if err == nil {
fmt.Println("err is nil")
} else {
fmt.Println("err is not nil") // 输出这行
}正确的处理方法nil时,需同时检查其动态值和动态类型:if err == nil || reflect.ValueOf(err).IsNil() {
fmt.Println("err is nil")
}nilnil,操作它们可能导致意外行为。代码示例var m map[string]int
m["key"] = 1 // panic: assignment to entry in nil map正确的处理方法m := make(map[string]int)
m["key"] = 1type User struct {
Name *string
}
var u User
fmt.Println(*u.Name) // panic正确的处理方法name := "John"
u := User{Name: &name}
fmt.Println(*u.Name)nil问题nil的情况。代码示例type User struct {
Age *int `json:"age"`
}
jsonStr := `{}`
var u User
json.Unmarshal([]byte(jsonStr), &u)
fmt.Println(*u.Age) // panic正确的处理方法nil检查:if u.Age != nil {
fmt.Println(*u.Age)
} else {
fmt.Println("Age is nil")
}nil,直接解引用将导致崩溃。代码示例var slice []*int
slice = append(slice, nil)
fmt.Println(*slice[0]) // panic正确的处理方法nil:for _, v := range slice {
if v != nil {
fmt.Println(*v)
} else {
fmt.Println("nil element")
}
}recover机制未捕获空指针异常panic/recover机制,但如果未正确捕获空指针异常,程序仍会终止。代码示例func risky() {
var ptr *int
fmt.Println(*ptr)
}
func main() {
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered from:", r)
}
}()
risky()
}正确的处理方法recover机制覆盖整个函数调用链。database/sql查询数据时,若字段值为NULL,扫描到指针类型字段时会返回nil。代码示例var name *string
err := db.QueryRow("SELECT name FROM users WHERE id = ?", 1).Scan(&name)
if err != nil {
log.Fatal(err)
}
fmt.Println(*name) // panic if name is nil正确的处理方法nil检查:if name != nil {
fmt.Println(*name)
} else {
fmt.Println("Name is NULL")
}空指针问题虽然常见,但通过仔细设计和谨慎编程,完全可以规避。以下是一些通用的建议:
nil。golangci-lint)捕捉潜在的空指针问题。通过遵循这些实践,可以显著提高Golang项目的健壮性和稳定性。