博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Go基础系列:接口类型断言和type-switch
阅读量:7078 次
发布时间:2019-06-28

本文共 3376 字,大约阅读时间需要 11 分钟。

接口类型探测:类型断言

接口实例中存储了实现接口的类型实例,类型的实例有两种:值类型实例和指针类型实例。在程序运行过程中,接口实例存储的实例类型可能会动态改变。例如:

// ins是接口实例var ins Shaper// ins存储值类型的实例ins = c1// 一段时间后......// ins存储指针类型的实例,存储的类型发生改变ins = c2// 一段时间后...// ins可能存储另一个类型实例ins = s1

所以,需要一种探测接口实例所存储的是值类型还是指针类型。

探测的方法是:ins.(Type)ins.(*Type)。它们有两个返回值,第二个返回值是ok返回值,布尔类型,第一个返回值是探测出的类型。也可以只有一个返回值:探测出的类型。

// 如果ins保存的是值类型的Type,则输出if t, ok := ins.(Type); ok {    fmt.Printf("%T\n", v)}// 如果ins保存的是指针类型的*Type,则输出if t, ok := ins.(*Type); ok {    fmt.Printf("%T\n", v)}// 一个返回值的探测t := ins.(Type)t := ins.(*Type)

以下是一个例子:

package mainimport "fmt"// Shaper 接口类型type Shaper interface {    Area() float64}// Square struct类型type Square struct {    length float64}// Square类型实现Shaper中的方法Area()func (s Square) Area() float64 {    return s.length * s.length}func main() {    var ins1, ins2 Shaper    // 指针类型的实例    s1 := new(Square)    s1.length = 3.0    ins1 = s1    if v, ok := ins1.(*Square); ok {        fmt.Printf("ins1: %T\n", v)    }    // 值类型的实例    s2 := Square{4.0}    ins2 = s2    if v, ok := ins2.(Square); ok {        fmt.Printf("ins2: %T\n", v)    }}

上面两个Printf都会输出,因为它们的类型判断都返回true。如果将ins2.(Square)改为ins2.(*Square),第二个Printf将不会输出,因为ins2它保存的是值类型的实例。

以下是输出结果:

ins1: *main.Squareins2: main.Square

特别需要注意的是,ins必须明确是接口实例。例如,以下前两种声明是有效的,第三种推断类型是错误的,因为它可能是接口实例,也可能是类型的实例副本。

var ins Shaper     // 正确ins := Shaper(s1)  // 正确ins := s1          // 错误

当ins不能确定是接口实例时,用它来进行测试,例如ins.(Square)将会报错:

invalid type assertion:ins.(Square) (non-interface type (type of ins) on left)

它说明了左边的ins是非接口类型(non-interface type)。

另一方面,通过接口类型断言(ins.(Type)),如果Type是一个接口类型,就可以判断接口实例ins中所保存的类型是否也实现了Type接口。例如:

var r io.Readtty, err := os.OpenFile("/dev/tty", os.O_RDWR, 0)if err != nil {    return nil, err}r = ttyvar w io.Writerw = r.(io.Writer)

上面的r是io.Read接口的一个实例变量,它里面保存的是tty和它的类型,即(tty, *os.File),然后断言r的类型,探测它里面的类型*File是否也实现了io.Writer接口,如果实现了,则保存到io.Writer接口的实例变量w中,这样w实例也将保存(tty,*os.File)

由于任意内容都实现了空接口,所以,总是可以把一个接口实例无需通过任何断言地赋值给一个空接口实例:

var empty interface{}empty = w

现在empty也保存了(tty,*os.File)

type Switch结构

switch流程控制结构还可以用来探测接口实例保存的类型。这种结构称为type-switch

用法如下:

switch v := ins.(type) {case *Square:    fmt.Printf("Type Square %T\n", v)case *Circle:    fmt.Printf("Type Circle %T\n", v)case nil:    fmt.Println("nil value: nothing to check?")default:    fmt.Printf("Unexpected type %T", v)}

其中ins.(type)中的小写type是固定的词语。

以下是一个使用示例:

package mainimport (    "fmt")// Shaper 接口类型type Shaper interface {    Area() float64}// Circle struct类型type Circle struct {    radius float64}// Circle类型实现Shaper中的方法Area()func (c *Circle) Area() float64 {    return 3.14 * c.radius * c.radius}// Square struct类型type Square struct {    length float64}// Square类型实现Shaper中的方法Area()func (s Square) Area() float64 {    return s.length * s.length}func main() {    s1 := &Square{3.3}    whichType(s1)    s2 := Square{3.4}    whichType(s2)    c1 := new(Circle)    c1.radius = 2.3    whichType(c1)}func whichType(n Shaper) {    switch v := n.(type) {    case *Square:        fmt.Printf("Type Square %T\n", v)    case Square:        fmt.Printf("Type Square %T\n", v)    case *Circle:        fmt.Printf("Type Circle %T\n", v)    case nil:        fmt.Println("nil value: nothing to check?")    default:        fmt.Printf("Unexpected type %T", v)    }}

上面的type-switch中,之所以没有加上case Circle,是因为Circle只实现了指针类型的receiver,根据Method Set对接口的实现规则,只有指针类型的Circle示例才算是实现了接口Shaper,所以将值类型的示例case Circle放进type-switch是错误的。

转载地址:http://rwcml.baihongyu.com/

你可能感兴趣的文章
[LeetCode] Sort Colors
查看>>
Hadoop集群datanode磁盘不均衡的解决方案
查看>>
SQL SERVER 中日期格式化,及GETDATE()、CONVERT()函数使用说明
查看>>
datasnap回调
查看>>
Python文件夹与文件的操作
查看>>
关于INTRAWEB ISAPI DLL发布
查看>>
解决ASP.NET MVC4中使用Html.DropDownListFor显示枚举值默认项问题
查看>>
数据挖掘10大算法介绍
查看>>
Kaggle 商品销量预测季军方案出炉,应对时间序列问题有何妙招
查看>>
《程序员的修炼——从优秀到卓越》
查看>>
使用.net开发手机管理软件 (十) 短信部分——VB.NET解码PDU
查看>>
sql2005 COM+ 目录要求 (警告)
查看>>
D3D绘图一点总结
查看>>
一起谈.NET技术,SharePoint 2010 BI(2):使用Visio Service
查看>>
报告称Windows7不安全 管理员权限是罪魁祸首
查看>>
Basic INFO - SUPPORTDIR变量的读取
查看>>
恋恋风尘
查看>>
mongodb - collMod
查看>>
学生如何提高专业英文阅读能力--施一公教授
查看>>
回顾2011,展望2012
查看>>