看下面的示例:
```
package main
import "fmt"
type User struct {
ID int
Name string
}
func main() {
var arrTest = [...]int{1, 2, 3}
var mapTest = map[string]int{"zhe": 1, "xiao": 2}
var structTest = User{ID: 1, Name: "ZX"}
var intTest = 10
// 现在打印指针出来
fmt.Printf("%v\n%v\n%v\n%v\n", &arrTest, &mapTest, &structTest, &intTest)
}
```
打印结果为:
```
&[1 2 3]
&map[zhe:1 xiao:2]
&{1 ZX}
0xc042060080
```
是不是很好奇为什么整数的指针打印出来是一个内存地址,而是数组、字典、结构体打印出来的是一个带&符号的数据。
针对复合类型,数据的打印有如下规则:
```
struct: {field0 field1 ...}
array, slice: [elem0 elem1 ...]
maps: map[key1:value1 key2:value2]
pointer to above: &{}, &[], &map[]
```
所以使用print函数的时候,%v使用默认的规则,就会发生下面的情况:
1. 基础数据类型直接打印出内存地址
2. 符合数据类型打印出值并在值前面加&符号
为什么会出现这种规则呢?解释如下:
```
func Printf(format string, a ...interface{}) (n int, err error)
```
这个函数有个参数interface{},所以如果你传的值不属于interface{}类型,则就会使用上面的规则来把这个数据类型的值包起来(&{}, &[], &map[])。
针对上面的例子:structTest 是属于User类型, 打印的数据 &User 的类型是 *User 类型 。所以打印出来的结果是 &{1 ZX}。
```
fmt.Println(reflect.TypeOf(intTest)) // int
fmt.Println(reflect.TypeOf(structTest)) // main.User
```
正确输出复合类型的指针地址,则可以使用print的 %p 动词:
```
fmt.Printf("%p\n%p\n%p\n%p\n", &arrTest, &mapTest, &structTest, &intTest)
```
打印结果:
```
0xc04205e0c0
0xc042080018
0xc04205a3e0
0xc042060080
```
参考:
https://stackoverflow.com/questions/51018357/how-does-a-pointer-to-a-struct-or-array-value-in-go-work/51018395#51018395
https://stackoverflow.com/questions/42039827/difference-between-golang-pointers/42042673#42042673
有疑问加站长微信联系(非本文作者)