go在方法中修改结构体的值_Go - 29 Go 结构体之方法

本文介绍了Go语言中如何在结构体方法中修改结构体值,详细阐述了方法的基本使用、调用机制、声明定义以及注意事项。通过示例展示了如何通过结构体指针来修改值,并提供了实现String方法的示例。同时,讨论了方法与函数的区别,强调了接收者类型对值传递的影响。
摘要由CSDN通过智能技术生成

基本介绍

在某些情况下,我们需要声明(定义)方法,比如Person结构体,除了有一些字段外(年龄,姓名...), Person结构体还有一些行为比如:可以说话,跑步...通过学习,还可以做算术题,这时就要用方法才能完成;

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

基本使用:

type Person struct {

Name string

Age  int

}

func (p Person) eat() {

fmt.Println(p.Name, "可以吃东西~~~")

}

func main() {

// 结构体的方法

var p Person

p.Name = "mary"

p.Age = 30

// 调用方法

p.eat()    // mary 可以吃东西~~~

}

上面的一个说明:

1.eat方法和Person 类型绑定;

2.eat方法只能通过Person类型的变量来调用,而不能直接调用,也不能使用其他类型变量来调用。

3.func (p Person)eat() {} ---> p 表示哪个Person变量调用,这个p就是他的副本,这点和函数传参非常相似。

4. p这个名字,由程序员指定,不是固定;

方法的调用和传参机制

1.在通过一个变量去调用方法时,其调用机制和函数一样

2.不一样的地方是,变量调用方法时,该变量本身也会作为一个参数传递到方法(如果变量是值类型,则进行值拷贝,如果变量是引用类型,则进行地址拷贝)

方法的声明(定义)

func (recevier  type)  methodName (参数列表) (返回值列表){

方法体

return  返回值

}

参数列表,表示方法输入;

receiver  type : 表示这个方法和type这个类型进行绑定,或者说该方法作用于type类型;

receiver  type:  type 表示可以是结构体,也可以是其他的自定义类型;

receiver: 就是type类型的一个变量(实例),比如:Person结构体的一个变量(实例)

返回值列表,表示返回的值,可以多个

方法主体,表示为了实现某一功能代码块

return 语句不是必须的(有返回值列表就必须有return);

方法注意事项和细节

1.结构体类型是值类型,在方法调用中,遵守值类型的传递机制,是值拷贝传递方式;

2.如果程序员希望在方法中,修改结构体变量的值,可以通过结构体指针的方式来处理

3.Golang中的方法作用在指定的数据类型上的(即:和指定的数据类型绑定)因此自定义类型,都可以有方法,而不仅仅是struct, 比如int,float32等都可以有方法;

4.方法的访问范围控制的规则,和函数一样,方法名首字母小写,只能在本包访问,方法首字母大写,可以在本包和其他包访问;

5.如果一个类型实现了String() 这个方法,那么fmt.Println 默认会调用这个变量的String() 进行输出;

示例:

type Circle struct {

Radius float64

}

// 为了提高效率,通常我们方法和结构体的指针类型绑定

func (c *Circle) area() float64 {

// 因为 c 是指针,因此我们标准的访问其字段方式 是 (*c).Radius

// return 3.14 * (*c).Radius * (*c).Radius

// (*c).radius 等价  c.radius

c.Radius = 10

return 3.14 * c.Radius * c.Radius

}

// 创建一个Circle 变量

var c Circle

// res := (&c).area()

// 编译器底层做了优化 (&c).area() 等价 c.area()

// 因为编译器会自动的给加上  &c

c.Radius = 7.0

res := c.area()

fmt.Println("面积是:", res)  // 面积是: 314

fmt.Println("c.Radius==", c.Radius)  // c.Radius== 10

实现String方法:

// 让student 结构体实现 String方法

type Student struct {

Name string

Age  int

}

func (s *Student) String() string {

str := fmt.Sprintf("Name=[%v] Age=[%v]", s.Name, s.Age)

return str

}

var s Student

s.Name = "smith"

s.Age = 30

// 没实现 String方法时,会打印出 &{smith 30}, 但是实现以后 Name=[smith] Age=[30]

fmt.Println(&s)

练习:

结构体实现乘法表打印与二维数组简单转置方法

// 结构体 MethodUtils

type MethodUtils struct {

// 结构体也可以没有字段

}

// 打印乘法表

func (mu MethodUtils) cfb(n int) {

for i := 1; i <= n; i ++ {

for j := 1; j <= i; j ++ {

fmt.Printf("%v * %v = %v ", j, i, i * j)

}

fmt.Println()

}

}

// 转置

func (mu MethodUtils) zz(ewz [3][3]int) {

// 原始打印

for _, v := range ewz {

for _, v2 := range v {

fmt.Printf("%v ", v2)

}

fmt.Println()

}

// 转置打印

for i := 0 ; i 

for j := 0; j 

fmt.Printf("%v ", ewz[j][i])

}

fmt.Println()

}

}

// 实例化

var mu MethodUtils

// 方法调用

mu.cfb(9)

var ewz = [3][3]int {{1,2,3},{4,5,6},{7,8,9}}

mu.zz(ewz)

方法与函数的区别

1.调用方式不一样;

函数的调用方式:  函数名(实参列表)

方法调用方式:     变量.方法名(实参列表)

2.对于普通函数,接收者为值类型时,不能将指针类型的数据直接传递,反之亦然;

3.对于方法(如struct的方法),接收者为值类型时,可以直接用指针类型的变量调用方法,反过来同样也可以;

不管调用形式如何,真正决定是值拷贝还是地址拷贝,看这个方法或函数定义的时候和哪个类型绑定的:

如果和值类型,比如(p  Person) 则是值拷贝;如果是和指针类型,比如是(p *Person) 则是地址拷贝;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值