首先开下例子的输出结果
package main
import "fmt"
func main() {
// 1
dl := data{"one"}
dl.setName("three") // 指针方法 name被修改了 three
dl.setName1("four") // 值方法 name没有修改 只是修改了nama副本的值
dl.print()
// 2
var dl1 = &data{"one"}
dl1.setName("three") // 指针方法 被修改成功
dl1.print()
// 3
// data继承了printer实现的接口方法通过指针方法实现 所以printer只能接受指针类型
var in printer = &data{"two"}
in.setName("three")
in.print()
// 4
// 下面两个结果是two
// 原因是go检测到只实现了结构方法、这样结构方法不能够修改只能修改副本的值
// 下面虽然赋值的是指针类型、但是go语言会检测到这是个结构体方法 他会隐式的转换为
// (*in1).setName("three")
// 还是只副本改变得值
var in1 printer = &data1{"two"}
in1.setName("three")
in1.print()
// 5
var in2 printer = data1{"two"}
in2.setName("three")
in2.print()
}
type data struct {
name string
}
type data1 struct {
name string
}
func (p *data) print() {
fmt.Println("name: ", p.name)
}
func (p *data) setName(name string) {
p.name = name
}
func (p data) setName1(name string) {
p.name = name
}
func (p data1) print() {
fmt.Println("name: ", p.name)
}
func (p data1) setName(name string) {
p.name = name
}
type printer interface {
print()
setName(name string)
}
结果
name: three
name: three
name: three
name: two
name: two
总结得出的结论
1、代码中标记为1的代码是: 一个结构如果有指针方法和结构体方法我们看到对于同一个变量的修改指针方法修改了结构体的值、但是结构体方法没有修改修改的只是结构体的副本的对应的变量的值。虽然dl我们赋值的是结构体不是指针,但是我们调用指针方法的时候其实go自动的转换为 (&dl).setName
setName修改成功 为three
setName1修改失败还是three
2、代码中标记为2的代码是:这个初始化一个变量为结构体指针,方法调用仍然醉熏第一条讲的那样
3、代码中标记为3的代码是:data继承了printer实现的接口方法通过指针方法实现 所以printer只能接受指针类型
4、代码中标记为4和5的代码是: 下面两个结果是two
原因是go检测到只实现了结构方法、这样结构方法不能够修改只能修改副本的值下面虽然赋值的是指针类型、但是go语言会检测到这是个结构体方法 他会隐式的转换为
// (*in1).setName("three")
// 还是只副本改变得值
Go语言中除了map、slice、chan(但是根本原因是他们的底层结构体有指针)外,其他类型在函数参数中都是值传递
Go语言不是面向对象的语言,很多时候实现结构体方法时需要用指针类型实现引用结构体对象
指针也是一个类型,在实现接口interface时,结构体类型和其指针类型对接口的实现是不同的