go学习-方法和接收者

方法和接收者

Go语言中的方法(Method)是一种作用于特定类型变量的函数。
这种特定类型变量叫做接收者(Receiver)。接收者的概念就类似于其他语言中的this或者 self。

方法的定义格式如下:
接收者变量:接收者中的参数变量名在命名时,官方建议使用接收者类型名称首字母的小写,例如,Person类型的接收者变量应该命名为 p

注意:接收者类型可以是任何类型,但必须是本地自定义类型。不能是其他包的类型。

func (接收者变量 接收者类型) 方法名(参数列表) (返回参数) {
    函数体
}

方法与函数的区别是,函数不属于任何类型,方法属于特定的类型。
(个人理解(不一定对),方法相当于其他语言中类里面的方法,需要实例化之后,用实例化的对象.方法名,go的接收者就相当于类的实例化对象)

//比如:java中toString()是Integer类中的一个方法,只有Integer类型的变量可以调用。
//toString()就相当于一个go的方法,接收者是Integer类型的
Integer i =10;
String s = i.toString();

实例:

//Person 结构体
type Person struct {
	name string
	age  int8
}

//NewPerson 构造函数
func NewPerson(name string, age int8) *Person {
	return &Person{
		name: name,
		age:  age,
	}
}

//Dream Person做梦的方法
func (p Person) Dream() {
	fmt.Printf("%s的梦想是学好Go语言!
", p.name)
}

func main() {
	p1 := NewPerson("小王子", 25)
	p1.Dream()//方法必须是特定类型,这里是Person类型,p1是Person,所有可以调用
}

结果

指针类型的接收者

指针类型的接收者由一个结构体的指针组成,由于指针的特性,调用方法时修改接收者指针的任意成员变量,在方法结束后,修改都是有效的。

// SetAge 设置p的年龄
// 使用指针接收者
package main

import "fmt"

//Person 结构体
type Person struct {
	name string
	age  int8
}

//NewPerson 构造函数
func NewPerson(name string, age int8) *Person {
	return &Person{
		name: name,
		age:  age,
	}
}

//Dream Person做梦的方法
func (p Person) Dream() {
	fmt.Printf("%s的梦想是学好Go语言!
", p.name)
}

// SetAge2 设置p的年龄
// 使用值接收者
func (p *Person) SetAge2(newAge int8) {
	p.age = newAge
}

func main() {
	p1 := NewPerson("小王子", 25)
	p1.Dream()
	fmt.Println(p1.age) // 25
	p1.SetAge2(30) // (*p1).SetAge2(30)
	fmt.Println(p1.age) // 25
}

值类型的接收者

当方法作用于值类型接收者时,Go语言会在代码运行时将接收者的值复制一份。在值类型接收者的方法中可以获取接收者的成员值,但修改操作只是针对副本,无法修改接收者变量本身。

package main

import "fmt"

//Person 结构体
type Person struct {
	name string
	age  int8
}

//NewPerson 构造函数
func NewPerson(name string, age int8) *Person {
	return &Person{
		name: name,
		age:  age,
	}
}

//Dream Person做梦的方法
func (p Person) Dream() {
	fmt.Printf("%s的梦想是学好Go语言!
", p.name)
}

// SetAge2 设置p的年龄
// 使用值接收者
func (p Person) SetAge2(newAge int8) {
	p.age = newAge
}

func main() {
	p1 := NewPerson("小王子", 25)
	p1.Dream()
	fmt.Println(p1.age) // 25
	p1.SetAge2(30) // (*p1).SetAge2(30)
	fmt.Println(p1.age) // 25
}

什么时候应该使用指针类型接收者

需要修改接收者中的值
接收者是拷贝代价比较大的大对象
保证一致性,如果有某个方法使用了指针接收者,那么其他的方法也应该使用指针接收者。

结构体的“继承”

//Animal 动物
type Animal struct {
	name string
}

func (a *Animal) move() {
	fmt.Printf("%s会动!
", a.name)
}

//Dog 狗
type Dog struct {
	Feet    int8
	*Animal //通过嵌套匿名结构体实现继承
}

func (d *Dog) wang() {
	fmt.Printf("%s会汪汪汪~
", d.name)
}

func main() {
	d1 := &Dog{
		Feet: 4,
		Animal: &Animal{ //注意嵌套的是结构体指针
			name: "乐乐",
		},
	}
	d1.wang() //乐乐会汪汪汪~
	d1.move() //乐乐会动!
}

结构体字段的可见性

结构体中字段大写开头表示可公开访问,小写表示私有(仅在定义当前结构体的包中可访问)。

所有博客均为自己学习的笔记。如有错误敬请理解。
原文地址:https://www.cnblogs.com/tangtang-benben/p/15075438.html