Golang accumulation-interface pointers and struct pointers

Source: Internet
Author: User
This is a creation in Article, where the information may have evolved or changed.

The friends who have developed for go are familiar with interface. These days on the Internet to see an article, talked about the interface and Nil award and so on. The question is a good question, and we will learn more about it.

The original question is as follows:

Nil interface is not an interface with nil pointers

typeinterface {  Meow()}typestruct {}func (*Tabby) Meow() { fmt.Println("meow") }func GetACat() Cat {  varnil  // Oops, we forgot to set myTabby to a real value  return myTabby}func TestGetACat(t *testing.T) {  ifnil {    t.Errorf("Forgot to return a real cat!")  }}

There is no doubt that the output is empty. That is to say, the value returned by the Getacat () method is not nil. The answer is "return a pointer to a null pointer". To tell the truth, I really did not read!

The official definition of interface

In the official FAQ, interface's judgment on nil was described: the original

    • Interface's internal implementation, there are two very core elements, that is the type and value.
    • Interface==nil, only if type, value are nil, i.e. (Nil,nil). Many times, the type has values, and value==nil, such as the above question.
    • In actual development, there should be no type==nil,value! =nil the situation.
      Therefore, the answer to the original question should be: type pointers are determined for type, but value is still not assigned.

More questions?

Viewed some of the data, there are several puzzles that need to be analyzed individually:
-Is the interface variable a pointer type?
-Can the struct pointer be sentenced to its interface variable?

First, a global interface and the corresponding two implementation classes are defined to facilitate subsequent analysis.

//InterfacetypeCatInterface{Meow ()}//Implementation Class 1typeTabbystruct{}func(*tabby) Meow () {fmt. Println ("Tabby meow") }funcGetniltabbycat () Cat {varMytabby *tabby =Nil    returnMytabby}funcGettabbycat () Cat {varMytabby *tabby = &tabby{}returnMytabby}//Implementation Class 2typeGafieldstruct{}func(*gafield) Meow () {fmt. Println ("Gafield Meow") }funcGetnilgafieldcat () Cat {varMygafield *gafield =Nil    returnMygafield}funcGetgafieldcat () Cat {varMygafield *gafield = &gafield{}returnMygafield}

is the interface variable a pointer type?
When faced with a type, you can use the typeof of the Reflection package (reflect) to obtain the type, and then call kind to understand the infrastructure category.

    var (        cat2        = GetNilTabbyCat()    )    fmt.Printf("cat1 information: type=%15v,kind=%10v \n",reflect.TypeOf(cat2),reflect.TypeOf(cat2).Kind())

Through the results, we can know thatcat2 is a pointer .
The contract between the interface variables, etc.

var (cat1 Cat =NilCAT2 = Getniltabbycat () Cat3 = Gettabbycat () cat4 = Getnilgafieldcat ()) fmt. Printf ("Cat1 information:nil?:%5v, type=%15v, value=%5v \ n", CAT1 = =Nil, reflect. TypeOf (CAT1), reflect. ValueOf (CAT1))//interface variable,type, value isNil, so cat1==NilFmt. Printf ("Cat2 information:nil?:%5v, type=%15v, type.kind=%5v, value=%5v \ n", Cat2 = =Nil, reflect. TypeOf (CAT2), reflect. TypeOf (CAT2). Kind (), reflect. ValueOf (CAT2))//interface variable,type!=Nil, so cat2!==NilFmt. Printf ("Cat3 information:nil?:%5v, type=%15v, type.kind=%5v, value=%5v \ n", CAT3 = =Nil, reflect. TypeOf (CAT3), reflect. TypeOf (CAT3). Kind (), reflect. ValueOf (CAT3))//interface variable,type!=Nil, so cat3!=NilFmt. Printf ("Cat4 information:nil?:%5v, type=%15v, type.kind=%5v, value=%5v \ n", CAT4 = =Nil, reflect. TypeOf (CAT4), reflect. TypeOf (CAT4). Kind (), reflect. ValueOf (CAT4))//interface variable, FMT. Printf ("cat1==cat2?%5v, cat2==cat3?%5v, cat2==cat4?%5v \ n", CAT1 = = Cat2, Cat2 = = Cat3, Cat2 = cat4)//output://CAT1 Information:Nil?:true,type= <Nil, value=<invalid reflect. value>//CAT2 Information:Nil?:false,type= *main. Tabby,type. kind= PTR, value=<Nil>//CAT3 Information:Nil?:false,type= *main. Tabby,type. kind= ptr, value=&{}//cat4 information:Nil?:false,type= *main. Gafield,type. kind= PTR, value=<Nil>//CAT1==CAT2?false, CAT2==CAT3?false, Cat2==cat4?false 

Judging from the running result, the interface variable is to compare the type and value.

    • The type of CAT1 is empty, so cat1!=cat2.
    • Cat2 and CAT3 have different values, so they are not equal.
    • CAT2 is different from the type of CAT4, so it is not equal.
      Further, you can actually use unsafe. Pointer to understand that you can clearly understand the category and value of the CAT2 variable, the code is as follows:
struct {        itype  uintptr        ivalue uintptr    }d1 := (*iface)(unsafe.Pointer(&cat1))d2 := (*iface)(unsafe.Pointer(&cat2))d3 := (*iface)(unsafe.Pointer(&cat3))d4 := (*iface)(unsafe.Pointer(&cat4))fmt.Println(d1)fmt.Println(d2)fmt.Println(d3)fmt.Println(d4)//Output://&{0 0} //&{7024192 0}  //&{7024192 7302976}  //&{7024128 0} 

whether the interface variable can be judged by its struct-body pointer
As you can see from the preceding code, an interface variable is a pointer. Will the interface pointer be the same as the struct pointer?

    typeiface struct {itype uintptr ivalue uintptr} var (cat1 Cat = Getniltabbycat ()//interface pointer CAT2 = Gettabbycat ()//interface pointer cat3 *tabby = &tabby{}//struct pointer) D1: = (*iface) (UNSAFE.P Ointer (&AMP;CAT1)) D2: = (*iface) (unsafe. Pointer (&AMP;CAT2)) D3: = (*iface) (unsafe. Pointer (&AMP;CAT3)) fmt. Printf ("Cat1 information:nil?:%5v, type=%15v, value=%v,%v \ n", CAT1 = =Nil, reflect. TypeOf (CAT1), reflect. ValueOf (CAT1), D1)//interface variable,type, value isNil, so cat1==NilFmt. Printf ("Cat2 information:nil?:%5v, type=%15v, type.kind=%10v, value=%v,%v \ n", CAT1 = =Nil, reflect. TypeOf (CAT2), reflect. TypeOf (CAT2). Kind (), reflect. ValueOf (CAT2), D2)//interface variable,type!=Nil, so cat2!==NilFmt. Printf ("Cat3 information:nil?:%5v, type=%15v, type.kind=%10v, value=%v,%v \ n", CAT3 = =Nil, reflect. TypeOf (CAT3), reflect. TypeOf (CAT3). Kind (), reflect. ValueOf (CAT3), D3)//interface variable,type!=Nil, so cat3!=NilFmt. Printf ("cat1==cat2?:%5v, cat2==cat3?%v \ n", CAT1==CAT2,CAT2==CAT3)//output://CAT1 Information:Nil?:false,type= *main. Tabby, value=<Nil>, &{7024192 0}//CAT2 Information:Nil?:false,type= *main. Tabby,type. kind= ptr, value=&{}, &{7024192 7302976}//CAT3 Information:Nil?:false,type= *main. Tabby,type. kind= ptr, value=&{}, &{7302976 0}//CAT1==CAT2?:false, CAT2==CAT3?true 

As can be seen, the struct pointer can be sentenced with the interface pointer, but note that although the CAT2, Cat3 Ivalue point to a different address, but the comparison is the specific value, so equal.

Simple conclusion:

    The judgment of the
    1. pointer involves both type and value. The contract between the
    2. interface pointers is different, depending on the type and value. The
    3. interface pointer and its corresponding implementation of the struct pointer, can be to be sentenced and other operations.

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.