在Go中,要打印一个变量、结构、数组、片断、地图或任何其他结构的内存地址,你需要用地址操作符&
,生成一个指向该值的指针,然后使用 fmt.Println()
函数(或软件包中的任何其他打印函数 fmt
包中的任何其他打印函数)将该值的地址写入标准输出。如果你想把地址作为文本的一部分,你可以使用%p
格式动词在 fmt.Printf()
函数。
例1:打印一个变量的地址
// variable
i := 32
fmt.Println(&i)
// pointer to the variable
p := &i
fmt.Println(p)
输出
0xc00001c088
0xc00001c088
例2:格式化变量的地址
// variable
i := 32
fmt.Printf("Address of i=%d:\t%p\n", i, &i)
// pointer to the variable
p := &i
fmt.Printf("Address of p=&i=%d:\t%p\n", *p, p)
输出
Address of i=32: 0xc00001c088
Address of p=&i=32: 0xc00001c088
例3:格式化各种Go数据结构的地址:数组、片断、结构、结构域和地图
package main
import "fmt"
type A struct {
Number int
Text string
}
func main() {
// array
arr := [3]int{1, 2, 3}
fmt.Printf("Address of array = %v: %p\n", arr, &arr)
// slice
slice := []int{1, 2, 3}
fmt.Printf("Address of slice = %v: %p\n", slice, &slice)
// struct
structInstance := A{Number: 23, Text: "abc"}
fmt.Printf("Address of struct = %+v: %p\n", structInstance, &structInstance)
// struct field
fmt.Printf("Address of struct field = %s: %p\n", structInstance.Text, &structInstance.Text)
// map
mapInstance := map[int]int{
0: 1,
}
fmt.Printf("Address of map = %v: %p\n", mapInstance, &mapInstance)
}
输出
Address of array = [1 2 3]: 0xc0000b4000
Address of slice = [1 2 3]: 0xc0000a4018
Address of struct = {Number:23 Text:abc}: 0xc0000a4048
Address of struct field = abc: 0xc0000a4050
Address of map = map[0:1]: 0xc0000aa020
你可能知道,地图索引表达式是不可寻址的,所以不可能打印带有特定键的地图值的地址。
打印一个指针的地址
在例1和例2中,我们创建了一个类型为*int
的新指针p
,并为其分配了变量i
的地址。然后,我们用fmt.Println(p)
打印了指针p
的值,这个值就是变量i
的地址。由于指针本身是一个值,我们也可以用fmt.Println(&p)
来打印这个值的地址。比较打印变量i
的地址、p
的值和p
的指针的输出。
// get the address of a variable
i := 32
fmt.Printf("Address of i=%d: %p\n", i, &i)
// get the address the pointer points to
p := &i
fmt.Printf("Address of p=&i=%d: %p\n", *p, p)
// get the address of pointer
fmt.Printf("Address of pointer p=&i=%d: %p\n", *p, &p)
输出
Address of i=32: 0xc00001c088
Address of p=&i=32: 0xc00001c088
Address of pointer p=&i=32: 0xc00000e030
下图显示了内存中变量和指针之间的关系。
打印片状底层数组的地址
片断是值,所以要打印片断的地址,你需要使用地址操作符&
,就像你对普通变量一样。但是动词%p
对于片子也有特殊的意义。引用包的文档fmt
包的文档。
%p address of 0th element in base 16 notation, with leading 0x
要打印分片的第0个元素的地址,相当于分片底层数组的地址,你只需要使用%p
格式和分片值参数。请看下面的代码,比较一个例子数组的地址,通过 "切片 "数组创建的切片的地址,以及切片的第0个元素的地址(底层数组的地址)。
// print address of array
arr := [3]int{1, 2, 3}
fmt.Printf("Address of arr: %p\n", &arr)
// print address of slice
// "slicing" the array
slice := arr[:]
fmt.Printf("Address of slice: %p\n", &slice)
// print address of the slice underlying array
fmt.Printf("Address of the slice underlying array: %p\n", slice)
// print address of 0th element of the slice
fmt.Printf("Address of 0th element of the slice: %p\n", &slice[0])
输出
Address of arr: 0xc000014120
Address of slice: 0xc00000c030
Address of the slice underlying array: 0xc000014120
Address of 0th element of the slice: 0xc000014120
打印一个没有前导0x的地址
要打印没有前导0x的地址,使用带有#
标志的格式化指针动词:%#p
。
// print address of array
arr := [3]int{1, 2, 3}
fmt.Printf("Address of arr: %#p\n", &arr)
输出
Address of arr: c000014120
将一个地址分配给一个字符串
要获得一个变量的地址并将其分配给字符串,可以使用 fmt.Sprintf()
函数。
arr := [3]int{1, 2, 3}
addr := fmt.Sprintf("%p", &arr)
fmt.Println(addr)
输出
0xc0000b4000