golang的可空类型和零值
non-nillbale and nillable types 可空和不可空类型
类型可以分为可空类型和不可空类型, 对应的默认值就为 nil
和零值(下方有说明)
可空类型可以置为nil
不可空类型不允许置为nil,否则会导致 nil-panic
不可空的基本类型
在go里面,基本类型都是不可空类型
var a int = nil
无法通过编译,因为 int
无法置成0值。 int
的默认值是0。
var a int // default value of int, cannot be nil
fmt.Println(a) // 0
0
我们称之为类型的零值
类型零值表 zero-value
Types | Zero value |
int, int8, int16, int32, int64 | 0 |
uint, uint8, uint16, uint32, uint64 | 0 |
uintptr | 0 |
float32, float64 | 0.0 |
byte | 0 |
rune | 0 |
string | "” (empty string) |
complex64, complex128 |
(0,0i) |
boolean |
false |
arrays of non-nillable types | array of zero-values |
arrays of nillable types | array of nil-values |
不可空的结构体
struct
也是不可空的,它的默认值由字段( field
)的默认值组成
可空类型
可空类型的默认值为 nil
需要保持可警惕,是否未nil,在可空类型在被初始化之前使用,可能会导致panic
可空类型包含:
- functions 函数
- channels 管道
- slices 切片
- maps 映射
- interface 接口
- pointer 指针
空映射 map
map会返回对应类型的默认值, 不会导致panic
但是,对空map赋值会导致panic
type Person struct {
Name string
Age int
Married bool
}
func main() {
var mp map[string]Person
var mpP map[string]*Person
var mpS map[string]string
//-> map[]
fmt.Println(mp)
//-> { 0 false} 有一个空字符串
fmt.Print(mp["me"])
// nil
fmt.Println(mpP["me"])
// 空字符串
fmt.Println(mpS[99])
// panic: assignment to entry in nil map
mpS[1] = "SSS"
}
为初始化使用导致 panic
var mp map[string]int
//panic: assignment to entry in nil map
mp["me"] = 0
空切片 slice
对空切片取值, 仅会导致数组越界的panic
但是对,未初始化的slice len()
和 cap()
返回0, append
操作也可以安全使用
var s []Person
//[]
fmt.Println(s)
// 0 0
fmt.Println(len(s), cap(s))
s = append(s, Person{Name:"kurt", Age: 18, Married:false})
fmt.Println(s)
//panic: runtime error: index out of range [1] with length 1
fmt.Println(s[1])
可空类型的panic
- pointers
- functions
- interface-types
以上类型使用对时候需要保持留意是否为nil值
panic
- pointers
var p *int // pointer to an int
*p++ // panic: runtime error: invalid memory address or nil pointer dereference
// p is an address to nothing, and therefore is nil
- interface
var p error // nil-value of type error
error.Error() // panic: runtime error: invalid memory address or nil pointer dereference
- func
var f func(string) // nil-function
f("oh oh") // panic: runtime error: invalid memory address or nil pointer dereference
死锁
- nil的channel无法读或者写,会造成死锁
var c chan bool
//fatal error: all goroutines are asleep - deadlock!
c <- true
fmt.Println("hello world")
- 关闭nil值对channel会导致panic
var c chan bool
//panic: close of nil channel
close(c)
fmt.Println("hello world")
以上
系统地学习go各种类型的默认值
参考文献
原文地址 https://nilsmagnus.github.io/post/nillability-in-go/ (英文)
语雀博文 https://www.yuque.com/docs/share/102a846a-013b-49a5-a149-063264a930a0?# 《golang的可空类型和零值》