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) // 输出 42
nil
判断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")
}
nil
nil
,操作它们可能导致意外行为。代码示例var m map[string]int
m["key"] = 1 // panic: assignment to entry in nil map
正确的处理方法m := make(map[string]int)
m["key"] = 1
type 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项目的健壮性和稳定性。