Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”
This article has participated in the “Digitalstar Project” and won a creative gift package to challenge the creative incentive money
Interface {} interface{} interface{} interface{} interface{} interface{} interface{} interface{} interface{} interface{} interface{} interface{} interface{} interface{
Interface {} can be used to simulate polymorphism
XDM Let’s write a simple example, let’s take an animal example
Write an Animal interface, similar to Java inside the abstract class, Animal interface has two schemes to be implemented
Write a Cat to inherit from Animal and implement Eat and Drink methods
- Animals all have eating and drinking behavior, cat eating behavior is to eat fish, cat drinking behavior is to drink coke
- Finally, in the main function, we use a pointer to the parent class to point to the address of a subclass instantiated by the subclass
type Animal interface {
Eat(string) string
Drink(string) string
}
type Cat struct{}
func (c *Cat) Eat(food string) string {
iffood ! ="fish" {
return "i dislike"
} else {
return "i like"}}func (c *Cat) Drink(drink string) string {
if drink == "coke" {
return "i love"
}else{
return "abandon"}}func main(a){
var a Animal = &Cat{}
fmt.Println(a.Eat("fish"))
fmt.Println(a.Drink("water"))}Copy the code
Var a Animal = &cat {} var a Animal = &cat {} var a Animal = &cat {} var a Animal = &cat {}
Note here that Animal is itself an interface type, which is itself a pointer
Run the code above to see the effect
# go run main.go
i like
abandon
Copy the code
No problem, the cat love to eat fish, do not love to drink water
Interface {} needs to be aware of empty and non-empty cases
What is an empty interface{} and what is a non-empty interface{}?
Let’s use the above example and add a testInterface function to try it out
func testInterface(a) Animal {
var c *Cat
return c
}
func main(a) {
test := testInterface()
if test == nil {
fmt.Println("test is nil")}else {
fmt.Println("test is not nil")}}Copy the code
Can you guess what the output of the above little case would be
- In theory,
testInterface
We’re just creating a Cat pointer, we’re not assigning it, so it defaults to zero, so it’s going to be anilSo when you return, it should be return nil, so it should be output by the logic of the codetest is nil
After executing the above code, view the results
# go run main.go
test is not nil
Copy the code
See the above results, is not feel very strange, and their expectations are inconsistent
It doesn’t matter, as we mentioned in the previous article, the reason why we feel a technical point is strange and not the effect we expect is that we are not familiar with its principle
Let’s answer the above question first
Empty interface: means an interface with no methods. Interface {} is an eface structure in the source code
Non-empty interface: represents an interface that contains methods. Interface {} is represented as an iface structure in the source code
For now, let’s go directly to structures in the source code
ifaceStructure, not empty
type iface struct {
tab *itab
data unsafe.Pointer
}
type itab struct {
inter *interfacetype
_type *_type
link *itab
hash uint32 // copy of _type.hash. Used for type switches.
bad bool // type does not implement interface
inhash bool // has this itab been added to hash?
unused [2]byte
fun [1]uintptr // variable sized
}
Copy the code
-
tab
Interface {} is an itAB structure that contains key information such as hash values, function Pointers, etc. Interface {} is an itAB structure that contains key information such as hash values, function Pointers, etc
-
data
Specific data information
efaceThe structure of the body
type eface struct {
_type *_type
data unsafe.Pointer
}
Copy the code
type _type struct {
size uintptr // Indicates the size of the type
ptrdata uintptr // The memory size of the prefix pointer
hash uint32 // Computes the hash value of the data
tflag tflag
align uint8 // Memory aligned
fieldalign uint8
kind uint8
alg *typeAlg
gcdata *byte
str nameOff
ptrToThis typeOff
}
Copy the code
- _type
The type information, similar to the non-null interface above, determines how the following data field is interpreted
- data
Specific data information
If XDM is careful, it can be seen that the Animal interface we wrote above is actually a non-empty interface, because it contains methods, so its underlying structure is an iFace structure, non-empty interface
So a null pointer initialized, c, is actually the data field in the iface structure is empty, the data is empty, but the iface structure itself is not empty, so this code is saying test is not nil
So, by the way, what other data structures in Golang are zero compared to nil, and we can look at the source code for that as well
// nil is a predeclared identifier representing the zero value for a
// pointer, channel, func, interface, map, or slice type.
var nil Type // Type must be a pointer, channel, func, interface, map, or slice type
Copy the code
The source code says that you can use nil for Pointers, channels, functions, interfaces, maps, slice types
Ok, this time here, knowledge points to use up just have value
Welcome to like, follow and favorites
Friends, your support and encouragement, I insist on sharing, improve the quality of the power
All right, that’s it for this time
Technology is open, our mentality, should be more open. Embrace change, live in the sun, and strive to move forward.
I am Nezha, welcome to like, see you next time ~