方法和函数区别
- 调用方式不一样
- 函数的调用方式:
- 函数名(实参列表)
- 方法的调用方式:
- 变量.方法名(实参列表)
- 对于普通函数,接收者为值类型时,不能将指针类型的数据直接传递,反之亦然
type Person struct { Name string } func test01(p Person) { fmt.Println(p.Name) } func main() { p := Person{"tom"} test01(p) -- test01(&p) 错误,是值类型,不能传地址 }
- 输出结果:
- 如果是参数是指针类型,则只能传指针
type Person struct { Name string } func test01(p *Person) { fmt.Println(p.Name) } func main() { p := Person{"tom"} test01(&p) -- test01(p) 错误,是指针类型,不能传值 }
- 对于方法(如 struct 的方法),接收者为值类型时,可以直接用指针类型的变量调用方法,反过来同样也可以
type Person struct { Name string } func (p Person) test03() { p.Name = "jack" fmt.Println("test03() =", p.Name) } func main() { p := Person{"tom"} p.test03() fmt.Println("main() p.name=", p.Name) // tom (&p).test03() // 从形式上是传入地址,但是本质仍然是值拷贝 fmt.Println("main() p.name=", p.Name) // tom }
- 输出结果:
- 注意:(&p).test03() 从形式上是传入地址,但是本质仍然是值拷贝
type Person struct { Name string } func (p *Person) test04() { p.Name = "mary" fmt.Println("test03() =", p.Name) // mary } func main() { p := Person{"tom"} (&p).test04() fmt.Println("main() p.name=", p.Name) // mary p.test04() // 等价 (&p).test04 , 从形式上是传入值类型,但是本质仍然是地址拷贝 }
- 输出结果:
- 注意:p.test04() 等价 (&p).test04 , 从形式上是传入值类型,但是本质仍然是地址拷贝
- 总结:
- 不管调用形式如何,真正决定是值拷贝还是地址拷贝,看这个方法是和哪个类型绑定.
- 如果是和值类型,比如 (p Person) , 则是值拷贝
- 如果和指针类型,比如是 (p *Person) 则是地址拷贝。