from:https://blog.csdn.net/qq_26981997/article/details/52608081
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: The nil interface is not an interface with nil pointers type Cat interface {Meow ()}type tabby struct {}func (*tabby) Meow () {fmt. Println ("Meow")}func Getacat () Cat {var mytabby *tabby = nil//Oops, we forgot to set Mytabby to a real value return my Tabby}func testgetacat (t *testing. T) {if getacat () = = Nil {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! Official definition of Interface official in the FAQ, the interface judgment nil is described: the internal implementation of the original interface, there are two very core elements, that is, 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? Looking at 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. Interface type Cat interface {Meow ()}//implements class 1type tabby Struct{}func (*tabby) Meow () {fmt. Println ("tabby meow")}func Getniltabbycat () Cat {var mytabby *tabby = nil return mytabby}func Gettabbycat () cat {var my Tabby *Tabby = &tabby{} return mytabby}//implements Class 2type Gafield Struct{}func (*gafield) Meow () {fmt. Println ("Gafield meow")}func Getnilgafieldcat () Cat {var Mygafield *gafield = nil return mygafield}func Getgafieldcat () Cat {var Mygafield *gafield = &gafield{} return Mygafield} interface variable is 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 ()) 1234 through the results, we can know that CAT2 is a pointer. The contract between the interface variables such as var (cat1 Cat = Nil Cat2 = 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 are nil, so Cat1==nil FMT. 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!==nil fmt. 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!=nil fmt. 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 in Formation:nil?: True, Type=, Value=//cat2 information:nil?:false, type= *main. Tabby, type.kind= ptr, Value=//cat3 information:nil?:false, type= *main. Tabby, type.kind= ptr, value=&{}//cat4 information:nil?:false, type= *main. Gafield, type.kind= ptr, Value=//cat1==cat2?false, Cat2==cat3?false, Cat2==cat4?false Judging from the running results, the interface variables, 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, it is clear to understand the CAT2 variable category and value of the case, the code is as follows: type iface 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} interface variable can be judged by its struct 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? Type iface struct {itype uintptr ivalue uintptr} var (cat1 Cat = Getniltabbycat ()//interface pointer cat2 = GETTABBYCAT ()//interface pointer CA T3 *tabby = &tabby{}//struct pointer) D1: = (*iface) (unsafe. Pointer (&CAT1)) D2: = (*iface) (unsafe. Pointer (&CAT2)) D3: = (*iface) (unsafe. Pointer (&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 are nil, so Cat1==nil FMT. 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!==nil FMT. 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!=nil fmt. Printf ("cat1==cat2?:%5v, cat2==cat3?%v \ n", CAT1==CAT2,CAT2==CAT3)//output://cat1 information:nil?:false, type= * Main. Tabby, value=, &{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 pointer's judgment involves both type and value.
The contract between the interface pointers, depending on the type and value, varies.
interface pointers and their corresponding implementation of the structure of the pointer, can be sentenced and other operations.