go language interface {} fallibility point

A, interface description

    If goroutine and channel are the two cornerstones go concurrent language, and that language interface is go abstract type of key. In a real project, almost all of the data structures are the lowest level interface type. Speaking of the C ++ language, we can immediately think of three terms: encapsulation, inheritance, polymorphism. Although there is no language objects go in the strict sense, but through the interface, can be said to achieve polymorphism. (The characteristics realized in a combination of the structure of the package, inheritance)

    language support will go method, struct, struct members is defined as the interface type, use struct give a simple chestnuts

 1 package main
 2 
 3 type animal interface {
 4     Move()
 5 }
 6 
 7 type bird struct{}
 8 
 9 func (self *bird) Move() {
10     println("bird move")
11 }
12 
13 type beast struct{}
14 
15 func (self *beast) Move() {
16     println("beast move")
17 }
18 
19 func animalMove(v animal) {
20     v.Move()
21 }
22 
23 func main() {
24     var a *bird
25     var b *beast
26     animalMove(a) // bird move
27     animalMove(b) // beast move
28 }

 

    Go use language interface characteristics, will be able to achieve polymorphism, a generic programming.

Two, interface principle

   If you do not fully understand the nature of the interface, the direct use, it will eventually step on a deep pit, it should first understand the use, take a look at the source code interface

 1 type eface struct {
 2     _type *_type
 3     data  unsafe.Pointer
 4 }
 5  
 6 type _type struct {
 7     size       uintptr // type size
 8     ptrdata    uintptr // size of memory prefix holding all pointers
 9     hash       uint32  // hash of type; avoids computation in hash tables
10     tflag      tflag   // extra type information flags
11     align      uint8   // alignment of variable with this type
12     fieldalign uint8   // alignment of struct field with this type
13     kind       uint8   // enumeration for C
14     alg        *typeAlg  // algorithm table
15     gcdata    *byte    // garbage collection data
16     str       nameOff  // string form
17     ptrToThis typeOff  // type for pointer to this type, may be zero
18 }

 

    The reason can be seen that variable interface may receive any type of variable, because its essence is an object, and the record pointer data blocks and their types. (In fact the source code interface also includes the structure and function of the distribution of memory, because it is not the focus of this article, interested students can inform themselves about)

Three, interface sentenced empty pit

    For an empty object, we tend to pass if v nil == conditional statement to determine whether it is empty, but filled in the code with the case of interface types, are often empty sentence is not what we want (in fact, understand or smart students from the essence of the above-mentioned interface is object already knew what I wanted to say)

 1 package main
 2 
 3 type animal interface {
 4     Move()
 5 }
 6 
 7 type bird struct{}
 8 
 9 func (self *bird) Move() {
10     println("bird move")
11 }
12 
13 type beast struct{}
14 
15 func (self *beast) Move() {
16     println("beast move")
17 }
18 
19 func animalMove(v animal) {
20     if v == nil {
21         println("nil animal")
22     }
23     v.Move()
24 }
25 
26 func main() {
27     var a *bird   // nil
28     var b *beast  // nil
29     animalMove(a) // bird move
30     animalMove(b) // beast move
31 }

 

    Or just chestnuts, in fact var a * bird The wording in languages ​​go, just a statement of its type, but did not apply for a space, so this time the nature of a null pointer is pointing to, but we were sentenced empty aminalMove function is a failure, and the following v.Move () call is successful, the reason is because the interface is the essence of an object to perform this function call, the bird will be null pointer of type implicit conversion, convert interface animal object instance, so this time v is not really empty, but its data variables pointing to the blank. This time looking at the implementation of all normal, it will stumble pit under what circumstances we do? Only need to add a piece of code

 1 package main
 2 
 3 type animal interface {
 4     Move()
 5 }
 6 
 7 type bird struct {
 8     name string
 9 }
10 
11 func (self *bird) Move() {
12     println("bird move %s", self.name) // panic
13 }
14 
15 type beast struct {
16     name string
17 }
18 
19 func (self *beast) Move() {
20     println("beast move %s", self.name) // panic
21 }
22 
23 func animalMove(v animal) {
24     if v == nil {
25         println("nil animal")
26     }
27     v.Move()
28 }
29 
30 func main() {
31     var a *bird   // nil
32     var b *beast  // nil
33     animalMove(a) // panic
34     animalMove(b) // panic
35 }

 

    In the code, we added to the derived class name variables, and function calls in the implementation of, panic occurs, this time self is actually nil pointer. So here we came out of the pit. Some people think that this type of error cautious or avoided, it is because we are thinking to go forward on behalf of the interface, but if it is easy to reverse engineer cause of hard to find bug

 1 package main
 2 
 3 type animal interface {
 4     Move()
 5 }
 6 
 7 type bird struct {
 8     name string
 9 }
10 
11 func (self *bird) Move() {
12     println("bird move %s", self.name)
13 }
14 
15 type beast struct {
16     name string
17 }
18 
19 func (self *beast) Move() {
20     println("beast move %s", self.name)
21 }
22 
23 func animalMove(v animal) {
24     if v == nil {
25         println("nil animal")
26     }
27     v.Move()
28 }
29 
30 func getBirdAnimal(name string) *bird {
31     if name != "" {
32         return &bird{name: name}
33     }
34     return nil
35 }
36 
37 func main() {
38     var a animal
39     var b animal
40     a = getBirdAnimal("big bird")
41     b = getBirdAnimal("") // return interface{data:nil}
42     animalMove(a) // bird move big bird
43     animalMove(b) // panic
44 }

 

    Here we see the pointer returned by the function type instance, when the return nil, because the variable is received by the interface type, it has been implicitly converted again leads to panic (difficult to find this kind of inverse conversion).

    How do we deal with such issues above it. My side finishing three points

    1, to fully understand the principles of interface, the course requires caution

    2, used with caution generic programming interfaces used to receive variables, which also needs to ensure that the interface returns to the interface type, the type of example and should not be

    3, it is determined null and is a reflection typeOf valueOf converted into an empty instance of the object and then arbitrates

 

Guess you like

Origin www.cnblogs.com/novice-dxx/p/11938952.html