学习资料来自
GitHub - unknwon/the-way-to-go_ZH_CN: 《The Way to Go》中文译本,中文正式名《Go 入门指南》
1、结构体(借助结构体隐式实现面向对象)
1)不论是结构体类型或是指向结构体的指针,均使用 '.' 作为选择器符
2)结构体工厂(惯例:工厂的名字以 new 或 New 开头),其实就是结构体的构造函数。构造结构体工厂后可以禁止使用new函数,强制用户使用工厂方法(实现类的私有化)
3)注意 new 初始化返回指针,make 初始化返回类型本身
4)结构体添加标签 :借助 reflect 包结构体可添加 Field,使用 Tag 属性
type TagType struct { // tags
field1 bool "An important answer"
field2 string "The name of the thing"
field3 int "How much there are"
}
func refTag(tt TagType, ix int) {
ttType := reflect.TypeOf(tt)
ixField := ttType.Field(ix)
fmt.Printf("%v\n", ixField.Tag)
}
5)匿名字段和内嵌结构体:可模拟类似继承的行为(Go中的继承通过内嵌/组合实现)
- 匿名字段的类型就是字段名,在同一结构体中每一种数据类型只能有一个匿名字段
- 内嵌结构体:访问时直接通过 “外层结构体名.内层结构体字段名”即可
6)结构体命名冲突:不同级别时外层将覆盖内层,同一级别时引发错误。
7)方法(作用在接收者recv上的函数),任何类型都可有方法,但接口和指针不能作为接收者,但允许是任何允许类型对应的指针。
(1)定义格式
func (recv receiver_type) methodName(parameter_list) (return_value_list) { ... }
(2)类型和作用其上的方法必须在同一个包里定义,想为基本类型定义方法时可先定义该类型的别名,以别名作为recv接收方法
(3)函数和方法的区别
- 函数将变量作为参数,方法在变量上调用
- 接收者是指针,方法可改变接收者的值/状态(函数中参数作为指针传递可实现同样效果),接收者非指针则无法改变接收者的值
(4)指针方法和值方法都可以在指针或非指针上被调用
(5)当一个匿名类型被内嵌在结构体中时,匿名类型的可见方法也同样被内嵌,这在效果上等同于外层类型继承了这些方法
8)给类型赋予功能
(1)组合(聚合)的方法:包含功能的类型有具体的名字
type Log struct {
msg string
}
type Customer struct {
Name string
log *Log
}
func (l *Log) Add(s string) {
l.msg += "\n" + s
}
func (l *Log) String() string {
return l.msg
}
func (c *Customer) Log() *Log {
return c.log
}
func main() {
c := new(Customer)
c.Name = "Barak Obama"
c.log = new(Log)
c.log.msg = "1 - Yes we can!"
// shorter
c = &Customer{"Barak Obama", &Log{"1 - Yes we can!"}}
// fmt.Println(c) &{Barak Obama 1 - Yes we can!}
c.Log().Add("2 - After me the world will be a better place!")
//fmt.Println(c.log)
fmt.Println(c.Log())
}
(2)内嵌:包含功能的类型采用匿名字段
type Log struct {
msg string
}
type Customer struct {
Name string
Log
}
func (l *Log) Add(s string) {
l.msg += "\n" + s
}
func (l *Log) String() string {
return l.msg
}
func (c *Customer) String() string {
return c.Name + "\nLog:" + fmt.Sprintln(c.Log.String())
}
func main() {
c := &Customer{"Barak Obama", Log{"1 - Yes we can!"}}
c.Add("2 - After me the world will be a better place!")
fmt.Println(c)
}
9)多重继承实现:在该类型中嵌入所有必要父类型
10)继承有两个好处:代码复用(组合和委托实现)和多态(接口实现),二者也成为组件编程
11)可定义String方法,类似Java中的toString,在打印对象时自动调用
12)垃圾回收:Go运行中含独立进程GC(垃圾收集器,搜索不再使用的变量然后释放),可通过runtime访问进程