golang面试题二之interface

stevenyeahnet · · 748 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

interface和nil
golang的nil在概念上和其它语言的null、None、nil、NULL一样,都指代零值或空值,在golang中,nil只能赋值给指针、channel、func、interface、map或slice类型的变量。如果未遵循这个规则,则会引发panic.
在底层,interface作为两个成员来实现,一个类型和一个值.接下来通过编写测试代码来看看interface倒底是什么。
测试代码一:

     package main  
       
    import (  
        "fmt"  
        "reflect"  
    )  
       
    func main() {  
        var val interface{} = int32(1)  
        fmt.Println(reflect.TypeOf(val))  
        val = 50  
        fmt.Println(reflect.TypeOf(val))  
    }  

我们已经知道接口类型变量底层是作为两个成员来实现,一个是type,一个是data。type用于存储变量的动态类型,data用于存储变量的具体数据。在上面的例子中,第一条打印语句输出的是:int32。这是因为已经显示的将类型为int64的数据1赋值给了interface类型的变量val,所以val的底层结构应该是:(int32, 1)。我们暂且用这种二元组的方式来描述,二元组的第一个成员为type,第二个成员为data。第二条打印语句输出的是:int。这是因为字面量的整数在golang中默认的类型是int,所以这个时候val的底层结构就变成了:(int, 1)
在底层,interface作为两个成员实现,一个类型,一个值。只有在内部值和类型都设置为nil时,interface才为nil。特别的,一个nil接口总是拥有一个nil类型。若我们在一个接口值中存储一个int类型指针,则内部类型将为int,而无论该指针的值是什么:(*int,nil)。因此这个接口值是非nil的,即使该指针值为nil。
看看测试代码二:

package main  
import (  
 "fmt"  
)  
  func main() {  
  var val interface{} = nil  
  if val == nil {  
  fmt.Println("val is nil")  
  } else {  
  fmt.Println("val is not nil")  
  }  
}

变量val是interface类型,它的底层结构必然是(type, data)。 由于nil是untyped(无类型),又将nil赋值给了变量val,所以val实际上存储的是(nil, nil)
测试代码三:

 package main  
 import (  
  "fmt"  
  )  
  func main() {  
      var val interface{} = (*interface{})(nil)   
      if val == nil {  
          fmt.Println("val is nil")  
      } else {  
           mt.Println("val is not nil") 
}

来看一种特例:(interface{})(nil)。将nil转成interface类型的指针,得到的结果仅仅是空接口类型指针并且它指向无效的地址。上面的代码定义了接口指针类型变量val,它指向无效的地址(0x0),因此val持有无效的数据。但它是有类型的(interface{})。所以val的底层结构应该是:(interface{}, nil)。很显然,无论该指针的值是什么:(interface{}, nil),这样的接口值总是非nil的,即使在该指针的内部为nil。


有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:stevenyeahnet

查看原文:golang面试题二之interface

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

748 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传