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动词时打印的值相同。