猿问

当参数不是 go 中的指针时,使用 reflect 通过引用更新值

我很难学习反射、指针和接口的基础知识,所以这是另一个我似乎无法弄清楚的入门级问题。


这段代码完成了我想要它做的事情——我正在使用反射将另一条记录添加到类型为接口的切片中。


package main


import (

  "reflect"

  "log"

)

type Person struct {

  Name string

}

func Add(slice interface{}) {

  s := reflect.ValueOf(slice).Elem()

  // in my actual code, p is declared via the use of reflect.New([Type])

  p := Person{Name:"Sam"}


  s.Set(reflect.Append(s,reflect.ValueOf(p)))

}


func main() {

  p := []Person{}

  Add(&p)

  log.Println(p)

}

如果我将 Add 和 main 功能更改为此,事情就不会按照我想要的方式工作。


func Add(slice interface{}) {

  s := reflect.ValueOf(&slice).Elem()

  p := Person{Name:"Sam"}


  s.Set(reflect.Append(reflect.ValueOf(slice),reflect.ValueOf(p)))

  log.Println(s)

}


func main() {

  p := []Person{}

  Add(p)

  log.Println(p)

}

也就是说,最后并没有像我希望的那样 log.Println(p)显示其中包含记录的切片。所以我的问题是,我是否有可能收到一个不是指针的切片,并且我仍然可以在其中编写一些代码来产生第一个场景中显示的结果?SamAdd()Add()


我最近的很多问题都围绕着这种主题,所以我仍然花了一些时间来弄清楚如何有效地使用反射包。


一只甜甜圈
浏览 97回答 1
1回答

呼唤远方

不,不可能在不传递指向切片的指针的情况下附加到函数中的切片。这与反射无关,而是与变量如何传递给函数有关。这是相同的代码,修改为不使用反射:package mainimport (        "log")type Person struct {        Name string}func AddWithPtr(slicep interface{}) {        sp := slicep.(*[]Person)        // This modifies p1 itself, since *sp IS p1        *sp = append(*sp, Person{"Sam"})}func Add(slice interface{}) {        // s is now a copy of p2        s := slice.([]Person)        sp := &s        // This modifies a copy of p2 (i.e. s), not p2 itself        *sp = append(*sp, Person{"Sam"})}func main() {        p1 := []Person{}        // This passes a reference to p1        AddWithPtr(&p1)        log.Println("Add with pointer:   ", p1)        p2 := []Person{}        // This passes a copy of p2        Add(p2)        log.Println("Add without pointer:", p2)}(上面,当它说切片的“副本”时,它并不意味着底层数据的副本 - 只是切片)当您传入一个切片时,该函数实际上得到一个新切片,该切片引用与原始数据相同的数据。附加到函数中的切片会增加新切片的长度,但不会更改传入的原始切片的长度。这就是原始切片保持不变的原因。
随时随地看视频慕课网APP

相关分类

Go
我要回答