Golang接口及其类型检查

Golang接口及其类型检查

一、接口及接口实现

​ 接口简介:Java、Go中的接口及其使用简介_玉言心的博客-CSDN博客_java接口和go接口

  • Golang接口定义 - 接口即约定【简单理解】

    type Writer interface {} // 空接口
    type Writer interface {  // 带有方法的接口
        Write(p []byte)(err error)
    } 
    
  • Golang接口实现

    type ByteWriter struct{}
    func (b *ByteWriter) Write(p []byte)(err error){
        if len(p) <= 0{
            return errors.New("err")
        }
        // 其他操作
        return nil
    }
    
二、interface与其他变量等价判断
  • interface类型变量与非interface类型变量判等时

    • 首先要求非interface类型实现了接口,否则编译不通过
    • 如果是空接口,则可以认为所有类型都实现了该接口
    • interface类型变量的动态类型、值均与非interface类型变量相同时,两个变量判等结果为true
  • 例如下列代码:

    首先,m的默认类型是一个空接口,因此可以认为int类型已经实现了接口,所以不会出现编译报错问题

    其次,p == m进行毕竟判断时,由于interface是基于动态派发的,具体类型(身份)是根据实现类型来确定具体类型的,又p和m均是int数组类型,因此类型相同,结合数组的初始化方式,我们也易知p和m的值相等,因此输出结果为true。

    package main
    
    import "fmt"
    
    func main() {
     var p [100]int
     var m interface{} = [...]int{99: 0}
     fmt.Println(p == m)
    }
    
  • interface类型变量与interface类型变量判等时

    • 会同时比较两个接口变量的type和value,都相等的时候,才会认为相等
  • 例如下列代码:

    type A interface{}
    type B struct{}
    var a *B
    
    print(a == nil)            //true nil代表接口类型的zero value
    print(a == (*B)(nil))      //true 
    print((A)(a) == (*B)(nil)) //true
    
    print((A)(a) == nil)       //false
    
    • 最后一个之所以是false,是因为只有当一个interface的value和type都unset的时候,它才等于nil,而上述代码中的interface (A)a 的type是*B, 不是unset。【结合下文】
三、nil关键字和类型断言
  • nil

    nil其实甚至不是golang的关键词,只是一个变量名。定义在 buildin/buildin.go 中

    // nil is a predeclared identifier representing the zero value for a
    // pointer, channel, func, interface, map, or slice type.
    var nil Type // Type must be a pointer, channel, func, interface, map, or slice type
    
    // Type is here for the purposes of documentation only. It is a stand-in
    // for any Go type, but represents the same type for any given function
    // invocation.
    type Type int
    
    • golang中nil代表了pointer, channel, func, interface, map 或者 slice 的zero value,比如:

      n1 := (*struct{})(nil) // 指针
      fmt.Printf("(*struct{})(nil) nil: %t ,type is: %s\n", n1 == nil, reflect.TypeOf(n1).String())
      
      n2 := []int(nil)      // 切片
      fmt.Printf("[]int(nil) nil: %t ,type is: %s\n", n2 == nil, reflect.TypeOf(n2).String())
      
      n3 := map[int]bool(nil) // map
      fmt.Printf("map[int]bool(nil) nil: %t ,type is: %s\n", n3 == nil, reflect.TypeOf(n3).String())
      
      输出结果:
      (*struct{})(nil) nil: true ,type is: *struct {}
      []int(nil) nil: true ,type is: []int
      map[int]bool(nil) nil: true ,type is: map[int]bool
      
    • 特别是在interface中,只有当一个interface的V和T都unset时,它的值才是nil,

  • 类型断言

    • 作用和语法格式

      1.作用:是一个接口表达式,作用于接口上的操作,用来检查作为操作数的动态类型是否满足指定的断言类型。
      2.语法:x.(T),x是接口类型的表达式,T是一个断言类型,如果T是具体类型,会检查x的动态类型是否就是T,如果检查成功,断言结果就是x的动态值,类型就是T,否正操作失败;如果T是接口类型,会检查x的动态类型是否就是T,如果检查成功,动态值并没有提取出来,结果仍然是一个接口值,接口值的类型type和值value部分不变,结果类型是接口类型T。
      
    • 示例

      type Cat struct{
          Name string
      }
      func main(){
          var in interface{} = &Cat{
              Name: "cici"
          }
          switch in.(type){
          case *Cat: 
              // 其他操作
          }
      }
      
四、拓展:var _ interface = (*type)(nil)
  • 作用:和类型断言类似,用来检查类型type这个struct是否实现了interface 这个接口

  • 理解:可以把=左右两边分开来看

    • 左边:var _ interface 等价于我们平时用的 var variable type
    • 右边:(* type)(nil) 等价于 var variable *type nil
  • 因此,可以直接理解为var _ interface = (*type)(nil)就是用来检查type是否实现了接口interface

  • 例子:

    type Writer interface {  // 带有方法的接口
    	Write(p []byte)(err error)
    	ToString() string
    }
    
    var _ Writer = (*ByteWriter)(nil)
    
    type ByteWriter struct{}
    func (b *ByteWriter) Write(p []byte)(err error){
    	if len(p) <= 0{
    		return errors.New("err")
    	}
    	// 其他操作
    	return nil
    }
    
    • 我们为Writer接口新增方法ToString,返回一个string类型的值,然后使用var _ Writer = (*ByteWriter)(nil)进行检查,由于ByteWriter仅仅实现了方法Write,没有实现ToString,因此会报:

      Cannot use '(*ByteWriter)(nil)' (type *ByteWriter) as the type Writer Type does not implement 'Writer' as some methods are missing: ToString() string
      

      从而提示用户还有ToString() string没有实现

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

玉言心

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值