与go中的函数参数中的指针,切片和接口{}混淆

问题描述 投票:1回答:1

我一直在阅读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个业务结构列表,其中包含Pizza 0到9的Business.Name。我理解在我的例子中,我的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不同?

pointers go slice go-interface
1个回答
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的十六进制值。

© www.soinside.com 2019 - 2024. All rights reserved.