深入理解golang的nil类型

发布时间 2023-07-19 10:09:22作者: 意犹未尽

误区

刚开始总是以为golang的nil和其他编程语言的NULL是一个东西,golang 的nil表示复杂类型的默认值,比如golang中基本类类型都有自己的默认值如 int=0 bool=false string=""

 

nli关键字?还是类型?还是变量?

nil是一个变量

 

nil本质上是一个 Type类型的变量而已;
Type类型仅仅是基于 int定义出来的一个新类型;
 

nil为特殊类型的默认值

注:并不包含stuct

pointer types (including type-unsafe ones). 
map types.
slice types.
function types.
channel types.
interface types.
package main
import "fmt"
type Person struct {
    Id   int
    Name string
    Info interface{}
}
func main() {
    var p Person
    fmt.Println(p)// {0  <nil>}
}

不同类型的nil不一样

package main
import (
    "fmt"
    "unsafe"
)
func main() {
    var p *struct{} = nil
    fmt.Println( unsafe.Sizeof( p ) ) // 8
    var s []int = nil
    fmt.Println( unsafe.Sizeof( s ) ) // 24
    var m map[int]bool = nil
    fmt.Println( unsafe.Sizeof( m ) ) // 8
    var c chan string = nil
    fmt.Println( unsafe.Sizeof( c ) ) // 8
    var f func() = nil
    fmt.Println( unsafe.Sizeof( f ) ) // 8
    var i interface{} = nil
    fmt.Println( unsafe.Sizeof( i ) ) // 16
}

nil需要足够的类型推导

因为不同类型的nil不一致,所以直接定义var a=nil 是不行的

package main
func main() {
    // This following line doesn't compile.
    /*
    v := nil
    */
    // There must be sufficient information for compiler
    // to deduce the type of a nil value.
    _ = (*struct{})(nil)
    _ = []int(nil)
    _ = map[int]bool(nil)
    _ = chan string(nil)
    _ = (func())(nil)
    _ = interface{}(nil)
    // This lines are equivalent to the above lines.
    var _ *struct{} = nil
    var _ []int = nil
    var _ map[int]bool = nil
    var _ chan string = nil
    var _ func() = nil
    var _ interface{} = nil
}

nil在go中不是关键字

预先宣布的nil可以被覆盖

package main
import "fmt"
func main() {
   nil := 123
   fmt.Println(nil) // 123
}

nil是不可以用来直接比较的

因为2个nil都不知道是什么类型不能用作比较

func main() {
    fmt.Println(nil == nil)
}
#invalid operation: nil == nil (operator == not defined on untyped nil)

 

调用nil的方法也是合法的

因为nil是复杂类型的预定义类型,所以我们可以使用他们的方法

package main

import "fmt"

func main() {
   for range []int(nil) { //循环次数将是0
      fmt.Println("Hello")
   }

   for range map[string]string(nil) { //循环次数将是0
      fmt.Println("world")
   }

   for i := range (*[5]int)(nil) {
      fmt.Println(i) // 0 1 2 3 4
   }

   for range chan bool(nil) { // block here
      fmt.Println("Bye") //fatal error: all goroutines are asleep - deadlock!

   }
}