1. What is an empty interface?

An empty interface is a special form of interface type. Normal interfaces have methods, but empty interfaces do not define any method ports. Therefore, we can say that all types implement at least an empty interface.

type empty_iface interface {
}
Copy the code

Each interface contains two properties, a value and a type.

For an empty interface, both are nil, so you can use FMT to verify that

package main

import (
    "fmt"
)

func main() {
    var i interface{}
    fmt.Printf("type: %T, value: %v", i, i)
}
Copy the code

The output is as follows

type: <nil>, value: <nil>
Copy the code

2. How to use empty interfaces?

First, we usually declare an instance directly using interface{} as a type, and this instance can hold any type of value.

Package main import (" FMT ") func main() {var I interface{} I = 1 fmt.println (I) // Println(I) = false Println(I)}Copy the code

Second, if you want your function to accept any type of value, you can also use a null interface

Accepts an example value of any type

package main

import (
    "fmt"
)

func myfunc(iface interface{}){
    fmt.Println(iface)
}

func main()  {
    a := 10
    b := "hello"
    c := true

    myfunc(a)
    myfunc(b)
    myfunc(c)
}
Copy the code

Accepts any sample value of any type

package main import ( "fmt" ) func myfunc(ifaces ... interface{}){ for _,iface := range ifaces{ fmt.Println(iface) } } func main() { a := 10 b := "hello" c := true myfunc(a,  b, c) }Copy the code

Third, you can also define an array that accepts any type of array, slice, map, or strcut. For example, define a slice here

package main

import "fmt"

func main() {
    any := make([]interface{}, 5)
    any[0] = 11
    any[1] = "hello world"
    any[2] = []int{11, 22, 33, 44}
    for _, value := range any {
        fmt.Println(value)
    }
}
Copy the code

3. Empty interface several pits to be noted

Pit 1: An empty interface can carry any value, but does not mean that any type can carry a value of an empty interface type

From an implementation point of view, any type of value satisfies a null interface. So a null interface type can hold any value, or it can fetch the original value from the null interface.

However, if you assign an object of an empty interface type to an object of fixed type (such as int, string, etc.), an error will be reported.

Package main func main() {// declare a variable, type int, initial value 1 var a int = 1 Var I interface{} = a var I interface{} = a var b int = I}Copy the code

This error is just like the things that can be put into the luggage box can definitely be put into the container, but conversely, the things that can be put into the container can not necessarily be put into the luggage box. In Go, such reverse operation is directly prohibited. (Disclaimer: There must be more to the underlying principles, but this explanation may be easier for beginners to understand.)

.\main.go:11:6: cannot use i (type interface {}) as type int in assignment: need type assertion
Copy the code

Pit 2: : The object cannot be sliced when the empty interface is carrying arrays and slices

package main

import "fmt"

func main() {
    sli := []int{2, 3, 5, 7, 11, 13}

    var i interface{}
    i = sli

    g := i[1:3]
    fmt.Println(g)
}
Copy the code

An error occurs during execution.

.\main.go:11:8: cannot slice i (type interface {})
Copy the code

Pit 3: When you use an empty interface to receive arguments of any type, its static type is interface{}, but its dynamic type (whether int, string, or some other type) is unknown, so type assertion is required.

package main import ( "fmt" ) func myfunc(i interface{}) { switch i.(type) { case int: FMT.Println(" Parameter type is int") Case String: Println(" argument type is string")}} func main() {a := 10 b := "hello" myfunc(a) myfunc(b)}Copy the code

The output is as follows

The parameter is of type int and the parameter is of type stringCopy the code