Go Struct function “指针接收者” 与 “值接收者” 区别

2024-05-10 17:53:32 浏览数 (1)

概念

在 Go 语言中,函数与方法代表不同的概念,函数是独立的,方法是指结构体方法,它依赖于结构体,但两者皆以关键字 func 定义,只是定义方式略有不同。

代码语言:javascript复制
type person struct {
    // 定义结构体    
    name   string    
    weight int
}

// 指针接收者
func (p *person) get_name(name string) string {    
    // 定义结构体方法    
    return name
}

// 值接收者
func (p person) get_name(name string) string {
    // 定义结构体方法    
    return name
}

“结构体方法” 与 “函数” 的区别,在于结构体方法必须在关键字和方法名称之间使用小括号声明结构体变量(称为值接收者)或结构体的指针变量(称为指针接收者)。

“指针接收者” 和 “值接收者” 的区别:

  1. 值接收者通过数据拷贝方式传递给方法,在结构体属性数据较多时,值接收者方式占用资源较多。
  2. 如果需要修改结构体成员原有的数据,则只能使用指针接收者。由于值接收者通过数据拷贝方式传递,因此在方法中修改结构体成员值不会改变结构体成员的原有值。
  3. 无论结构体方法是指针接收者还是值接收者,结构体方法的调用方式都是一样的。

示例

以下是一个对比 “值接收者” 和 “指针接收者” 区别的例子:struct_function_receiver.go

代码语言:javascript复制
package main

import "fmt"

type person struct {
   // 定义结构体
   name   string
   weight int
}

func (p *person) setWeigthPointer(weight int) {

   p.weight = weight

}

func (p person) setWeigthValue(weight int) {

   p.weight = weight
   fmt.Println(p.weight)

}

func main() {
   p1 := person{}

   p1.init("Tom", 99)
   fmt.Println(p1)
   p1.setWeigthPointer(100)
   fmt.Println(p1)

   p2 := person{}

   p2.init("Json", 99)
   fmt.Println(p2)
   p2.setWeigthValue(200)
   fmt.Println(p2)

   // p2 weight 值未变,这就是 “值接收者” 和 “指针接收者” 的区别。
   // “值接收者” 是基于原对象,有生成了一个函数上下文里的局部对象。
}

>> 打印数据
{Tom 99}
{Tom 100}
{Json 99}
200      
{Json 99}

总结

  1. “值接收者” 方式
    1. 基于原来的 Struct 拷贝了一个新的 Struct,在 New Struct 的基础上执行 function。因此,对 Source Struct 是没有影响的。
    2. 这种方式不改变 Source Struct 中的属性数据,那么应用场景只能是获取 Source Struct 中的数据,然后通过计算获取一个 return 值,供调用方使用,才有使用价值了。
  2. “指针接收者”
    1. 使用的就是原来的那个结构体,可以改变原结构体成员的值。
    2. 一般来说,使用 “指针接收者” 就足够了,我们的大部分场景是使用 “指针接收者”,即使不理解二者的区别的话,记住这个默认规则就可以了。
    3. Java 中函数方式的入参使用的是对象引用,这个对象引用就是 Go 里的 “指针接收者”。
  3. 两种方式在使用时,语法上没有什么区别,都是 structName.methodName 。
go

0 人点赞