我一直在学习Go如何通过指针与值将参数传递给函数。我一直在阅读有关接口类型的信息。而且我一直在篡改反射包。但是很明显,由于这里的示例代码,我仍然不明白它是如何工作的:
package main
import (
"reflect"
"fmt"
)
type Business struct {
Name string
}
func DoSomething(b []Business) {
var i interface{}
i = &b
v := reflect.ValueOf(i).Elem()
for c:=0 ;c<10; c++ {
z := reflect.New(v.Type().Elem())
s := reflect.ValueOf(z.Interface()).Elem()
s.Field(0).SetString("Pizza Store "+ fmt.Sprintf("%v",c))
v.Set(reflect.Append(v, z.Elem()))
}
fmt.Println(b)
}
func main() {
business := []Business{}
DoSomething(business)
}
运行此代码时,它将打印包含Business.Name为Pizza 0到9的10个业务结构的列表。我了解在我的示例中,我的DoSomething
函数收到了切片的副本业务,因此,我的主要功能中的business
变量不受DoSomething
的影响。
接下来我要做的就是将我的func DoSomething(b []Business)
更改为func DoSomething(b interface{})
。现在,当我尝试运行脚本时,在行panic: reflect: Elem of invalid type on
上出现了z := reflect.New(v.Type().Elem())
的运行时错误
我注意到使用DoSomething(b []Business)
,变量i == &[]
。但是对于DoSomething(b interface{})
,变量i == 0xc42000e1d0
。在这两种情况下,变量i
为什么不同?
答案 0 :(得分:2)
您的调试器最有可能使用(或至少遵循)fmt
包的默认格式设置规则:
对于复合对象,使用以下规则递归地打印元素,如下所示:
struct: {field0 field1 ...} array, slice: [elem0 elem1 ...] maps: map[key1:value1 key2:value2 ...] pointer to above: &{}, &[], &map[]
在您的第一种情况下,i
拥有类型为*[]Business
的值。因此,如果要打印(或检查)的值是切片的指针,则将其打印为&[values]
。
在第二种情况下,i
持有指向interface{}
类型的*interface{}
值的指针。打印此类型的值时,将使用默认的%p
格式,该格式仅将内存地址打印为前缀为0x
的十六进制值。