Go开发 结构体方法详解「终于解决」

go (54) 2023-03-24 21:49

大家好,我是编程小6,很高兴遇见你,有问题可以及时留言哦。

概述

在面向对象编程中,一般将抽象的东西称为。在Go语言中没有类对应的东西,因此用结构体来抽象。因此可以说,在Go语言中,类就是结构体,结构体就是类(后面我们统一都采用类的说法)。

类主要由两部分组成,一是属性,比如一辆车的品牌,外观,引擎等,二是行为,表示类所拥有的动作,比如车可以拐弯,加速,刹车等。

结构体添加方法

首先,我们定义一个猫类,如下:

//定义猫类
type Cat struct {
	age int
}

这里我们简单的抽象一个属性就是年龄,接着就可以给猫绑定几个方法。在Go语言中称为给“接收器”绑定几个方法,接收器一共有两种,1. 实例接收 2. 指针接收

一、为猫类添加setAge方法,使用实例接收

//设置猫的年龄
func (c Cat) setAge(a int) {
	c.age = a
}

有些同学不理解这个,我们可以换另一种方式理解。先将setAge就当作是一个普通的函数,只不过在形参中将实例安插进来,如下:

Go开发 结构体方法详解「终于解决」_https://bianchenghao6.com/blog_go_第1张

这样看就一下理解了,我们可以认为两者是等价的。

二、为猫类添加setAge方法,使用指针接收

//设置猫的年龄
func (c *Cat) setAge(a int) {
	c.age = a
}

同理,它也等价于下面的普通函数调用

func setAge(c *Cat, a int) {
	c.age = a
}

基础类型和指针类型的互相转换

首先,我们给出两条结论:

  1. 基础类型可以调用类的任何方法
  2. 指针类型可以调用类的任何方法

也就是说,不管实例或者指针,都可以调用该类的任何方法,只不过在具体调用过程中会发生转换,我们重点看下不同的调用。

一、基础类型调用指针接收器的方法

//定义猫类
type Cat struct {
	age int
}

//设置猫的年龄
func (c *Cat) setAge(a int) {
	c.age = a
}
func main() {
	var cat = Cat{
		age: 2,
	}
	//基础类型调用指针的方法
	cat.setAge(3)
	fmt.Println(cat.age)
}

根据前面的推导,我们知道,指针接收器的方法就是指针做为形参的函数调用,既然需要的是指针,按照逻辑,应该传过去的是实例的地址。

因此,Go语言会将cat转换为&cat传过去,结果就是将原来猫的年龄修改了。

二、指针调用基础类型接收器的方法

//定义猫类
type Cat struct {
	age int
}

//设置猫的年龄
func (c Cat) setAge(a int) {
	c.age = a
}
func main() {
	var cat = &Cat{
		age: 2,
	}
	//指针调用基础类型的方法
	cat.setAge(3)
	fmt.Println(cat.age)
	//打印2
}

根据推导,基础类型接收器的方法就相当于实例做为形参的函数调用,既然需要的是实例,而这里调用的指针,按照逻辑,应该传过去的是该指针指向值的副本。

因此,Go语言会将cat取值复制一份过去,也就是*cat复制一份,这样一只猫变成两只猫,方法修改的是副本的值,原值不会变化。

总结

一、实例可以调用类的任何方法
二、指针可以调用类的任何方法
三、用实例值或指针类型调用方法时,编译器会自动在基础类型和指针类型之间转换

发表回复