Empty interface
define
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 test interface {
}
Copy the code
Each interface contains two properties, a value and a type.
Var I interface {} FMT. Printf (" type: % T - value: % v \ n ", I, I) / / type: < nil > - value: < nil >Copy the code
So both of these are nil for an empty interface
Usage scenarios
First, we usually declare an instance directly using interface{} as a type, and this instance can hold any type of value.
Func main() {var I interface{} I = 100 ftt.println (I) //100 I = "yif" ftt.println (I) //yif I = 3.14 ftt.println (I) //3.14 I = false fmt.println (I)Copy the code
Second, if you want your function to accept any type of value, you can also use a null interface. The following codes are printed normally:
Func main() {I := 100 s := "yif" f := 3.14 test(I) test(s) test(f)} func test(I interface{}) {ftt.println (I)}Copy the code
It’s a little tricky to write above, but you can use mutable functions. As follows:
Func main() {I := 100 s := "yif" f := 3.14 test(I, s, f)} func main() {I := 100 s := "yif" f := 3.14 test(I, s, f)} For k, v := range res {FMT.Println(k, v)}}Copy the code
Results:
D: workspace\go\ SRC \test>go run main.go [100 yif 3.14] 0 100 1 yif 2 3.14Copy 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
func main() { sli := make([]interface{}, 4) sli[0] = 100 sli[1] = "yif" sli[2] = []int{1, 2, 3} sli[3] = [...] int{5, 6, 7} fmt.Println(sli) for k, v := range sli { fmt.Println(k, v) } }Copy the code
Results:
D:\workspace\go\src\test>go run main.go
[100 yif [1 2 3] [5 6 7]]
0 100
1 yif
2 [1 2 3]
3 [5 6 7]
Copy the code
Empty interface several pits to note
** First, an empty interface can carry any value, but it does not mean that any type can carry a value of an empty interface type
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.
var i interface{} = 100
var t int = i // cannot use i (type interface {}) as type int in assignment: need type assertion
Copy the code
But if you use short variable declarations, that’s fine:
var i interface{} = 100
t := i
fmt.Println(t) //100
Copy the code
Because the compiler does the initialization by deriving the type of the variable from the value to the right of the equals sign.
** The object can no longer be sliced when the empty interface carries the array and slice
sli := []int{1, 2, 3, 4}
var i interface{}
i = sli
fmt.Println(i[1:2]) //cannot slice i (type interface {})
Copy the code
Types of assertions
Type Assertion is an operation used on an interface value to check whether the value held by an interface Type variable implements the desired interface or specific Type
Type assertion, which can only be asserted on objects with statically typed empty interfaces (interface{}), otherwise an error will be thrown
Two syntax for type assertion in Go
The first syntactic format for type assertions in Go is as follows:
t := i.(T)
Copy the code
This expression can assert that an interface object (I) is not nil, and that the interface object (I) stores a value of type T. If the assertion succeeds, the value will be returned to T, and if the assertion fails, panic will occur.
func main() {
var i interface{} = 100
t := i.(int)
fmt.Println(t) //100
fmt.Println("------------------------------------")
s := i.(string)
fmt.Println(s)
}
Copy the code
Result [failed to execute the second assertion and triggered panic] :
D:\workspace\go\src\test>go run main.go
100
------------------------------------
panic: interface conversion: interface {} is int, not string
goroutine 1 [running]:
main.main()
D:/workspace/go/src/test/main.go:32 +0x10e
exit status 2
Copy the code
If the interface value being asserted is nil, let’s see if panic is triggered as expected
var i interface{}
var _ = i.(interface{})
Copy the code
Results:
D:\workspace\go\src\test>go run main.go
panic: interface conversion: interface is nil, not interface {}
goroutine 1 [running]:
main.main()
D:/workspace/go/src/test/main.go:27 +0x34
exit status 2
Copy the code
Another syntax format for type assertions in the Go language is as follows:
t, ok:= i.(T)
Copy the code
As above, this expression can also assert that an interface object (I) is not nil, and that the interface object (I) stores a value of type T. If the assertion succeeds, the type is returned to T, and ok is true, indicating success.
If the interface value is of a type other than T, the assertion fails, but unlike the first expression, this does not trigger panic. Instead, it sets ok to false, indicating that the assertion fails, where T is zero for T.
Func main () {var I interface {} = 10 t1, ok: i. = (int), FMT) Printf (" % d - % t \ n ", t1, ok) FMT. Println (" = = = = = separation line 1 = = = = = ") t2, Ok: i. = (string) FMT) Printf (" % s \ n - % t, "t2, ok) FMT. Println (" = = = = = = = = = = separation line 2") interface var k {} / / nil t3, K. (interface ok: = {}) FMT. Println (t3, "-", ok) FMT. Println (" = = = = = separation line 3 = = = = = ") k = 10 t4, ok := k.(interface{}) fmt.Printf("%d-%t\n", t4, ok) t5, ok := k.(int) fmt.Printf("%d-%t\n", t5, ok) }Copy the code
The second assertion failed, but did not trigger panic:
D: \ workspace \ go \ SRC \ test > go run. Main go 10 - true = = = = = separation line 1 = = = = = = = = = = - false separation line 2 = = = = = < nil > - false = = = = = separation line 3 = = = = = 10-true 10-trueCopy the code
The output of the second assertion before -false does not output any value of t2, but because the assertion failed, t2 gets a string of zero, which is zero length, so you can’t see its output.
Type assertions work with the Switch
If you need to distinguish between multiple types, you can use type Switch assertions.
Func main() {test(100) test("yif") test(3.14) var I interface{} //nil test(I) test(nil)} func test(I interface{}) { Switch r := I.(type) {case int: FMT.Println(r, "is int ") case String: FMT.Println(r," is string ") case nil: Println(r, "nil") default: Println(" no result! ") )}}Copy the code
Results:
D: workspace\go\ SRC \test>go run main. <nil> is nil. <nil> is nilCopy the code