3

我对golang很陌生。在这里,我有一个问题让我困惑了一段时间。我知道我们应该使用“&”来获取地址,但是如果我们在没有“&”的切片上使用 printf 怎么办?

package main

import "fmt"

var slice = []int{1, 2, 3, 4}

func main() {

   fmt.Printf("address of slice %p \n", slice)

   fmt.Printf("address of slice %p \n", &slice)

}

结果在我的 MacBook 上是这样的:

切片0x11354d0的地址

切片0x1128be0的地址

先感谢您!

4

1 回答 1

9

Go 中的切片是小型的、类似结构的数据结构,指向一个实际保存切片元素的后备数组。切片标头可以使用以下类型建模reflect.SliceHeader

type SliceHeader struct {
        Data uintptr
        Len  int
        Cap  int
}

引用fmt动词的包文档%p

印刷:

动词:

片:

%p    address of 0th element in base 16 notation, with leading 0x

指针:

%p    base 16 notation, with leading 0x
The %b, %d, %o, %x and %X verbs also work with pointers,
formatting the value exactly as if it were an integer.

所以确实,为动词传递一个切片值会%p打印第 0 个元素的地址,这是后备数组的第 0 个元素,当你传递&slicefor%p时,它将打印切片头的地址(因为&slice已经是一个指针值)。

为了验证,还要显式打印第 0 个元素的地址:

fmt.Printf("address of slice %p \n", slice)
fmt.Printf("address of slice %p \n", &slice)
fmt.Println(&slice[0])

输出将是(在Go Playground上尝试):

address of slice 0x170460 
address of slice 0x17d0b8 
0x170460

如您所见,与for&slice[0]的值相同。%pslice

现在让我们修改示例以使用我们自己的支持数组:

var arr = [4]int{1, 2, 3, 4}
var slice = arr[:]

所以这样我们也可以打印后备数组的第 0 个元素的地址:

fmt.Printf("address of slice %p \n", slice)
fmt.Printf("address of slice %p \n", &slice)
fmt.Println(&slice[0])
fmt.Printf("Array 0th: %p", &arr[0])

输出(在Go Playground上试试):

address of slice 0x170460 
address of slice 0x183e78 
0x170460
Array 0th: 0x170460

是的,支持数组的第 0 个元素的地址确实与切片的第 0 个元素的地址相同,这与slice传递给%p动词时打印的值相同。

于 2018-09-18T06:51:50.430 回答