SoFunction
Updated on 2025-03-03

Implementation of Golang empty interface and type assertion

Empty interface

definition

Empty interfaces are special forms of interface types. Ordinary interfaces have methods, while empty interfaces do not define any method ports. Therefore, we can say that all types implement at least empty interfaces.

type test interface {
}

Each interface contains two properties, one is a value and the other is a type.

var i interface{}
("Type: %T----Value: %v\n", i, i) //Type: <nil>----Value: <nil>

It can be seen that for empty interfaces, both are nil

Use scenarios

First, we usually use it directlyinterface{}An instance is declared as a type, and this instance can carry arbitrary type of values.

func main() {
	var i interface{}

	i = 100
	(i) //100

	i = "yif"
	(i) //yif

	i = 3.14
	(i) //3.14

	i = false
	(i) //false
}

second, if you want your function to receive any type of value, you can also use an empty 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{}) {
	(i)
}

The above writing method is a bit troublesome, you can use functions with variable parameters. as follows:

func main() {
	i := 100
	s := "yif"
	f := 3.14

	test(i, s, f)
}

func test(res ...interface{}) {
	(res) //res is sliced	for k, v := range res {
		(k, v)
	}
}

result:

D:\workspace\go\src\test>go run
[100 yif 3.14]
0 100
1 yif
2 3.14 

third, you also define an array, slice, map, and strcut that can receive any type, 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}
	(sli)
	for k, v := range sli {
		(k, v)
	}
}

result:

D:\workspace\go\src\test>go run
[100 yif [1 2 3] [5 6 7]]
0 100
1 yif
2 [1 2 3]
3 [5 6 7] 

Several pitfalls to pay attention to in empty interfaces

**First, **The empty interface can carry any value, but does not mean that any type can bear the value of the empty interface type.

The empty interface type can save any value, or the original value can be taken out from the empty interface.

But if you assign an object of an empty interface type to an object of a 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

But you can use short variable declarations:

var i interface{} = 100
t := i
(t) //100

Because the compiler will deduce the variable type based on the value to the right of the equal sign to complete the initialization.

**Second: **When the empty interface carries the array and slice, the object can no longer be sliced

sli := []int{1, 2, 3, 4}
var i interface{}
i = sli
(i[1:2]) //cannot slice i (type interface {})

Type Assertion

Type Assertion is an operation used on interface values ​​to check whether the value held by an interface type variable implements the expected interface or specific type.

Type assertions, only objects with static type empty interface (interface{}) can be asserted, otherwise an error will be thrown.

Two syntaxes for type assertions in Go

The first syntax format for type assertions in Go is as follows:

t := i.(T)

This expression can assert that an interface object (i) is not nil, and the type of value stored in the interface object (i) is T. If the assertion is successful, the value will be returned to t. If the assertion fails, panic will be triggered.

func main() {
	var i interface{} = 100
	t := i.(int)
	(t) //100
	
	("------------------------------------")

	s := i.(string)
	(s)
}

As a result, [Failed when executing the second assertion and triggered panic]:

D:\workspace\go\src\test>go run
100
------------------------------------
panic: interface conversion: interface {} is int, not string

goroutine 1 [running]:
()
        D:/workspace/go/src/test/:32 +0x10e
exit status 2 

If the interface value to be asserted is nil, then let's see if it will trigger panic as expected

var i interface{}
var _ = i.(interface{})

result:

D:\workspace\go\src\test>go run
panic: interface conversion: interface is nil, not interface {}

goroutine 1 [running]:
()
        D:/workspace/go/src/test/:27 +0x34
exit status 2 

Another syntax format for type assertions in Go is as follows:

t, ok:= i.(T)

Like the above, this expression can also assert that an interface object (i) is not nil, and the type of the value stored in the interface object (i) is T. If the assertion is successful, its type will be returned to t, and the value of ok is true at this time, indicating that the assertion is successful.

If the type of the interface value is not the T we asserted, the assertion will fail, but if something different from the first expression, this will not trigger panic, but set the value of ok to false, indicating that the assertion has failed. At this time, t is the zero value of T.

func main() {
    var i interface{} = 10
    t1, ok := i.(int)
    ("%d-%t\n", t1, ok)

    ("=====Dividing line1=====")

    t2, ok := i.(string)
    ("%s-%t\n", t2, ok)

    ("=====Dividing line2=====")

    var k interface{} // nil
    t3, ok := k.(interface{})
    (t3, "-", ok)

    ("=====Dividing line3=====")
    k = 10
    t4, ok := k.(interface{})
    ("%d-%t\n", t4, ok)

    t5, ok := k.(int)
    ("%d-%t\n", t5, ok)
}

Results [The output after running is as follows. You can find that when executing the second assertion, although it failed, panic was not triggered]:

D:\workspace\go\src\test>go run
10-true
===== Dividing line 1======
-false
===== Dividing line 2======
<nil> - false
===== Dividing line 3======
10-true
10-true 

In the above output, you need to pay attention to the output of the second assertion.-falseBefore, it was not that there was no output of any value of t2, but because the assertion failed, so what t2 got was the zero value of string."", it is zero length, so you can't see its output.

Type assertions are used with switch

If you need to distinguish between multiple types, you can use the type switch assertion.

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:
		(r, "It's an int type")
	case string:
		(r, "Yes string")
	case nil:
		(r, "It's nil")
	default:
		("No result!")
	}
}

result:

D:\workspace\go\src\test>go run
100 is int type
yif is a string
No results!
<nil> is nil
<nil> is nil

This is the end of this article about the implementation of Golang empty interface and type assertions. For more related contents of Golang empty interface and type assertions, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!