【问题标题】:Confusion with pointer, slices and interface{} in function arguments in gogo中函数参数中的指针、切片和接口{}混淆
【发布时间】:2019-02-05 13:47:24
【问题描述】:

我一直在阅读 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 的比萨饼 0 到 9。我知道在我的示例中,我的 DoSomething 函数收到了业务切片的副本,因此,我的 main 函数中的 business 变量不受 DoSomething 所做的任何影响。

接下来我将func DoSomething(b []Business) 更改为func DoSomething(b interface{})。现在,当我尝试运行我的脚本时,我在z := reflect.New(v.Type().Elem()) 行上收到了panic: reflect: Elem of invalid type on 的运行时错误

我注意到DoSomething(b []Business) 的变量i == &amp;[]。但是对于DoSomething(b interface{}),变量i == 0xc42000e1d0。为什么这两种情况下变量i不一样?

【问题讨论】:

  • 虽然DoSomething 收到了切片的副本,但它们仍然指向同一个底层数组。因此,对DoSomething 中的切片所做的任何更改仍然会对您的主函数中的business 切片产生影响。 blog.golang.org/go-slices-usage-and-internals
  • @Gavin 几天来,人们对切片如何通过引用作为函数中的参数有效传递的类似说法感到困惑。导致这种困惑的是,在我的许多实验中,即使是最小的实验,我在我的代码中引入了slice = append(slice, newitem)。所以我从来没有观察到通过引用传递切片的行为,我很沮丧我怎么可能误解了每个人在说的话。学习一门新语言的痛苦...

标签: pointers go slice go-interface


【解决方案1】:

您的调试器最有可能使用(或至少遵循)fmt 包的默认格式规则:

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

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

在您的第一种情况下,i 拥有一个 *[]Business 类型的值。因此,如果正在打印(或检查)的值是指向切片的指针,则将其打印为 &amp;[values]

在第二种情况下,i 持有一个指向 interface{} 值的指针,该值的类型为 *interface{}。打印这种类型的值时,使用默认的%p 格式,它只是将内存地址打印为前缀为0x 的十六进制值。

【讨论】:

    猜你喜欢
    • 2017-07-04
    • 2016-07-17
    • 1970-01-01
    • 1970-01-01
    • 2017-07-25
    • 2017-10-03
    • 1970-01-01
    • 2015-09-12
    • 2020-10-07
    相关资源
    最近更新 更多