一、go的面向对象,通过将方法与结构体变量进行绑定(当然方法也可以与其他数据类型进行绑定)。
func(t T)methodName(参数列表) (返回值列表){}
package main
import "fmt"
type Person struct{
Name string
Age int
}
func (p Person)Say() {
fmt.Println(p.Name,"say hello")
}
func main() {
p := Person{"Nomen",18}
p.Say()
}
因为结构体是值拷贝类型,所以调用方法的时候将会复制一份结构体变量的数据。所以为了节约开销,绑定方法的方式可以通过结构体变量指针绑定
func(t *T)methodName(参数列表) (返回值列表) {}
type Person struct{
Name string
Age int
}
func (p *Person)Say() {
fmt.Println(p.Name,"say hello")
}
以指针方式绑定结构体或者直接类型绑定,访问属性值可以用(&p).Name ,go官方在底层其实已经实现了可以直接用p.Name 进行访问。但是要注意的是,指针绑定的对象是值引用,直接类型绑定的是值拷贝
package main
import "fmt"
type Person struct{
Name string
Age int
}
func (p Person)test1() {
p.Name = "tom"
fmt.Println("test1",p.Name)
}
func (p *Person)test2() {
p.Name = "jack"
fmt.Println("test2",p.Name)
}
func main() {
p := Person{"Nomen",18}
(&p).test1()
p.test1()
fmt.Println((&p).Name,p.Name)
(&p).test2()
p.test2()
fmt.Println((&p).Name,p.Name)
}
由执行结果可以说明:test1() 直接绑定类型(值拷贝),方法内更改了name为tom,方法内输出为tom,而方法外用p.Name 依然是初始值Nome。 说明启用test1时,拷贝了一份Persen。操作的内存空间不同了。所以方法内和方法外的结果不同
test2() 绑定的是指针类型(值引用),方法内更改Name为jack,方法内输出为jack,方法外用p.Name已经将Nome更改为jack了。说明启用test2()时,引用了初始的Person。方法内部操作的内存空间还是同一份。所以方法内和方法外的结果是一样的。
所以我们在实际项目中,大部分都会 绑定指针类型。既节省了资源,又同步了对象的数据。
二、方法的访问限定与方法名首字母是否大小写有关,与属性访问限定一样。首字母大写,包外可以访问,小写则只能在包内访问。
三、如果一个类型实现了String()方法,那么fmt.Println()进行打印的时候就会默认调用变量实现的这个String()方法。