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的可空类型和零值》

原文地址:https://www.cnblogs.com/Gilfoyle/p/14259725.html