go day 01 静态类型与动态类型

375 阅读1分钟

go具有浅浅的继承(实现)关系,定义一个结构体,只要实现了某个接口内部的全部方法就可以被认为是实现了该接口,基于此就可以面向对象中的多态。

package Reflect

type inter interface {
   print()
}

type School struct {
   name string
}

type Address struct {
   name string
}

func (s School) print() {
   fmt.Println(s.name)
}

func (a Address) print() {
   fmt.Println(s.name)
}

如上所示,School结构体以及Address结构体实现了inter接口,基于此可以做如下声明

var p inter=School{"xjtu"}
var pp inter=Address{"xi'an"}

此时变量p的静态类型是inter,而其动态类型为School,前者静态类型不能更改,也就是说不能再做如下声明:var p int。但是后者动态类型可以更改,p=Address{"xi'an"},将p的动态类型改为Address这个是可以的,属于说向下兼容了。

接下来用反射表述一下这个过程

var in inter
fmt.Printf("%T %v\n", in, reflect.TypeOf(&in).Elem())
in = School{"xjtu"}
fmt.Printf("%T %v\n", in, reflect.TypeOf(&in).Elem())

注意reflect.TypeOf(in)获得的是in的动态类型,用fmt包通过%T获取的也是in的动态类型,而reflect.TypeOf(&in).Elem()获取的是in的静态类型。 代码输出为

<nil> Reflect.inter
Reflect.School Reflect.inter

可见一开始没有为in声明实指的时候,其动态类型为nil,静态类型为Reflect.inter,在为其声明了实指为School之后,其动态类型为School,静态类型不变。

ps:p的类型分为静态和动态类型,数据只有一份,在声明in = School{"xjtu"}之后,其数据就指向了School{"xjtu"}