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)
posted @   左扬  阅读(917)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
levels of contents
点击右上角即可分享
微信分享提示