Golang类型断言

116 阅读2分钟

系列文章:

golang实现多态

golang利用组合实现继承,和php或java面向对象的继承有何不同

Golang类型断言

golang之interface入门

interface,鸭子类型与泛型


所谓 类型断言(type assertion):

cannot convert a (type interface{}) to type string: need type assertion


直接转换


如果明确知道a的类型,可以直接转换:

package main

import "fmt"

func main() {
	var i interface{}
	i = "cuishuang"
	f(i)
}

func f(a interface{}) string {
	fmt.Println(a)

	return a.(string)
}

则编译通过.


格式为 a.(对应的类型)

但如果"()"里面的类型不对,则会直接panic

package main

import "fmt"

func main() {
	var i interface{}
	i = "cuishuang"
	f(i)
}

func f(a interface{}) string {
	fmt.Println(a.(int))

	return ""
}

输出为:

panic: interface conversion: interface {} is string, not int

goroutine 1 [running]:




OK判别式


如上,如果类型不一致,会直接panic。所以一般在断言时,都要用OK判别式的格式(哪怕只是value, _ := a.(float32),起码这样不会panic了)

如:

package main

import "fmt"

func main() {
	var i interface{}
	i = "cuishuang"
	f(i)
}

func f(a interface{}) string {

	value, _ := a.(float32)

	fmt.Println("value ", value)

	return ""
}

输出为:value 0


而如果:

package main

import "fmt"

func main() {
	var i interface{}
	i = "cuishuang"
	f(i)
}

func f(a interface{}) string {

	value := a.(float32)

	fmt.Println("value ", value)

	return ""
}

则会

panic: interface conversion: interface {} is string, not float32

goroutine 1 [running]:
main.f({0x10071baa0?, 0x10072c748?})
        /Users/fliter/go/src/shuang/interfacee/assert.go:13 +0xb4
main.main()
        /Users/fliter/go/src/shuang/interfacee/assert.go:8 +0x2c
exit status 2

golangci-lint有一个检查项 forcetypeassert,用来强制类型断言,检查interface转换有没有进行类型校验


在断言时进行判断:

  • 如果断言失败,那么ok的值将会是false.

  • 如果断言成功, ok的值将会是true, 同时value就是所期待的正确的值

package main

import "fmt"

func main() {
	var i interface{}
	i = "cuishuang"
	f(i)
}

func f(a interface{}) string {
	value,ok := a.(int)

	if ok {
		fmt.Println(a.(int)) //a.(int) 即 value
		fmt.Println(value)
	} else {
		fmt.Println("i中不是int类型")
	}

	return ""
}

输出为:

i中不是int类型



配合switch语句进行判断


package main

import "fmt"

func main() {
	var i interface{}
	i = "cuishuang"
	f(i)
}

func f(a interface{}) string {

	switch val := a.(type) {
	default:
		fmt.Printf("unexpected type %T", val) // %T prints whatever type t has
		break
	case bool:
		fmt.Printf("boolean: %t\n", val) // t has type bool
		break
	case int:
		fmt.Printf("integer: %d\n", val) // t has type int
		break
	case string:
		fmt.Printf("string: %s\n", val) // t has type string
		break
	case *bool:
		fmt.Printf("pointer to boolean: %t\n", *val) // t has type *bool
		break
	case *int:
		fmt.Printf("pointer to integer: %d\n", *val) // t has type *int

	case *string:
		fmt.Printf("pointer to string: %s\n", *val) // t has type *string
		break

	}

	return ""
}

输出为:

string: cuishuang

参考:

深入Go语言 - 6

golang类型断言的使用(Type Assertion)