Go:方法

一、基本介绍

在某些情况下,我们需要定义方法。比如 Person 结构体,除了有一些字段外(姓名、年龄...),还可以有一些行为动作(吃、唱歌...),这就需要用方法才能实现。

Go中的方法是作用在指定的数据类型上的(即:和指定的数据类型绑定),因此自定义类型,都可以有方法,而不仅仅是 struct 有。

示例:

type Person struct {
	Name string
}

// 给Person类型绑定一个方法
func (person Person) Eat() {
	fmt.Printf("%s正在吃东西...", person.Name)
}

func main() {
	person := Person{"pd"}
	person.Eat() // 调用方法
}

对上面代码总结:

  1. Eat 方法和 Person 类型绑定;
  2. Eat 方法只能通过 Person 类型的(变量 / 实例 / 对象)来调用,而不能直接调用,也不能使用其他类型的实例来调用;
  3. func (person Person) Eat() {},person表示哪个Person的实例调用,可以理解为 java 中的 this,python 中的 self;
  4. 方法的参数、返回值与函数一样。

二、方法的引用传递与值传递

结构体是值类型,在方法调用中,遵守值类型的传递机制,是值拷贝的传递方式。如果想在方法中,修改结构体字段的值,可以通过结构体指针的方式来处理。

type Person struct {
	Name string
	Age int
}

func (p *Person) Change() {
	/*
	因为 p 是指针,所以标准的访问字段的方式是 (*p).Name,但写成
	p.Name 也是可以的,因为编译器在底层会帮我们处理,方便程序员
	使用。
	同理,在下面的 main 函数中,本因 (&p).Change() 这样调用方法,
	但写成 p.Change() 也是可以的。
	 */
	p.Name = "乔治"
	p.Age = 20
}

func (p Person) Change1() {
	p.Name = "诺手"
	p.Age = 22
}

func main() {
	p := Person{"佩奇", 10}
	fmt.Println(p.Name, p.Age) // 佩奇 10
	p.Change()
	fmt.Println(p.Name, p.Age) // 乔治 20

	p1 := Person{"德玛", 11}
	p1.Change1()
	fmt.Println(p1.Name, p1.Age) // 德玛 11
	(&p1).Change1() // 同理,编译器会优化,因为 Change1() 中的Person不是一个指针
	fmt.Println(p1.Name, p1.Age) // 德玛 11
}

结论:不管结构体实例是 p.Change() 还是 (&p).Change() 的形式调用方法,都是由方法中 p 对应的结构体是 *Person 还是 Person 决定的!!!,*Person就是引用传递,Person就是值传递。

 

posted @ 2019-05-27 23:13  就俗人一个  阅读(182)  评论(0编辑  收藏  举报