Golang's knowledge about nil

Source: Internet
Author: User
Tags what interface

Golang's knowledge about nil

1. What is nil?

As we all know, when you declare a variable but still have the value of the wood, the Golang will automatically give you a corresponding default value of 0 for the variable type. This is the corresponding 0 value for each type:

bool      -> false                              numbers -> 0                                 string    -> ""      pointers -> nilslices -> nilmaps -> nilchannels -> nilfunctions -> nilinterfaces -> nil

One more strcut:

type Person struct {  Age int  Name string  Friends []Person}var p Person // Person{0, "", nil}

The variable p is only declared but not assigned, so all fields of P have a corresponding value of 0.

1. In the go document, nil is a predefined identifier that represents the 0 value of a pointer, channel, function, interface, map, or slice, and is not one of the key words of Go

2. Nil can only be assigned to pointers, channel, Func, interface, map, or slice type variables (non-basic types) or it will cause panic

2. What's the use of nil?

Pointers

var p *intp == nil    // true*p          // panic: invalid memory address or nil pointer dereference

The pointer represents the address that points to memory, which causes panic if the pointer to nil is dereferenced.

Interface and nil (highlights)

Nil can only be assigned to variables of the pointer, channel, Func, interface, map, or slice type. If this rule is not followed, panic is raised.

At the bottom, interface is implemented as two members, one type and one value

Look, there's a clear official statement here.

At the bottom, interface is implemented as two members: a type and a value. The value is called the dynamic value of the interface, which is an arbitrary concrete value, and the type of the interface is the type of the value. For an int value of 3, an interface value is schematically inclusive (int, 3).

Only if the internal values and types are not set (nil, nil), the value of an interface is nil. In particular, a nil interface will always have a nil type. If we store a pointer of type *int in an interface value, the inner type will be int, regardless of the value of the pointer: (int, nil). Therefore, such an interface value is non-nil, even if it is nil inside the pointer.

Let's see what interface is. will use reflection, about the reflection of the article you can come down to study, but also refer to this article

Reflection article explanation

package mainimport (    "fmt"    "reflect")func main() {    var val interface{} = int64(58)    fmt.Println(reflect.TypeOf(val)) // int64    val = 50    fmt.Println(reflect.TypeOf(val)) // int}

In the example above, the first print statement output is: Int64. This is because the data that has been shown for type Int64 is assigned to the variable Val of type interface, so the underlying structure of Val should be: (Int64, 58).

For the moment, we'll describe it in this binary way, the first member of the two-tuple is type, and the second member is data. The second PRINT statement outputs: Int. This is because the literal integer in the Golang default type is int, so this time the underlying structure of Val becomes: (int, 50).

Take a look at the following code:

Package Mainimport ("FMT" "reflect") type myerror struct {Name string}func (e *myerror) Error () string {Retu                          RN "A"}func main () {//nil can only be assigned to pointers, channel, Func, interface, map or slice type variables (non-basic type) Otherwise the panic Var a *myerror will be thrown Here is not the interface type = = But a value of nil for the pointer variable a FMT. Printf ("%+v\n", reflect. TypeOf (a))//*main. Myerror FMT. Printf ("% #v \ n", reflect. ValueOf (a))//A = (*main. Myerror) (nil) fmt. Printf ("%p% #v \ n", &a, a)//0xc42000c028 (*main. Myerror) (nil) I: = reflect. ValueOf (a) fmt. Println (I.isnil ())//true if a = = nil {fmt. Println ("a = = nil")//A = = nil} else {fmt. PRINTLN ("A! = nil")} FMT. Println ("A Error ():", A.error ())//a Why A is nil can also invoke the method? (The value of the pointer type is nil and the method can be called!) However, you cannot assign a value operation! below:)//A.name = "1"//panic:runtime Error:invalid memory address or nil pointer dereference var b erro R = A//Why A for nil gave B and b! = Nil??? = = error is a type interface, type = *a.myerroR data = Nil FMT. Printf ("%+v\n", reflect. TypeOf (b))//type = *main. Myerror FMT. Printf ("%+v\n", reflect. ValueOf (b))//data = = Nil if b = = nil {fmt. Println ("b = = nil")} else {fmt. PRINTLN ("B! = nil")} FMT. Println ("B Error ():", B.error ())//A}

1. First A is a variable pointer, (note that a is not interface) The variable pointer is only declared, but does not point to any address, so a = = Nil

2. The value of the pointer type is nil, can also call the method, but cannot be assigned operation, otherwise it will cause panic

3. var b error = A, at this point B is a interface, that should be satisfied with the above mentioned interface and nil relationship, that is, only if its type and data are nil only = nil! (b There are types for *main. Myerror) So finally there will be b! = Nil

3. Let's look at an example of error.

Sometimes you want to customize an error-returning function to do this, and you might write the following code:

package main     import (      "fmt"  )     type data struct{}     func (this *data) Error() string { return "" }     func test() error {      var p *data = nil      return p  }     func main() {      var e error = test()      if e == nil {          fmt.Println("e is nil")      } else {          fmt.Println("e is not nil")   //  e is not nil    }  }  

Analysis:

Error is an interface type, the pointer returned in the test method, p, although the data is nil, but because it is returned as a wrapper error type, that is, it is of type. So its underlying structure should be (*data, nil), obviously it is non-nil. You can print and observe the underlying structure data:

package mainimport (    "fmt"    "unsafe")type data struct{}func (*data) Error() string { return "" }func test() error {    var p *data = nil // (*data, nil)    return p}type aa struct {    itab uintptr    data uintptr}func main() {    var e error = test()    d := (*aa)(unsafe.Pointer(&e))    dd := (*struct {        itab uintptr        data uintptr    })(unsafe.Pointer(&e))    fmt.Println(d)          // &{17636960 0}    fmt.Printf("%+v\n", d)  // &{itab:17644608 data:0}    fmt.Printf("%#v\n", d)  // &main.aa{itab:0x10d3e00, data:0x0}    fmt.Printf("%#v\n", dd) // &struct { itab uintptr; data uintptr }{itab:0x10d3ca0, data:0x0}}

The right approach should be:

 package Main import ("FMT") type Data struct{} func (this *data) Error () string          {return "} func bad () bool {return true} Func Test () error {var p *data = Nil If bad () {          Return P} return nil//Direct throw Nil} func main () {var e error = Test () if E = = Nil { Fmt. Println ("E is nil")} else {fmt. Println ("E is not nil")}}  
Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.