1. 静态类型 static type

声明变量时的类型

  1. var i int //int是静态类型
  2. var str string //string是静态类型 编码时能确定的,可看见的类型是静态类型

2. 动态类型 dynamic type

程序运行时才能确定具体类型的类型是动态类型

  1. var i interface{} //空接口可以接受任何类型,因此声明时不确定是什么具体类型
  2. i = 25 //赋值为int,但静态类型还是interface{}, 运行时,i的类型才会改变为int
  3. i = "abcdefg" //赋值为string,但静态类型还是interface{},运行时,i的类型才会改变为string

3. 接口组成

接口由type和data组成

  1. var temp interface{}
  2. temp = 25

执行temp = 25后,interface的type=int data=25

3.1 接口细分

接口分为非空接口iface和空接口eface
iface带有一组函数的接口

  1. //非空接口
  2. type ifcae struct {
  3. tab *itab //类型信息
  4. data unsafe.Pointer //数据指针
  5. }
  6. // 非空接口的类型信息
  7. type itab struct {
  8. inter *interfacetype // 接口定义的类型信息
  9. _type *_type // 接口实际指向值的类型信息 l
  10. ink *itab
  11. bad int32
  12. inhash int32
  13. fun [1]uintptr //接口方法实现列表,即函数地址列表,按字典序排序
  14. }

eface空接口

  1. type eface struct {
  2. _type *_type //类型
  3. data unsafe.Pointer //数据指针
  4. }

3.2 理解动态类型

3.2.1 iface
  1. var reader io.Reader
  2. tty, err := os.OpenFile("/dev/tty", os.O_RDWR, 0)
  3. if err != nil {
  4. return nil, err
  5. }
  6. reader = tty

io.Reader接口包含Read(),所以是非空接口 执行var reader io.Reader后,此时reader的静态类型是io.Reader,动态类型是nil,函数集为Read(),数据指针为nil 执行reader = tty后,此时reader的静态类型还是io.Reader,动态类型改变为*io.File,函数集为Read(),数据指针为tty

3.2.2 eface
  1. var empty interface{}
  2. tty, err := os.OpenFile("dev/tty", os.O_RDWR, 0)
  3. if err != nil {
  4. return nil, err
  5. }
  6. empty = tty

执行var empty interface{}后,此时empty的静态类型为nil,数据指针为nil 执行empty = tty后,此时empty的静态类型改变为*os.File,数据指针为tty