go语言 - 方法

概述

在go语言中,可以给任意自定义类型(包括内置类型,但不包括指针类型)添加相应的方法;

方法相关的特性如下:

1. 方法总是绑定对象实例,并隐式将实例作为第一实参(receiver)
2. 只能为当前包内命名类型定义方法
3. 参数receiver 可任意命名,如方法中为曾使用,可省略参数名
4. 参数receiver 类型可以是T or *T; 基类型T 不能是接口或指针
5. 不支持方法重载,receiver 只是参数签名的组成部分
6. 可用实例 value 或 pointer 调用全部方法,编译器自动转换
7. 没有构造和析构方法,通常用简单工厂模式返回对象实例

 

基础类型作为接收者


/*
	1. 实现两数相加
	1.1 函数方式
	1.2 方法方式
*/

//1.1 函数方式,实现两数相加
func addFunc(n1, n2 int) int {
	return n1 + n2
}

//1.2 方法方式,实现两数相加,首先定义一个类型 myInt
type myInt int

//为类型long 添加一个方法addMethod
func (n1 myInt) addMethod(n2 myInt) myInt {
	return n1 + n2
}

func main() {

	//1.1 函数实现
	r1 := addFunc(1, 3)
	fmt.Println("By function: ", r1)

	//1.2 方法实现
	var numOne myInt = 1
	fmt.Println("By Method: ", numOne.addMethod(3))
}

结构体作为接收者

  • 值语义
  • 指针语义
//定义结构体Person
type Person struct {
	name   string
	gender string //male or female
	age    int
}

//为Person 类定制一个结构化输出的方法, 类似java 中序列化方法 toString
func (p Person) toString() {
	fmt.Printf("name: %s \n age: %d \n gender: %s \n", p.name, p.age, p.gender)
}

//为Person 添加一个 修改信息的方法
func (p *Person) modify(name, gender string, age int) {
	p.name = name
	p.age = age
	p.gender = gender
}

//值语义 - 接收者 p 为普通变量,非指针变量
func (p Person) modifyValue(name, gender string, age int) {
	p.name = name
	p.age = age
	p.gender = gender
	fmt.Printf("************** modifyValue **************: \n")
	p.toString()
}

func main() {
	person := Person{
		"Ryan",
		"male",
		26,
	}
	person.toString()
	person.modify("Ryan.xu", "male", 27)
	person.toString()
	
	//通过值语义的方法来修改结构体成员,不能正常修改
	person.modifyValue("go", "male", 8)
	person.toString()
	
}

方法集

类型的变量能够调用哪些方法,这些方法的一个集合,简称“方法集”

1. 类型T 方法集包含全部receiver T 方法
2. 类型*T 方法集包含全部receiver T + *T 方法
3. 如类型S 包含匿名字段T,则S 方法集包含T 方法
4. 如类型S 包含匿名字段*T,则S 方法集包含T + *T 方法
5. 不管嵌入T 或者 *T, *S方法集总是包含 T + *T 方法

Tips: 用实例“普通对象”和“指针对象”调用方法(含匿名字段)不受方法集约束,编译器总是查找全部方法,并自动转换receiver 实参

 

匿名字段

  • 方法继承
  • 方法重写

 

方法继承

type Student struct {
	Person  //匿名字段, 引用前面的 Person类型,继承toString 的方法
	id      int
	address string
}


func main() {
	fmt.Println("************** 方法继承 **************")
	stu := Student{Person{"Ryan.xu", "male", 26}, 10001, "SH"}
	stu.toString() 
}

 

方法重写

type Student struct {
	Person  //匿名字段
	id      int
	address string
}

// student 重写 person 中的 toString 方法
func (s Student) toString() {
	fmt.Printf("id: %d \n name: %s \n age: %d \n gender: %s \n address: %s \n",
		s.id, s.name, s.age, s.gender, s.address)
}

func main() {
	fmt.Println("************** 方法重写 **************")
	stu := Student{Person{"Ryan.xu", "male", 26}, 10001, "SH"}
	//就近原则,先找本作用域,找不到再用继承的方法
	stu.toString() 
	//如果还想调用 Person 中的toString方法, 需显示调用
	stu.Person.toString()
}

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值