获取已知结构字段的名称

时间:2013-01-25 02:18:23

标签: go

我有一个表示数据库中对象的结构,如:

type Object struct {
    Id string
    Field1 string
    Field2 int
}

我希望有一个函数可以在修改字段时更新数据库中的特定字段,具体如下:

func (self *Object) SetField1(value string) {
    self.Field1 = value
    database.Update(self.Id, "Field1", self.Field1) // pseudocode
}

有没有办法替换"Field1"硬编码字符串,以便我的代码能够抵抗结构字段排序和命名的未来变化?

我在反射包周围戳了一下,能够获得表示我正在使用的字段的StructField会很好,但它似乎需要通过硬编码字符串的字段名称,或结构中的字段索引(可能会发生变化)。

2 个答案:

答案 0 :(得分:6)

不在你所谈论的背景下。它不作为参数传入,因此您需要一些其他方法来指定要发送的结构字段的。这里的心理差距是你试图将那个集合函数视为一个属性,而不是它;如其他语言所示,属性之间的关键区别在于属性绑定到特定的字段,而您的SetField1方法绑定到整个结构。该方法也可以设置两个字段。

一般来说,如果你正在做一些场上反射的东西,并且你想用字段做一些花哨的动态东西,你想要使用struct标签。例如,像这样:

type Object struct {
    Id string     `db:"id"`
    Field1 string `db:"field1"`
    Field2 int    `db:"field2"`
}

您可以访问这些标签,例如-a-this:

package main

import (
    "reflect"
    "fmt"
)

func main() {
    var x struct {
        MyField int `core:"required"`
    }
    t := reflect.TypeOf(x)

    for i := 0; i < t.NumField(); i++ {
        field := t.Field(i)
        fmt.Println(field.Name, ":", field.Tag.Get("core"))
    }
}

这不是一个完整的解决方案,但是......问题的方式是不可能的。

答案 1 :(得分:3)

您可以通过添加如下方法来验证字符串:

func (self *Object) verify(field string) string {
    if _, ok := reflect.TypeOf(*self).FieldByName(field); ok {
        return field
    }
    panic("Invalid field name")
}

然后在将字符串传递给数据库更新时使用它

func (self *Object) SetField1(value string) {
    self.Field1 = value
    database.Update(self.Id, self.verify("Field1"), self.Field1) // pseudocode
}

但我认为如果你愿意使用反射,你最好只做一个接受字段为字符串的通用setField方法,并将值作为{{1检查字段和值,设置值并更新数据库。

这样一切都是使用字符串完成的,所以它会工作或恐慌,你不需要记住使用interface{}方法。

像:

.verify()

虽然我认为这不适用于未出口的字段。