Pointer 和 Non-Poiner 方法 区别

在Go里,receiver是关联在某个结构体上的,定义后,可以像方法一样调用它。例如,下面代码中的 func(d Dog)

package main

import "fmt"

type Dog struct {
}

func (d Dog) Say() {
    fmt.Println("Woof!")
}

func main() {
    d := &Dog{}
    d.Say()
}

Go可以定义指针和非指针receiver,前者类似func (t *Type) 后者类似func (t Type),官网的这篇文章已经说明了两者具体的行为。

在C语言里,指针是要使用->操作符,而结构体方法的调用是使用.操作符,如下:

#include <stdio.h>
#include <stdlib.h>

struct Tree {
    int a;
    int b;
};

int main() {
    struct Tree tree, *pointerToTree;
    tree.a = 5;
    tree.b = 7;
    pointerToTree = malloc(sizeof(struct Tree));
    pointerToTree->a = 5;
    pointerToTree->b = 7;
    printf("tree vals: %d %d\n", tree.a, tree.b);
    printf("pointerToTree: %p %d %d\n", pointerToTree, pointerToTree->a, pointerToTree->b);
    free(pointerToTree);
    return 0;
}

Go类型系统有如下规定:
如果类型 x包含m方法,而且它的参数列表和m的参数列表一致,那么使用x.m()调用该方法是有效的。如果x是可寻址的,且&x 的方法集合包含m,那么,x.m() 也可以调用,可以理解为是 (&x).m() 的简略形式。

Receiver 定义为指针或者非指针,会导致不同的行为。我们在做设计和考虑时,可以假设该 receiver 需要被当做参数来传递,可以按该假设将receiver定义为传值或传引用:

  1. receiver 需要被修改
  2. struct 比较大,深拷贝操作代价较大
  3. 一致性:如果struct 部分的方法有指针类型receiver,那么其余的也应该如此,这样struct的行为是比较明确的。

如果你的方法调用有以上三个特点,那么使用指针类型的receiver

package main

import "fmt"

type Mutatable struct {
    a int
    b int
}

func (m Mutatable) StayTheSame() {
    m.a = 5
    m.b = 7
}

func (m *Mutatable) Mutate() {
    m.a = 5
    m.b = 7
}

func main() {
    m := &Mutatable{0, 0}
    fmt.Println(m)
    m.StayTheSame()
    fmt.Println(m)
    m.Mutate()
    fmt.Println(m)
}

你会注意到,StayTheSame 定义了非指针的receiver,不会改变struct,和 Mutate 定义了指针类型,会改变struct。

提供Golang直播培训,3人开班,有需要请站短。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值