Go 笔记之面向对象
Go语言如早期的js和python一样,没有显式的类类型,但可通过结构体与函数显式绑定,隐式地组合实现面向对象编程思维。
struct类型
- struct类型初始化
- 按照顺序提供初始化值
- 通过
field:value
的方式初始化,这样可以任意顺序 - 通过 new 函数分配一个指针,此处P的类型为 *person
- struct 的匿名字段(嵌入字段)
- 匿名字段能够实现字段的继承
- 所有的内置类型和自定义类型都可以作为匿名字段
- 同名字段,外层的优先访问,可重载
-
匿名结构体
- 空结构值
struct{}{}
, 通常用在通道结束符信号,不占内存 -
struct{}{name:string}
类似如其它语言中的匿名类一样type Skills []string type Human struct { name string age int weight int } type Student struct { Human // 匿名字段,那么默认 Student 就包含了 Human 的所有字段 Skills // 匿名字段,自定义的类型 string slice int // 内置类型作为匿名字段 speciality string } func main() { // 我们初始化一个学生 mark := Student{Human{"Mark", 25, 120}, "Computer Science"} }
- 空结构值
面向对象
-
方法 带有接收者的函数
func (r ReceiverType) funcName(parameters) (results) // 自定义类型,类似于别名 type typeName typeLiteral type ages int type months map[string]int
-
可以在任何的自定义类型中定义任意多的 method
-
指针作为receiver
- go 知道是否调用指针的 method 还是非指针的 method,会自转
- 如果一个 method 的 receiver 是 *T, 你可以在一个 T 类型的实例变量 V 上面调用method,而不需要 &V 去调用这个 method
-
方法继承 vs 重写
- Go使用的是内嵌式组合继承,注意区别于其它语言,Go的‘子类’并非是‘父类’类型
interface类型
- interface 是一组 method 签名的组合
- 空interface
- interface{} 存储任意类型的数值 (类C void*)
- interface 函数参数
- interface 变量存储的类型
- Comma-ok 断言
- value,ok = element(T)
- element 为interface变量,T断言的类型
- element.(type) 语法不能在switch外的任何逻辑里面使用
- Comma-ok 断言
-
嵌入interface
-
相同的逻辑引入到interface内
type Interface interface { sort.Interface // 嵌入字段 sort.Interface Push(x interface{}) // a Push method to push elements into the heap Pop() interface{} // a Pop elements that pops elements from the heap }
-
反射
-
结构休字段类型
type StructField struct { Name string // 字段名 PkgPath string // 字段路径 Type Type // 字段反射类型对象 Tag StructTag // 字段的结构体标签 Offset uintptr // 字段在结构体中的相对偏移 Index []int // Type.FieldByIndex中的返回的索引值 Anonymous bool // 是否为匿名字段 }
-
反射某一类型的值(这些值都实现了空interface)
-
转化为reflect对象(reflect.Type 或 reflect.Value)
t := reflect.TypeOf(i) // 得到类型的元数据,通过t我们能获取类型定义里面的所有元素 v := reflect.ValueOf(i) // 得到实际的值,通过 v 我们获取存储在里面的值,还可以去改变值
-
将reflect转化为相应的值
tag := t.Elem().Field(0).Tag // 获取定义在 struct 里面的标签 name := v.Elem().Field(0).String() // 获取存储在第一个字段里面的值
-
反射的字段必须是可修改(可寻址,即非导出字段不能被修改)
var x float64 = 3.4 v := reflect.ValueOf(x) fmt.Println("type:", v.Type()) fmt.Println("kind is float64:", v.Kind() == reflect.Float64) fmt.Println("value:", v.Float()) //修改相应的值 p := reflect.ValueOf(&x) v := p.Elem() v.SetFloat(7.1)
-
本作品采用《CC 协议》,转载必须注明作者和本文链接