[Understanding] Golang nil Go language

The pre golang nil declared identifier defined in builtin / builtin.go.

// nil is a predeclared identifier representing the zero value for a
// pointer, channel, func, interface, map, or slice type.
// Type must be a pointer, channel, func, interface, map, or slice type
var nil Type 

// Type is here for the purposes of documentation only. It is a stand-in
// for any Go type, but represents the same type for any given function
// invocation.
type Type int
Zero value of nil

Go according language specification, when any type corresponds to a non-zero value initialized: Boolean is false, 0 is an integer, string is "", and the pointer value is zero, functions, interface, slice, channel map, and are nil.

PS: There is not zero, said structure struct is nil, because the zero value struct property related thereto.

nil is not the default type, though it is more than one type of zero value, you must explicitly type explicitly or implicitly specify each nil usage.

package main

func main() {

    // 明确.
    _ = (*struct{})(nil)
    _ = []int(nil)
    _ = map[int]bool(nil)
    _ = chan string(nil)
    _ = (func())(nil)
    _ = interface{}(nil)

    // 隐式.
    var _ *struct{} = nil
    var _ []int = nil
    var _ map[int]bool = nil
    var _ chan string = nil
    var _ func() = nil
    var _ interface{} = nil
}

If concerned about the students will find golang keywords, which is not nil, nil that is not a keyword, it can be defined in the code nil, then nil will be hidden.

package main

import "fmt"

func main() {
    nil := 123
    fmt.Println(nil) // 123
    var _ map[string]int = nil //cannot use nil (type int) as type map[string]int in assignment
}
nil value of the size and type of address

Memory layout of all types of nil value is always the same, that is, other words: nil different types of memory address is the same.

package main
import (
    "fmt"
)
func main() {
    var m map[int]string
    var ptr *int
    var sl []int
    fmt.Printf("%p\n", m)       //0x0
    fmt.Printf("%p\n", ptr )    //0x0
    fmt.Printf("%p\n", sl )     //0x0
}

Business generally nil value is expressed as an exception. Its size is always nil value type of the nil value of the same non-nil value of the same size. Thus, a different value of zero indicates nil identifier may have different sizes.

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
}

The compiler and the size depends architecture. The results for the above print 64-bit architecture and official Go compiler. For 32-bit architecture, the size of the print will be half.

Go to the official compiler, the size of two nil values ​​of different types of the same kind of always the same. For example, two different types of slices ([] and int [] String) nil value of the two is always the same.

nil value comparison

Different types of nil is not comparable.

package main
import (
    "fmt"
)
func main() {
    var m map[int]string
    var ptr *int
    fmt.Printf(m == ptr) //invalid operation: m == ptr (mismatched types map[int]string and *int)
}

In Go, the two values ​​are different types may be compared to a value of only implicitly convertible to compare a case where another type. Specifically, there are two cases two different values ​​can be compared:

  • One of two types of values ​​are the basis of another type.
  • One of two types of values ​​to achieve a value of another type (the type of interface must be).

nil value comparison and without departing from the above rules.

package main
import (
    "fmt"
)
func main() {
    type IntPtr *int
    fmt.Println(IntPtr(nil) == (*int)(nil))            //true
    fmt.Println((interface{})(nil) == (*int)(nil))    //false
}

Two nil values ​​of the same type could not be compared because of the presence map golang in, slice type and function type are not comparable, they do not have a type called incomparable, so comparing their nil is also illegal.

package main
import (
    "fmt"
)
func main() {
    var v1 []int = nil
    var v2 []int = nil
    fmt.Println(v1 == v2)
    fmt.Println((map[string]int)(nil) == (map[string]int)(nil))
    fmt.Println((func())(nil) == (func())(nil))
}

Incomparable types of missing values ​​can be compared with "pure nil".

package main
import (
    "fmt"
)
func main() {
    fmt.Println((map[string]int)(nil) == nil)  //true
    fmt.Println((func())(nil) == nil)           //true
}

Two nil value may not be equal

Nil value if one of the two compared values ​​is an interface, the other is not, it is assumed that they are comparable, the comparison result is always false. The reason is that prior to the comparison, the interface value is converted to an interface type value. Interface converted value having a particular dynamic type, but other values ​​are not interfaces. That's why the comparison is always wrong.

package main
import (
    "fmt"
)
func main() {
    fmt.Println( (interface{})(nil) == (*int)(nil) ) // false
}
common problem

Function returns

func nilReturn() (string,error)  {

    return nil,nil  //cannot use nil as type string in return argument
}

Because the error is error type interface types so there is no error.

nil key of the map key map pointer, a function, interface, slice, channel map, and, the key may be nil.

package main
import (
    "fmt"
)
func main() {
    mmap := make(map[*string]int,4)
    a:="a"
    mmap[&a] = 1
    mmap[nil] = 99
    fmt.Println(mmap)   //map[0xc042008220:1 <nil>:99]
}
Published 343 original articles · won praise 14 · views 90000 +

Guess you like

Origin blog.csdn.net/LU_ZHAO/article/details/105300612