pointers - go中函数参数中的指针、切片和接口{}混淆
问题描述
我一直在阅读有关 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)
}
当我运行此代码时,它将打印一个包含 10 个业务结构的列表,其中 Business.Name 的比萨饼 0 到 9。我知道在我的示例中,我的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
在这两种情况下变量不同?
解决方案
您的调试器最有可能使用(或至少遵循)fmt
包的默认格式规则:
对于复合对象,使用这些规则以递归方式打印元素,布局如下:
struct: {field0 field1 ...} array, slice: [elem0 elem1 ...] maps: map[key1:value1 key2:value2 ...] pointer to above: &{}, &[], &map[]
在您的第一种情况下i
,它的值是 type *[]Business
。因此,如果正在打印(或检查)的值是指向切片的指针,则将其打印为&[values]
.
在你的第二种情况下,i
持有一个指向interface{}
类型的值的指针*interface{}
。打印这种类型的值时,使用默认%p
格式,它只是将内存地址打印为前缀为 的十六进制值0x
。
推荐阅读
- java - Android studio NumberFormatException 导致崩溃
- python - 列表的组合
- java - 如何从 Firebase 播放 mp3?
- angular - 使用可观察的更改调用管道
- macos - VirtualBox - Mac OSX 主机上的 Lubuntu 18.10 没有声音
- autodesk-forge - 为什么在尝试使用 Design Automation API 发布新活动时出现内部服务器错误?
- django - Django JSONField 动态包含和键查找
- project-reactor - Reactor StepVerifier 测试因 blockFirst() 而失败
- python - 在一个时间间隔内运行一些指令集
- c++ - C2440:“=”:无法从“const char [9]”转换为“char*”