复合与基础的数据结构类型 在Go语言中指针输出的表现方式

看下面的示例:

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

共 0 个回复