只保留了组合(composition)这个最基础的特性
Go语言和C语言一样,类型都是基于值传递的。要想修改变量的值,只能传递指针。
Go语言中的面向对象最为直观,也无需支付额外的成本。如果要求对象必须以指针传递, 这有时会是个额外成本,因为对象有时很小(比如4字节),用指针传递并不划算。
只有在你需要修改对象的时候,才必须用指针
var a Integer = 1 //传入b=2
func (a *Integer) Add(b Integer) {
*a += b // 执行方法后 a=3
}
// 如果传入的不是指针则方法外部a的值不变,相当于值传递
func (a Integer) Add(b Integer) {
a += b // 执行后a在外面不变 a=1
}
b=a
修改b,a值不变 值语义
修改b,a值改变 引用语义
go中数组为值语义
var a = [3]int{1, 2, 3}
var b = a
b[1]++
fmt.Println(a, b) //结果 [1 2 3] [1 3 3]
var a = [3]int{1, 2, 3}
var b = &a //b为a的引用
b[1]++
fmt.Println(a, *b) //结果 [1 3 3] [1 3 3]
或
var a = []int{1, 2, 3} // slice a 本身就是引用
var b = a //b的值直接就是引用
b[1]++
fmt.Println(a, *b) //结果 [1 3 3] [1 3 3]
go中四种引用类型
package main
import ()
import "fmt"
type Dept struct {
name string
building string
floor uint8
}
func (self Dept) Name() string {
return self.name
}
func (self Dept) SetName(name string) {
self.name = name
}
func (self *Dept) Relocate(building string, floor uint8) {
self.building = building
self.floor = floor
}
func main() {
dept1 := Dept{name: "MySohu", building: "Media", floor: 7}
dept1.Relocate("Media", 12) //实例调用指针方法
}
依据Go语言规范:
如果结构的实例x是"可被寻址的",且&x的方法集中包含方法m,则 x.m()为(&x).m()的速记(快捷方式)。
即:dept1是可被寻址的,且&dept1的方法集中包含方法Relocate(),则 dept1.Relocate()为&dept1.Relocate()的快捷方式。
type Foo struct {
... //
Base
}
//也有形如下面这种,只是Foo创建实例的时候,需要外部提供一个Base类 实例的
type Foo struct {
... //
*Base
}
//这种方式可以很容易的借到定义类型的方法
eg:
type Job struct {
Command string
*log.Logger
}
func (job *Job)Start() {
//借用log.Logger的方法,实际还是使用原有log.Logger的方法,因此不能访问到Job中的其他属性
job.Log("starting now...")
... //做事情
job.Log("started.")
}
//匿名组合类型相当于以其类型名称(去掉包名部分) 作为成员变量的名字。按此规则,Y类型中就相当于存在两个名为Logger的成员,虽然类型不同。 因此,我们会收到编译错误。
type Logger struct {
Level int
}
type Y struct {
*Logger
Name string
*log.Logger
}
//这个编译错误并不是一定会发生的。 如这两个Logger在定义后再也没有被用过,那么编译器将直接 忽略掉这个冲突问题,直到开发者开始使用其中的某个Logger。