英文:
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.
答案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))
}
答案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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论