一、类型对象和类型对象指针调用
Go语言有值类型和指针类型直接调用其值接收者方法和指针接收者方法的区别:
先看一个实例:
package main
import "fmt"
type IFather interface {
getName() string
setName(string)
}
type Person struct {
name string
}
func(p Person) getName() string {
return p.name
}
func(p *Person) setName(name string) {
p.name = name
}
func main() {
per := Person{}
fmt.Printf("未初始化默认值:per :%s\n",per.getName())
per.setName("test")
fmt.Printf("设置值后:per :%s\n",per.getName())
per2 := &Person{name:"lisi"}
fmt.Printf("初始化值后:per2 :%s\n",per2.getName())
per2.setName("wanger")
fmt.Printf("设置值后:per2 :%s\n",per2.getName())
}
输出:
未初始化默认值:per1 :
设置值后:per1 :test
初始化值后:per2 :lisi
设置值后:per2 :wanger
值类型变量和指针类型变量都可以调用其值接收者方法和指针接收者方法。
值接收者声明的方法,调用时会使用这个值的一个副本去执行,而指针接收者在调用时会共享调用方法时接收者所指向的值,即可以修改指向的值。
二、接口和接口指针调用
值接收者和指针接收者赋值给接口的区别:
还是上面一个实例,稍微更改一下:就把对象赋给接口
package main
import "fmt"
type IFather interface {
getName() string
setName(string)
}
type Person struct {
name string
}
func(p Person) getName() string {
return p.name
}
func(p *Person) setName(name string) {
p.name = name
}
func main() {
var IPer IFather = &Person{}
var IPer2 IFather = Person{name:"lisi"}
fmt.Printf("未初始化默认值:s1:%s\n",IPer.getName())
IPer.setName("test")
fmt.Printf("设置值后:s1:%s\n",IPer.getName())
}
编译将报错:出现在这行
var IPer2 IFather = Person{name:"lisi"}
Person没有实现接口IFather的setName函数,所以不能赋值。
表面上看*Person也没有实现getName函数,但是*Person所指向的值实现了getName函数,所以*Person也自动拥有getName函数,所以实现接口IFather。Person作为值接收者,Go无从知道值的原始值是什么,因为 值接收者 是份拷贝,所以不能影响Person。go 会把指针进行隐式转换得到 value,但反过来则不行。
所以,类型 T 变量只有接受者是 T 的方法;而类型 *T变量拥有接受者是 T 和 *T 的方法,换句话,当实现了一个接收者是值类型的方法,就可以自动生成一个接收者是对应指针类型的方法,因为两者都不会影响接收者。但是,当实现了一个接收者是指针类型的方法,如果此时自动生成一个接收者是值类型的方法,原本期望对接收者的改变(通过指针实现),现在无法实现,因为值类型会产生一个拷贝,不会真正影响调用者。
(1)指针类型变量*T可以接收T和*T方法
(2)类型T只能接收T方法