Golang获取特定结构字段名称的字符串表示



我真的想要一种在GO中打印字段名称的字符串表示形式。它有几个用例,但这里有一个例子:

可以说我有一个结构

type Test struct {
    Field      string `bson:"Field" json:"field"`
    OtherField int    `bson:"OtherField" json:"otherField"`
}

,例如,我想做一个mongo查找:

collection.Find(bson.M{"OtherField": someValue})

我不喜欢我必须将字符串的"其他场"放在其中。错误概况或结构更改似乎很脆弱,然后我的查询失败了,而我不知道它。

有什么办法可以获取字符串"其他场",而无需声明const或类似的内容?我知道我可以将反射从结构中获取字段名称列表,但我真的很想按照

的方式做一些事情
fieldName := nameOf(Test{}.OtherField) 
collection.Find(bson.M{fieldName: someValue})

有什么办法在旅途中做到这一点?C#6具有内置的名称,但是通过反射挖掘我找不到任何方法。

我真的不认为有。您可能可以通过反射加载一组类型,生成一组字段名称的常数。所以:

type Test struct {
    Field      string `bson:"Field" json:"field"`
    OtherField int    `bson:"OtherField" json:"otherField"`
}

可以生成类似的东西:

var TestFields = struct{
      Field string
      OtherField string
}{"Field","OtherField"}

,您可以将TestFields.Field用作常数。

不幸的是,我不知道有任何这样做的现有工具。做得很简单,但是连接到go generate

编辑:

我如何生成它:

  1. 制作一个接受reflect.Typeinterface{}阵列并吐出代码文件的软件包。
  2. 在我的存储库中以主函数为单位的 generate.go

    func main(){
       var text = mygenerator.Gen(Test{}, OtherStruct{}, ...)
       // write text to constants.go or something
    }
    
  3. //go:generate go run scripts/generate.go添加到我的主应用程序并运行go generate

这是一个函数,它将返回带有struct字段名称的[]string。我认为它是按定义的顺序进行的。

警告:重新排序结构定义中的字段将更改它们出现的顺序

https://play.golang.org/p/dnatznn47s

package main
import (
    "fmt"
    "strings"
    "regexp"
    )
type Test struct {
    Field      string `bson:"Field" json:"field"`
    OtherField int    `bson:"OtherField" json:"otherField"`
}
func main() {
    fields, err := GetFieldNames(Test{})
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Println(fields)
}

func GetFieldNames(i interface{}) ([]string, error) {
    // regular expression to find the unquoted json
    reg := regexp.MustCompile(`(s*?{s*?|s*?,s*?)(['"])?(?P<Field>[a-zA-Z0-9]+)(['"])?:`)
    // print struct in almost json form (fields unquoted)
    raw := fmt.Sprintf("%#v", i)
    // remove the struct name so string begins with "{"
    fjs := raw[strings.Index(raw,"{"):]
    // find and grab submatch 3
    matches := reg.FindAllStringSubmatch(fjs,-1)
    // collect
    fields := []string{}
    for _, v := range matches {
        if len(v) >= 3 && v[3] != "" {
            fields = append(fields, v[3])
        }
    }

return fields, nil

}

相关内容

  • 没有找到相关文章

最新更新