Golang中的addressable

本文探讨了Go语言中对象函数调用的规则,特别是针对非指针接收者和指针接收者的函数。示例代码展示了直接通过结构体实例调用非指针方法是允许的,而调用指针方法则需要使用指针实例或`new()`函数。这涉及到Go语言的地址运算符和对象的addressable状态。官方文档指出,只有变量、间接指针或特定索引操作才是addressable,因此非指针实例无法直接调用指针方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我们来看下面一个示例程序,最下面的测试函数,其中有三行是正确的,一行是错误的,你知道为什么那一行是错的么?

package js

import (
	"fmt"
	"testing"
)

type Tester struct{}

func (t Tester) Operation1() {
	fmt.Println("first")
}

func (t *Tester) Operation2() {
	fmt.Println("second")
}

func TestNewTester(t *testing.T) {
	Tester{}.Operation1() //正确
	Tester{}.Operation2() //错误
	new(Tester).Operation2() //正确
    new(Tester).Operation1() //正确
}

有这么几个现象:

1)定义在对象上的函数,比如这个:

func (t Tester) Operation1() {
	fmt.Println("first")
}

是直接可以通过下面的方式调用的

Tester{}.Operation1() //正确

但是定义在指针上的函数,比如:

func (t *Tester) Operation2() {
	fmt.Println("second")
}

是不可以使用下面的方式调用的

Tester{}.Operation2() //错误

但是如果用new(Tester)定义出来的指针则都可以调用

new(Tester).Operation2() //正确
new(Tester).Operation1() //正确

如果没有测试过,我也一直有这么一种错觉,就是直接初始化的对象不能调用函数,但从上面我们就可以看出,中间还是有很多细微的地方。

那这是为什么呢?

应该是Tester{}这种方式定义出来的对象因为没有正式的指针引用过,是和reflect库提到过的一种叫addressable的状态有关。这种应该是还没有addressable,所以不能直接调用指针函数。

官方文档是这个

The Go Programming Language Specification - The Go Programming Language​go.dev/ref/spec#Address_operators

里面提到:

For an operand xof type T, the address operation &xgenerates a pointer of type *Tto x. The operand must be addressable, that is,  either a variable, pointer indirection, or slice indexing operation; or a field selector of an addressable struct operand; or an array indexing operation of an addressable array. As an exception to the addressability requirement, xmay also be a (possibly parenthesized) composite literal. If the evaluation of xwould cause a run-time panic, then the evaluation of &xdoes too.

加粗的部分是我加的,意思是只有变量,间接指针(比如一个实例对象的变量直接调指针函数,实际是编译器先转了一遍指针)或切片的index操作,才称之为addressable。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

百家饭AI

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值