Go中取址符(&)取的到底是内存地址,还是指针变量?

最近在书上看到一个例子:

package main

import "fmt"

func main() {
    var a = [3]int{1, 2, 3}
    var b = &a // & 应该是取址符,变量b就应该是数组a在内存中的地址,那么为什么b[1]可以自加
    b[1]++
    fmt.Println(a, *b)
}

对于取址符有了一些疑问,根据这个例子,单独写了一段demo代码:

package main

import "fmt"

func main() {
    var a = []int{1,2,3} // or var a = 3
    var b = &a
    fmt.Println(b)
}

经过测试dmeo代码中,如果变量a为基本类型(例如:int、float、string等),则变量b返回的就是变量a在内存中的地址,但是如果变量a为复合类型(例如:数组、切片),则变量b返回的是指针变量,且可以当作复合类型的变量直接使用(例如:b[1]++),为什么Go中的&符返回的东西不一致呢?

已邀请:

Chaofei

赞同来自: netuser

个人理解: & 取的就是地址 你用 fmt.Println() 去打印这个变量,其实是调用了这个变量类型的 String() 方法,可以试试 println() 打印原始值。

func main() {
    var a = []int{1, 2, 3} // or var a = 3
    var b = &a
    println(b) // 0xc00008a000
    fmt.Println(b) // &[1 2 3]                        
}
type Custom [3]int                

func main() {
    var a Custom = [3]int{1, 2, 3}
    fmt.Println(&a) // &[1 2 3]
}
type Custom [3]int                

func (c *Custom) String() string {
    return "*Custom"
}

func main() {
    var a Custom = [3]int{1, 2, 3}
    fmt.Println(&a) // *Custom
}

另外指针类型 b[1]++, 可能是 go 内部做了解引用操作,当执行 b[1]++ 时如果是指针类型是数组,就自动解引用 (*b)[1]++,类似于下边:

type A struct {              
    value int
}

func main() {
    a := A{1}
    b := &a
    fmt.Println(a.value) // 1
    fmt.Println(b.value) // 1
    fmt.Println((*b).value) // 1
}

h12 - https://h12.io/about

赞同来自: ldh33514

取地址就是取变量的地址,如果变量是slice就取slice的地址(slice wrapper struct的地址),如果是array就取array的地址(等于第一个元素的地址)。 http://golang.org/ref/spec#Address_operators 这一点没有异议。

奇葩点在于数组的指针可以当作数组变量本身来做indexing操作,这个完全就是兼容C语言指针用法的语法糖了。 https://golang.org/ref/spec#Index_expressions

LazyboyChen7 - 这个人很懒,什么都没有留下。

赞同来自:

    var c = []int{1,2,3}
    var d = &c
    fmt.Println(reflect.TypeOf(d))   // *[]int

    var e int = 5
    var f = &e
    fmt.Println(reflect.TypeOf(f))  // *int

xiaoma

赞同来自:

Go语言中数组是值语义。一个数组变量即表示整个数组,它并不是隐式的指向第一个元素的指针(比如C语言的数组),而是一个完整的值。如果数组较大的话,数组的赋值也会有较大的开销。为了避免复制数组带来的开销,可以传递一个指向数组的指针,但是数组指针并不是数组。 ————by advanced-go-programming-book

haohongfan - talk is expensive, just show code

赞同来自:

For a of pointer to array type: a[x] is shorthand for (*a)[x]

golang是没有指针操作的, 所以不会出现像c/c++这样的题:

#include <stdio.h>
int a[2] = {1,2};
int main(){
        printf("a = %p\n", a); // I
        printf("&a = %p\n", &a); // II
        printf("a + 1 = %p\n", a + 1);// III
        printf("&a + 1 = %p\n", &a + 1);// IV
        return 0;
}

所以不用考虑那么复杂: [] 优先级大于 ++, 故b[1]++ 就是(*b)[1]++, 所以结果就是[ 1, 3, 3]

要回复问题请先登录注册