获取字段标签的反射

huangapple go评论81阅读模式
英文:

Reflection to get field tag

问题

在Go语言中,可以使用反射来通过将字段包装在reflect库的函数中来获取字段标签。你可以尝试以下方法来创建一个轻量级的数据访问对象,以便在数据库中获取列名而不需要在代码中硬编码。

首先,你可以定义一个结构体,其中包含带有数据库列名标签的字段:

// 表结构
type CusipTableRow struct {
    Id          int64  `db:"id"`
    Cusip       string `db:"cusip"`
    Symbol      string `db:"symbol"`
    Active      int8   `db:"active"`
    Added_Time  int32  `db:"added_timestamp"`
    Description string `db:"description"`
    Exchange    string `db:"exchange"`
    AssetType   string `db:"asset_type"`
}

接下来,你可以为结构体定义一个方法,使用反射来获取字段标签的值:

func (row CusipTableRow) GetColumnName(field interface{}) string {
    t := reflect.TypeOf(row)
    if t.Kind() == reflect.Ptr {
        t = t.Elem()
    }

    fieldName := reflect.ValueOf(field).Elem().Type().Name()
    fieldTag := t.FieldByName(fieldName).Tag.Get("db")

    return fieldTag
}

现在,你可以创建一个CusipTableRow对象,并调用GetColumnName方法来获取字段的标签值:

var row CusipTableRow
columnName := row.GetColumnName(&row.Id) // 根据标签获取列名

这样,你就可以通过反射来获取字段标签的值,而不需要下载其他库。希望这个方法对你有帮助!

英文:

In Go is there a good way to use reflection to get a field tag by just wrapping a field in a function from the reflect library?

I am basically trying to create a thin data access object that allows be to get the column name in the db without hard coding it all over the place.

Below is the struct with db column names as tags.

    // Table Structures
type CusipTableRow struct {
	Id          int64  `db:"id"`
	Cusip       string `db:"cusip"`
	Symbol      string `db:"symbol"`
	Active      int8   `db:"active"`
	Added_Time  int32  `db:"added_timestamp"`
	Description string `db:"description"`
	Exchange    string `db:"exchange"`
	AssetType   string `db:"asset_type"`
}

I am seeking a suggestion other than downloading another library on how to use reflection to essentially make a call like this to return a string with the tag value.

var row CusipTableRow
row.GetColumnName(row.Id) //Return column name based on tag.

I was considering possibly trying to use a map[address] fieldTag, but did not have luck getting that to work perhaps due to not fully having a grasp of the unsafe package. If that approach would have worked I was thinking a call like this could have worked:

row.GetColumnName(&row.Id) //Return column name based on tag.

答案1

得分: 5

给定结构体的地址和字段的地址,可以获取字段标签。不需要使用不安全的操作。

func GetColumnName(pstruct interface{}, pfield interface{}) string {
	v := reflect.ValueOf(pstruct).Elem()
	for i := 0; i < v.NumField(); i++ {
		if v.Field(i).Addr().Interface() == pfield {
			return v.Type().Field(i).Tag.Get("db")
		}
	}
	panic("field not in struct")
}

示例用法:

var v CusipTableRow
fmt.Println(GetColumnName(&v, &v.Added_Time)) // 输出 added_timestamp

在 Go Playground 上运行:点击这里

英文:

You can get field tag given the address of the struct and the address of the field. Unsafe shenanigans are not required.

func GetColumnName(pstruct interface{}, pfield interface{}) string {
	v := reflect.ValueOf(pstruct).Elem()
	for i := 0; i &lt; v.NumField(); i++ {
		if v.Field(i).Addr().Interface() == pfield {
			return v.Type().Field(i).Tag.Get(&quot;db&quot;)
		}
	}
	panic(&quot;field not in struct&quot;)
}

Example use:

var v CusipTableRow
fmt.Println(GetColumnName(&amp;v, &amp;v.Added_Time)) // prints added_timestamp

Run it on the Go Playground.

huangapple
  • 本文由 发表于 2021年9月3日 23:19:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/69047246.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定