admin

golang指针的区别

sql

我有两种变量。检查golang,我不明白为什么会这样。问题:我从中得到的Models应该是struct将它用于 GORMFirst()函数。

编码:

package main

import (
    "fmt"
)

type Test struct {
    Test string
}

var Models = map[string]interface{}{
    "test": newTest(),
}

func main() {
    test1 := Test{}
    fmt.Println("Test 1: ")
    fmt.Printf("%v", test1)
    fmt.Println()
    fmt.Println("Test 1 as pointer: ")
    fmt.Printf("%v", &test1)
    fmt.Println()
    test2 := Models["test"]
    fmt.Println("Test 2: ")
    fmt.Printf("%v", test2)
    fmt.Println()
    fmt.Println("Test 2 as pointer: ")
    fmt.Printf("%v", &test2)

}

func newTest() Test {
    var model Test 
    return model
}

阅读 212

收藏
2021-07-01

共1个答案

admin

TL;DR:在第一种情况下,您传递一个 type 值*Test用于打印,但在第二种情况下,您传递一个 type 值*interface{}!在%v使用默认格式,但默认格式动词手段格式取决于值的类型。


您看到的区别只是fmt包实现的默认格式规则。

您正在使用fmt.Printf()

func Printf(format string, a ...interface{}) (n int, err error)

它将格式字符串和其他参数作为 type interface{}。所以请注意,如果您传递的值不是 type interface{},则该值将被包装在 type 值中interface{}

现在让我们看看你的例子:

test1 := Test{}
// ...
fmt.Printf("%v", &test1)

test1是 type Test,你通过&test1哪个 type *Test。这将被包裹在一个interface{}. 来自包文档的格式规则fmt

对于复合对象,元素使用这些规则递归打印,布局如下:

golang struct: {field0 field1 ...} array, slice: [elem0 elem1 ...] maps: map[key1:value1 key2:value2] pointer to above: &{}, &[], &map[]

由于它是指向 a 的指针struct,因此&{}将使用该格式。Test有一个 field Test string,但你没有设置它的值,所以它默认为空 string类型的零值。这就是为什么在显示时您什么也看不到的原因。请注意,如果您像这样初始化它:string``""

test1 := Test{"a"}

输出将是:

&{a}

让我们看看你的第二个例子:

test2 := Models["test"]
// ...
fmt.Printf("%v", &test2)

第一行是一个简短的变量声明,test2从右边的表达式推断类型。右手边的表达式是一个索引表达式,索引地图。它的类型将是地图的值类型,并且由于类型Modelsmap[string]interface{},类型test2将是interface{}

到现在为止还挺好。但是当您尝试打印它时会发生什么fmt.Printf("%v", &test2)?您传递了一个指向test2which 类型的指针interface{},因此您传递的是 type *interface{},并且由于这与 不同interface{},它将被包装在另一个interface{}值中。

所以传递给的fmt.Printf()是一个interface{}值,包装一个*interface{}值作为test2变量的地址。

现在适用于此处的格式规则:

%v 的默认格式是:

golang bool: %t int, int8 etc.: %d uint, uint8 etc.: %d, %x if printed with %#v float32, complex64, etc: %g string: %s chan: %p pointer: %p

由于要格式化的值是一个指针 ( *interface{}),因此%v将默认为%p,即:

指针:

golang %p base 16 notation, with leading 0x

所以结果是以十六进制格式正确打印地址值,例如:

0x1040a160

要从中获取结构test2,可以使用类型断言。所以它应该是这样的:

t2 := Models["test"]
test2 := t2.(Test) // test2 is of type Test

test2与 的类型相同test1,并且在打印时会产生相同的结果。在Go Playground上试一试。

最好将*Test值存储在映射中,因此不需要类型断言甚至存储在局部变量中,因为interface{}存储在映射中的已经是指向 的指针Test,可以按原样使用/传递。

2021-07-01