企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
[TOC] 接口值可能赋值为任意类型的值,那我们如何从接口值获取其存储的具体数据呢? 我们可以借助标准库fmt包的格式化打印获取到接口值的动态类型。示例如下 ```go type Mover interface { Move() } type Cat struct{} func (c Cat) Move() { fmt.Println("狗在跑~") } func main() { var m Mover m = Cat{} fmt.Printf("m type is: %T\n", m) } // 运行结果 // m type is: main.Cat ``` 而fmt包内部其实是使用反射的机制在程序运行时获取到动态类型的名称。关于反射的内容我们会在后续章节详细介绍。 而想要从接口值中获取到对应的实际值需要使用类型断言,其语法格式如下。 ```go 接口变量.(猜测的类型) ``` >[info] **说明**: 该语法返回两个参数,第一个参数是接口变量转化为猜测类型后的变量,第二个值是一个布尔值,若为true则表示断言成功,为false则表示断言失败。 举例说明 ```go func typeAssertion(x interface{}) { // 没了解这种为什么可以使用switch..case语法, 可能是搭配使用的... switch v := x.(type) { case string: fmt.Printf("x is a string is %v\n", v) case int: fmt.Printf("x is a int is %v\n", v) case bool: fmt.Printf("x is a bool is %v\n", v) case Cat: fmt.Printf("x is a Cat is %v\n", v) default: fmt.Println("unsupport type") } } func main() { typeAssertion(1) typeAssertion(string("12.32")) typeAssertion(true) typeAssertion([]string{}) typeAssertion(m) } // 运行结果: // x is a int is 1 // x is a string is 12.32 // x is a bool is true // unsupport type // x is a Cat is {} ``` 由于接口类型变量能够动态存储不同类型值的特点,所以很多初学者会滥用接口类型(特别是空接口)来实现编码过程中的便捷。只有当有两个或两个以上的具体类型必须以相同的方式进行处理时才需要定义接口。切记不要为了使用接口类型而增加不必要的抽象,导致不必要的运行时损耗。 在 Go 语言中接口是一个非常重要的概念和特性,使用接口类型能够实现代码的抽象和解耦,也可以隐藏某个功能的内部实现,但是缺点就是在查看源码的时候,不太方便查找到具体实现接口的类型。