【问题标题】:How can I choose which struct member to update at runtime?如何选择在运行时更新哪个结构成员?
【发布时间】:2020-06-01 02:13:34
【问题描述】:

假设我在 Go 中有一个如下所示的结构:

LastUpdate struct {
     Name string `yaml:"name"`
     Address string `yaml:"address"`
     Phone string `yaml:"phone"`
}

现在假设我想创建一个接受字段名称(例如“电话”)的函数,然后将该字段更新为一个值,例如今天的日期。

如何构建函数以使其接受字段名称并在结构中更新该字段?

我知道我可以为每个场景创建一个 IF 子句(如果 field == "Phone"){var.LastUpdate.Phone = time.Now().Date()},但我想构建这个函数,这样我以后每次向该结构添加新成员时都不必添加 IF 子句。想法?

【问题讨论】:

  • 标准库中的reflect 包可以对结构等类型进行自省。需要按顺序遍历字段以按名称查找。设置字段值是可能的,但在传入可能不兼容的值(或类型)时会变得非常棘手。这是一个滑坡,不适合胆小的人。如果您是 go 的新手,我强烈建议您不要这样做。
  • 这能回答你的问题吗? Golang dynamic access to a struct property

标签: go data-structures struct updates


【解决方案1】:

使用reflect 包按名称设置字段。

// setFieldByName sets field with given name to specified value.
// The structPtr argument must be a pointer to a struct. The
// value argument must be assignable to the field.
func setFieldByName(structPtr interface{}, name string, value interface{}) error {

    v := reflect.ValueOf(structPtr)
    v = v.Elem()            // deference pointer
    v = v.FieldByName(name) // get field with specified name

    if !v.IsValid() {
        return errors.New("field not found")
    }

    v.Set(reflect.ValueOf(value))

    return nil
}

像这样使用它:

var lu LastUpdate
setFieldByName(&lu, "Name", "Russ Cox")

Run it on the Playground

【讨论】:

  • 完美,这正是我想要的!谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-20
  • 1970-01-01
  • 2013-12-14
  • 2023-02-16
  • 1970-01-01
相关资源
最近更新 更多