go语言接口类型如何转换


这篇文章主要介绍“go语言接口类型如何转换”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“go语言接口类型如何转换”文章能帮助大家解决问题。 go语言可利用类型断言来进行接口类型。在Go中,无论是将一个接口类型转换成另一个接口类型,还是将一个接口转换为另一个基本类型,都必须需要使用 类型断言;转换语法有两种“转换后的变量 := 接口变量.(目标类型)”和“转换后的变量 , ok := 接口变量.(目标类型)”。在 Golang 中,将一个 接口 类型转换成另一个接口 类型,或者将一个接口转换为另一个基本类型,都必须需要使用 类型断言类型断言的格式类型断言是一个使用在接口值上的操作。语法上它看起来像 i.(T) 被称为断言类型,这里 i 表示一个接口的类型和 T 表示一个类型。一个类型断言检查它操作对象的动态类型是否和断言的类型匹配。类型断言的基本格式如下:

t:=i.(T)

其中,i 代表接口变量,T 代表转换的目标类型,t 代表转换后的变量。这里有两种可能。第一种,如果断言的类型 T 是一个具体类型,然后类型断言检查 i 的动态类型是否和 T 相同。如果这个检查成功了,类型断言的结果是 i 的动态值,当然它的类型是 T。换句话说,具体类型的类型断言从它的操作对象中获得具体的值。如果检查失败,接下来这个操作会抛出 panic。例如:

varwio.Writer
w=os.Stdout
f:=w.(*os.File)//成功:f==os.Stdout
c:=w.(*bytes.Buffer)//死机:接口保存*os.file,而不是*bytes.buffer

第二种,如果相反断言的类型 T 是一个接口类型,然后类型断言检查是否 i 的动态类型满足 T。如果这个检查成功了,动态值没有获取到;这个结果仍然是一个有相同类型和值部分的接口值,但是结果有类型 T。换句话说,对一个接口类型的类型断言改变了类型的表述方式,改变了可以获取的方法集合(通常更大),但是它保护了接口值内部的动态类型和值的部分。在下面的第一个类型断言后,w 和 rw 都持有 os.Stdout 因此它们每个有一个动态类型 *os.File,但是变量 w 是一个 io.Writer 类型只对外公开出文件的 Write 方法,然而 rw 变量也只公开它的 Read 方法。

varwio.Writer
w=os.Stdout
rw:=w.(io.ReadWriter)//成功:*os.file具有读写功能
w=new(ByteCounter)
rw=w.(io.ReadWriter)//死机:*字节计数器没有读取方法

如果断言操作的对象是一个 nil 接口值,那么不论被断言的类型是什么这个类型断言都会失败。几乎不需要对一个更少限制性的接口类型(更少的方法集合)做断言,因为它表现的就像赋值操作一样,除了对于 nil 接口值的情况。如果 i 没有完全实现 T 接口的方法,这个语句将会触发宕机。触发宕机不是很友好,因此上面的语句还有一种写法:

t,ok:=i.(T)

这种写法下,如果发生接口未实现时,将会把 ok 置为 false,t 置为 T 类型的 0 值。正常实现时,ok 为 true。这里 ok 可以被认为是:i 接口是否实现 T 类型的结果。将接口转换为其他接口实现某个接口的类型同时实现了另外一个接口,此时可以在两个接口间转换。鸟和猪具有不同的特性,鸟可以飞,猪不能飞,但两种动物都可以行走。如果使用结构体实现鸟和猪,让它们具备自己特性的 Fly() 和 Walk() 方法就让鸟和猪各自实现了飞行动物接口(Flyer)和行走动物接口(Walker)。将鸟和猪的实例创建后,被保存到 interface{} 类型的 map 中。interface{} 类型表示空接口,意思就是这种接口可以保存为任意类型。对保存有鸟或猪的实例的 interface{} 变量进行断言免费云主机域名操作,如果断言对象是断言指定的类型,则返回转换为断言对象类型的接口;如果不是指定的断言类型时,断言的第二个参数将返回 false。例如下面的代码:

varobjinterface=new(bird)
f,isFlyer:=obj.(Flyer)

