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