当参数不是go中的指针时,使用反射通过引用更新值 [英] Using reflect to update value by reference when argument is not a pointer in go

查看:114
本文介绍了当参数不是go中的指针时,使用反射通过引用更新值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在学习go中的反射,指针和接口的基础时遇到了困难,所以这是我似乎无法弄清楚的另一个入门级问题.

I've had difficulty learning the basics of reflect, pointers and interface in go, so here's another entry level question I can't seem to figure out.

此代码完成了我想要的工作-我正在使用反射将另一个记录添加到键入为接口的切片中.

This code does what I want it to do - I'm using reflect to add another record to a slice that's typed as an interface.

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函数更改为此,那么事情将无法按照我想要的方式进行.

If I changed the Add and main function to this, things don't work the way I want it to.

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)并没有像我希望的那样显示带有记录Sam的切片. 所以我的问题是,是否有可能让Add()接收不是指针的切片,并且让我仍然在Add()中编写一些代码,以产生第一种情况下显示的结果?/strong>

That is, the log.Println(p) at the end doesn't show a slice with the record Sam in it like the way I had hoped. So my question is whether it's possible for me to have Add() receive a slice that is not a pointer, and for me to still write some code in Add() that will produce the outcome shown in my first scenario?

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

A lot of my recent questions dance around this kind of subject, so it's still taking me a while to figure out how to use the reflect package effectively.

推荐答案

否,如果不传入指向切片的指针,则无法将其追加到函数中.这与反射无关,但是与如何将变量传递给函数有关.这是相同的代码,修改为不使用反射:

No, it's not possible to append to a slice in a function without passing in a pointer to the slice. This isn't related to reflection, but to how variables are passed in to functions. Here's the same code, modified to not use reflection:

package main

import (
        "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)
}

(上面,当说切片的副本"时,并不意味着底层数据的副本-只是切片)

(Above, when it says 'copy' of the slice, it doesn't mean the copy of the underlying data - just the slice)

传递切片时,该函数有效地获取一个新切片,该切片引用与原始数据相同的数据.在函数中附加到切片会增加新切片的长度,但不会更改传入的原始切片的长度.这就是为什么原始切片保持不变的原因.

When you pass in a slice, the function effectively gets a new slice that refers to the same data as the original. Appending to the slice in the function increases the length of the new slice, but doesn't change the length of the original slice that was passed in. That's why the original slice remains unchanged.

这篇关于当参数不是go中的指针时,使用反射通过引用更新值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