Go从门到精通——接口(interface)——在接口和类型间转换
在接口和类型间转换
Go 语言中使用的接口断言(type assertions)将接口转换成另外一个接口,也可以将接口转换为另外的类型。接口的转换在开发中非常常见,使用也非常频繁。
1、类型断言的格式
类型断言的基本格式如下:
1 | t := i.(T) |
- i 代表接口变量。
- T 代表转换的目标类型。
- t 代表转换后的变量。
如果 i 没有完全实现 T 接口的方法,这个语句将会触发宕机。触发宕机不是很友好,因此上面的语句还有另一种写法:
1 | t, ok := i.(T) |
这种写法下,如果发生接口未实现时,将会把 ok 设置为 false,t 设置为 T 类型的 0 值。正常实现时,ok 为 true。这里 ok 可以被认为是: i 接口是否实现 T 类型的结果。
2、将接口转换为其他接口
实现某个接口的类型同时实现了另外一个接口,此时可以在两个接口间转换。
鸟和猪具有不同的特性,鸟可以飞,猪不能飞,但两种动物都可以走。
如果使用结构体实现鸟和猪,让它们具备自己特性的 Fly() 和 Walk() 方法就让鸟和猪各自实现了飞行动物接口(Flyer)和行走动物接口(Walker)。
将鸟和猪的实例创建后,被保存到 interface{} 类型的 map 中。interface{} 类型表示空接口,意思是这种接口可以保存为任意类型。对保存有鸟或猪的实例的 interface{} 变量进行断言操作,如果断言对象是断言指定的类型,则返回转换为断言对象类型的接口;如果不是指定的断言类型时,断言的第二个参数将返回 false。例如下面的代码:
1 2 | var obj interface = new(bird) f, isFlyer := obj.(Flyer) |
代码中, new(bird) 产生 *bird 类型的 bird 实例,这个实例被保存在 interface{} 类型的 obj 变量中。使用 obj.(Flyer) 类型断言,将 obj 转换为 Fly 接口。 f 为转换成功时的 Flyer 接口类型,isFlyer 表示是否转换成功,类型就是 bool。详细代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | package main import "fmt" //定义飞行动物接口 type Flyer interface { Fly() } //定义行走动物接口 type Walker interface { Walk() } //定义鸟类 type bird struct {} //实现飞行动物接口 func (b *bird) Fly() { fmt.Println( "bird: fly" ) } //为鸟添加 Walk() 方法,实现行走动物接口 func (b *bird) Walk() { fmt.Println( "bird: walk" ) } //定义猪 type pig struct {} //为猪定义 Walk() 方法,实现行走动物接口 func (p *pig) Walk() { fmt.Println( "ping: walk" ) } func main() { //创建动物的名字到实例的映射 animals := map [string] interface {}{ "bird" : new(bird), "pig" : new(pig), } //遍历映射 for name, obj := range animals { //判断对象是否为飞行动物 f, isFlyer := obj.(Flyer) //判断对象是否为行走动物接口 w, isWalker := obj.(Walker) fmt.Printf( "name: %s 是飞行动物吗?: %v ,是行走动物吗?: %v\n" , name, isFlyer, isWalker) // 如果是飞行动物则调用飞行动物接口 if isFlyer { f.Fly() } // 如果是行走动物则调用行走动物接口 if isWalker { w.Walk() } } } |
代码运行后输出如下:
1 2 3 4 5 6 7 8 9 10 11 | GOROOT=C:\Program Files\Go #gosetup GOPATH=D:\ go -testfiles #gosetup "C:\Program Files\Go\bin\go.exe" build -o C:\Users\zuoyang\AppData\Local\Temp\GoLand\___1go_build____go.exe D:\ go -testfiles\接口-在接口和类型间转换-鸟和猪. go #gosetup C:\Users\zuoyang\AppData\Local\Temp\GoLand\___1go_build____go.exe name: bird 能飞行动物吗?: true ,是行走动物吗?: true bird: fly bird: walk name: pig 能飞行动物吗?: false ,是行走动物吗?: true ping: walk 进程 已完成,退出代码为 0 |
3、将接口转换为其他类型
上面鸟猪的代码中,可以实现将接口转换Wie普通的指针类型。例如将 Walker 接口转换为 *ping 类型,代码如下:
1 2 3 4 5 6 7 8 9 10 | p1 := new(pig) //由于 pig 实现了 Walker 接口,因此可以被隐式转换为 Walker 接口类型保存于 a 中。 var a Walker = p1 //由于 a 中保存的本来就是 *pig 本体,因此可以转换为 *pig 类型 p2 := a.(*pig) fmt.Printf( "p1=%p p2=%p" , p1, p2) |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具