define

  • Interface is a collection of defined method signatures that specify the behavior of an object. If an object implements the behavior defined by the set of methods in Interface, it implements the Interface.

  • These methods can be implemented by different objects in different places, and these implementations can have different behaviors;

  • The main job of an interface is simply to provide method name signatures, input parameters, and return types. Methods are ultimately implemented by concrete objects, such as structs;

  • Interface initializes to nil;

  • The type keyword is used for this declaration, interface represents the type, and curly braces define the set of method signatures for the interface.

    type Animal interface {
    	Bark() string
    	Walk() string
    }
    Copy the code

    As follows, Dog implements the Animal interface, so you can use an instance of Animal to receive an instance of Dog. You must implement both Bark() and Walk(), otherwise you are not implementing the Animal interface.

    type Dog struct {
    	name string
    }
    
    func (dog Dog) Bark() string {
    	fmt.Println(dog.name + ":wan wan wan!")
    	return "wan wan wan"
    }
    
    func (dog Dog) Walk() string {
    	fmt.Println(dog.name + ":walk to park!")
    	return "walk to park"
    }
    
    func main() {
    	var animal Animal
    
    	fmt.Println("animal value is:", animal)	//animal value is: <nil>
    	fmt.Printf("animal type is: %T\n", animal) //animal type is: <nil>
    
    	animal = Dog{"Prosperous wealth."} animal.Bark() // Bark :wan Wan wan! Animal.Walk() // Walk to park! fmt.Println("animal value is:", animal) //animal value is: {FMT.Printf("animal type is: %T\n", animal) //animal type is: main.Dog
    }
    Copy the code

nil interface

In the example above, we print the animal we just defined:

  • The value is nil
  • The type also is nil

Interface values with nil underlying values:

  • I’m just going to say that interfaces that aren’t assigned are nil interface, value and type are nil
  • As long as you assign, even if you assign a value of type nil, it’s no longer a nil interface
type I interface {
	Hello()
}

type S []int

func (i S) Hello() {
	fmt.Println("hello")
}
func main() {
	var i I
	fmt.Printf("1:i Type:%T\n", i)
	fmt.Printf("2:i Value:%v\n", i)

	var s S
	if s == nil {
		fmt.Printf("3:s Value%v\n", s)
		fmt.Printf("4:s Type is %T\n", s)
	}

	i = s
	if i == nil {
		fmt.Println("5:i is nil")}else {
		fmt.Printf("6:i Type:%T\n", i)
		fmt.Printf("7:i Value:%v\n", i)
	}
}
Copy the code

output:

	1:i Type:<nil>
	2:i Value:<nil>
	3:s Value[]
	4:s Type is main.S
	6:i Type:main.S
	7:i Value:[]
Copy the code

According to the result, the initialized variable I is a nil interface. When I is assigned to the variable S with a value of nil, I is no longer nil interface. Those of you who are careful will notice a detail in line 3 of the output

3:s Value[]
Copy the code

The value of s is nil, but the output is a []. This is because FMT uses reflection to determine what to print. Since S is of type slice, FMT is represented by [].

empty interface

Go allows interfaces without any methods. This type of interface is called an Empty Interface. All types implement empty Interface, because any type implements at least 0 methods. A typical application scenario is the FMT package Println method, which can receive various types of data and output to the console, thanks to interface{}. Let’s take a look at the case:

func Print(i interface{}) {
	fmt.Println(i)
}
func main() {
	var i interface{}
	i = "hello"Print(I) I = 100 Print(I) I = 1.29 Print(I)}Copy the code

Print (interface{}) accepts string,int,float, etc. Slice of type interface{} can accept any type of slice, although interface{} can accept any type of slice. The following code will trigger a Panic error,

var dataSlice []int = foo()
var interfaceSlice []interface{} = dataSlice
// cannot use dataSlice (type []int) as type []interface { } in assignment
Copy the code

For specific reasons, the official website wiki(github.com/golang/go/w…) Errors are caused by two things:

  • []interface{} is not an interface, it is a slice, only the elements in the slice are interfaces
  • The memory sizeof the []interface{} type is determined at compile time (N*2), while the sizeof the other slice types is N* sizeof(MyType), so it is not quick to assign the type []MyType to []interface{}.

Determine which type is stored in the interface variable

An interface can be implemented with multiple types. Sometimes we need to distinguish which type of value the interface variable stores. Type assertions provide access to the underlying concrete value of an interface value

t := i.(T)
Copy the code

This statement asserts that the interface value I holds the concrete type T and assigns the base value of T to the variable T. If I stores a value other than type T, a panic error will be triggered. To avoid panic errors, you can do the following for assertion checking

t, ok := i.(T)
Copy the code

Assertion succeeds, ok has a value of true, t has a zero value of type T for assertion failure, and no panic error occurs.

func main() {
	var i interface{}
	i = "hello"

	s := i.(string)
	fmt.Println(s)

	s, ok := i.(string)
	fmt.Println(s, ok)

	f, ok := i.(float64)
	fmt.Println(f, ok)

	i = 100
	t, ok := i.(int)
	fmt.Println(t, ok)

	t2 := i.(string) //panic
	fmt.Println(t2)
}
Copy the code

Type switch

Another convenient way to determine the specific type of interface variable is to use the switch statement. As follows:

func Print(i interface{}) {
	switch i.(type) {
	case string:
		fmt.Printf("type is string,value is:%v\n", i.(string))
	case float64:
		fmt.Printf("type is float32,value is:%v\n", i.(float64))
	case int:
		fmt.Printf("type is int,value is:%v\n", i.(int))
	}
}
func main() {
	var i interface{}
	i = "hello"Print(I) I = 100 Print(I) I = 1.29 Print(I)}Copy the code

The flexible and efficient interface dynamic typing enables the Go language to safely and flexibly convert between different compatible types while maintaining the safety and efficiency of strong static typing

Originally posted on my Github

reference

Golang print nil

InterfaceSlice