代码中,new(bird) 产生 *bird 类型的 bird 实例,这个实例被保存在 interface{} 类型的 obj 变量中。使用 obj.(Flyer) 类型断言,将 obj 转换为 Flyer 接口。f 为转换成功时的 Flyer 接口类型,isFlyer 表示是否转换成功,类型就是 bool。下面是详细的代码(代码1):

packagemain
import"fmt"
//定义飞行动物接口
typeFlyerinterface{
Fly()
}
//定义行走动物接口
typeWalkerinterface{
Walk()
}
//定义鸟类
typebirdstruct{
}
//实现飞行动物接口
func(b*bird)Fly(){
fmt.Println("bird:fly")
}
//为鸟添加Walk()方法,实现行走动物接口
func(b*bird)Walk(){
fmt.Println("bird:walk")
}
//定义猪
typepigstruct{
}
//为猪添加Walk()方法,实现行走动物接口
func(p*pig)Walk(){
fmt.Println("pig:walk")
}
funcmain(){
//创建动物的名字到实例的映射
animals:=map[string]interface{}{
"bird":new(bird),
"pig":new(pig),
}
//遍历映射
forname,obj:=rangeanimals{
//判断对象是否为飞行动物
f,isFlyer:=obj.(Flyer)
//判断对象是否为行走动物
w,isWalker:=obj.(Walker)
fmt.Printf("name:%sisFlyer:%visWalker:%vn",name,isFlyer,isWalker)
//如果是飞行动物则调用飞行动物接口
ifisFlyer{
f.Fly()
}
//如果是行走动物则调用行走动物接口
ifisWalker{
w.Walk()
}
}
}

代码说明如下:第 6 行定义了飞行动物的接口。第 11 行定义了行走动物的接口。第 16 和 30 行分别定义了鸟和猪两个对象,并分别实现了飞行动物和行走动物接口。第 41 行是一个 map,映射对象名字和对象实例,实例是鸟和猪。第 47 行开始遍历 map,obj 为 interface{} 接口类型。第 50 行中,使用类型断言获得 f,类型为 Flyer 及 isFlyer 的断言成功的判定。第 52 行中,使用类型断言获得 w,类型为 Walker 及 isWalker 的断言成功的判定。第 57 和 62 行,根据飞行动物和行走动物两者是否断言成功,调用其接口。代码输出如下:将接口转换为其他类型在代码 1 中,可以实现将接口转换为普通的指针类型。例如将 Walker 接口转换为 *pig 类型,请参考下面的代码:

p1:=new(pig)
varaWalker=p1
p2:=a.(*pig)
fmt.Printf("p1=%pp2=%p",p1,p2)

对代码的说明如下:第 3 行,由于 pig 实现了 Walker 接口,因此可以被隐式转换为 Walker 接口类型保存于 a 中。第 4 行,由于 a 中保存的本来就是 *pig 本体,因此可以转换为 *pig 类型。第 6 行,对比发现,p1 和 p2 指针是相同的。如果尝试将上面这段代码中的 Walker 类型的 a 转换为 *bird 类型,将会发出运行时错误,请参考下面的代码:

p1:=new(pig)
varaWalker=p1
p2:=a.(*bird)

运行时报错:

panic:interfaceconversion:main.Walkeris*main.pig,not*main.bird

报错意思是:接口转换时,main.Walker 接口的内部保存的是 *main.pig,而不是 *main.bird。因此,接口在转换为其他类型时,接口内保存的实例对应的类型指针,必须是要转换的对应的类型指针。关于“go语言接口类型如何转换”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识,可以关注百云主机行业资讯频道,小编每天都会为大家更新不同的知识点。

相关推荐: javascript有返回值吗

本篇内容主要讲解“javascript有返回值吗”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“javascript有返回值吗”吧! JavaScript有返回值,分为两种类型:return语句设置的值和“undef…

免责声明:本站发布的图片视频文字,以转载和分享为主,文章观点不代表本站立场,本站不承担相关法律责任;如果涉及侵权请联系邮箱:360163164@qq.com举报,并提供相关证据,经查实将立刻删除涉嫌侵权内容。

(0)
打赏 微信扫一扫 微信扫一扫
上一篇 03/07 18:35
下一篇 03/07 18:42

相关推荐