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,testInterfaceWe’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 ~