使用Go的反射包获取结构体字段的标签。

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

Get struct field tag using Go reflect package

问题

在Go语言中,可以通过反射来获取结构体字段的标签值。以下是一个示例:

package main

import (
	"fmt"
	"reflect"
)

type User struct {
	name string `json:"name-field"`
	age  int
}

func main() {
	user := &User{"John Doe The Fourth", 20}
	tag := getStructTag(user, "name")
	fmt.Println(tag)
}

func getStructTag(i interface{}, fieldName string) string {
	t := reflect.TypeOf(i).Elem()
	field, _ := t.FieldByName(fieldName)
	return field.Tag.Get("json")
}

在上面的示例中,我们定义了一个User结构体,其中name字段有一个json标签。getStructTag函数接收一个接口类型和字段名作为参数,使用反射获取字段的标签值。

请注意,由于user是一个指针类型,我们需要使用reflect.TypeOf(i).Elem()来获取指针指向的结构体类型。

运行上述代码,将输出name-field,即name字段的标签值。

希望对你有帮助!

英文:

Is it possible to reflect on a field of a struct, and get a reference to its tag values?

For example:

type User struct {
	name    string `json:name-field`
	age     int
}
// ...
user := &User{"John Doe The Fourth", 20}
getStructTag(user.name)
// ...
func getStructTag(i interface{}) string{
   //get tag from field
   
}

From what I can see, the usual way to do this is to range over typ.NumField(), and then call field.Tag.Get("tagname").

However, in my use-case, it would be much better to not have to pass the whole struct in.

答案1

得分: 78

你不需要传递整个结构体,但仅传递一个字段的值是不够的。

在你的例子中,user.name字段只是一个string类型 - 反射包无法将其与原始结构体关联起来。

相反,你需要传递给定字段的reflect.StructField

field, ok := reflect.TypeOf(user).Elem().FieldByName("name")

tag := string(field.Tag)

注意:我们在上面使用Elem是因为user是一个指向结构体的指针。

你可以在这里尝试一个例子。

英文:

You don't need to pass in the whole struct, but passing in the value of one of the fields is not sufficient.

In your example user.name field is just a string - the reflect package will have no way of correlating that back to the original struct.

Instead, you need to pass around the reflect.StructField for the given field:

field, ok := reflect.TypeOf(user).Elem().FieldByName("name")
…
tag = string(field.Tag)

Note: we use Elem above because user is a pointer to a struct.

You can play with an example here.

答案2

得分: 10

修改上面的答案可以给出特定标签的值

package main

import (
	"fmt"
	"reflect"
)

type User struct {
	Name string `json:"name_field"`
	Age  int
}

func main() {
	user := &User{"John Doe The Fourth", 20}

	field, ok := reflect.TypeOf(user).Elem().FieldByName("Name")
	if !ok {
		panic("Field not found")
	}
	fmt.Println(getStructTag(field, "json")) //name_field
}

func getStructTag(f reflect.StructField, tagName string) string {
	return string(f.Tag.Get(tagName))
}

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

英文:

Modifying the above answer can give value of a specific tag

package main

import (
	"fmt"
	"reflect"
)

type User struct {
	Name string `json:"name_field"`
	Age  int
}

func main() {
	user := &User{"John Doe The Fourth", 20}

	field, ok := reflect.TypeOf(user).Elem().FieldByName("Name")
	if !ok {
		panic("Field not found")
	}
	fmt.Println(getStructTag(field, "json")) //name_field
}

func getStructTag(f reflect.StructField, tagName string) string {
	return string(f.Tag.Get(tagName))
}

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

答案3

得分: 2

从结构体中列出所有标签的清晰方法(使用外部库)。

外部库:https://github.com/fatih/structs

示例:https://go.dev/play/p/C_yXMdbFYAq

package main

import (
	"fmt"

	"github.com/fatih/structs"
)

type User struct {
	Name string `json:"name_field"`
	Age  int    `json:"age_field"`
}

func main() {
	user := &User{}
	fields := structs.Fields(user)

	for _, field := range fields {
		tag := field.Tag("json")
		fmt.Println(tag)
	}
}

结果:

name_field
age_field
英文:

Clean way to list all tags from a struct (using external lib).

External lib: https://github.com/fatih/structs

Example: https://go.dev/play/p/C_yXMdbFYAq

package main

import (
	"fmt"

	"github.com/fatih/structs"
)

type User struct {
	Name string `json:"name_field"`
	Age  int    `json:"age_field"`
}

func main() {
	user := &User{}
	fields := structs.Fields(user)

	for _, field := range fields {
		tag := field.Tag("json")
		fmt.Println(tag)
	}
}

Result:

name_field
age_field

huangapple
  • 本文由 发表于 2014年5月7日 09:06:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/23507033.html
匿名

发表评论

匿名网友

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

确定