Golang的可直接取地址addressable

文章详细阐述了Go语言中哪些情况可以对值取地址,包括变量、复合类型字面量初始化以及特定的表达式情况。强调了字面量中的例外,如复合类型的初始化可以取地址,而其他如常量、函数等则不行。同时,讨论了表达式中的间接变量、切片和数组索引、结构体字段选择器等特殊情况。最后指出,取地址的原因在于只有可取地址的值才能被赋值。
摘要由CSDN通过智能技术生成

先说结论

可以直接取地址,就是可以在expression侧直接用&操作符,其范围仅仅为:

1、变量都可取地址

2、字面量--复合类型初始化。

3、表达式---迂回指针和变量嵌套。

一个原则

可取地址,就代表该值在内存中可见,可寻找。

以赋值操作为例,变量名v = 变量值expression,整体作为一个变量。expression初始化了一个值,然后赋值给变量名v(变量名就是一个内存地址),这个值才拥有一个地址。才可见,可寻找。

var v type = expression

变量名v其实就是内存地址的一个助记符,代表整个变量。(类型type用于编译器确定分配的内存大小空间,expression提供一个该类型的值。)

大原则:只要是变量都是可以取地址的。

字面量例外

1、字面量是不可取地址的,但是作为例外,复合类型字面量的初始化,是可以取地址的,相当于初始化了复合类型和该值的指针。这是一个例外。

[复合类型]: arrays, slices ,struct,map

x := &People{"name"}

常见的字面量都是常量。常量没有地址,常量通常会被编译器在预处理阶段直接展开,作为指令数据使用。它和内存没有映射关系。

[引用类型]:pointer,function,channel ,slice ,map 。引用类型都是有地址的,但是其字面量却只有slice和map可取地址,pointer、function、channel都无法取地址,可能是出于安全考虑。

注意,这个例外只是在字面量的前提下,make和new的复合类型都是不能取地址的。

表达式例外

1、间接变量

pointer indirection 迂回指针(取值操作)

理解:间接变量,取值操作,就是取到了变量,是可以进行取地址操作,符合大原则。

x := 2 
xx := &x 
y := &*xx

2、变量的嵌套key,也是变量

如果有下层嵌套的key,主要看上层是不是变量(或间接变量)

2.1、slice indexing operation

理解:切片因为是引用类型的,天生初始化的时候就有地址的(可以视为变量),索引操作其实就是进行了偏移,能得到地址。

x := []int{1, 2, 3} 
xx := &x[2]

同样的,如果切片没有赋值给变量x,那么切片本身是个引用类型本身初始化的时候是有地址的。因此也是可以获取地址的。

x := &([]int{1, 2, 3}[2])

2.2、an array indexing operation of an addressable array

理解:道理和slice一样,只不过slice是引用类型,初始化的时候会自带地址。而array作为基本值类型,初始化的时候不会初始化地址。

数组赋值给变量x,拥有地址(可视为变量),所以其索引操作也可以取地址。

x := [3]int{1,2,3} 
xx := &x[0]

而如果数组没有地址的话,那么其索引操作便无法取地址。

x := &[3]int{1,2,3}[0] //error,这点和slice不同,因为key的父节点不是变量

2.3、a field selector of an addressable struct operand

理解:struct有地址,那么字段就有地址。编译器会计算每个字段的偏移,和slice有点类似,能计算每个字段的地址。

People作为变量名p,因此是可寻址的,所以其字段也可以寻址。

p := People{"p"} 
pp := &p.Name

相反的,如果struct初始化的时候没有分配地址(不可视为变量),那么其字段就无法取地址

p := &(People{"p"}.Name) //error

如果给struct初始化的时候,也初始化其地址,就可以取地址了。

p := &((&People{"p"}).Name)

注意1: expression如果是map是嵌套key不能取地址

理解:map在rehash的时候,是隐式的,不像slice会把重新分配的地址显示返回。所以为了安全,不提供key的取地址操作。这个嵌套的key也是个例外。

m := &map[string]int{"name":1}["name"] //error

注意2: expression如果是方法调用不能取地址

理解:如果了解方法调用时的内存分配,返回值的值在调用栈,返回值的变量在被调用栈中。因此返回值在调用者的作用域内,地址不可见。

总结

可以取地址的仅仅为:

1、变量都可取地址

2、字面量--复合类型初始化。

3、表达式---迂回指针和变量嵌套。

为什么要取地址

只有可取地址的值,才能被赋值。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值