问题描述
假设我们有这个 PoC:
package main
import (
"fmt"
"reflect"
"strings"
)
type MyStruct struct {
Str string `gorm:"size:10" json:"string"`
}
func main() {
aStruct := MyStruct{"Hello"}
s := reflect.ValueOf(&aStruct).Elem()
if s.Kind() == reflect.Struct {
for i := 0; i < s.NumField(); i++ {
field := s.Field(i)
if field.IsValid() {
if field.CanSet() {
fmt.Printf("%T\n",field) // reflect.Value,need reflect.StructField
gormTag := field.Tag.Get("gorm") // Compile ERROR HERE
gormSize := strings.Split(gormTag,"size:")[1]
fmt.Println(gormSize)
}
}
}
}
}
错误是:
go run test1.go
# command-line-arguments
./test1.go:22:22: field.Tag undefined (type reflect.Value has no field or method Tag)
使用 go 1.14.6 和 go 1.15.2 进行测试。
据我所知,我需要将 reflect.Value
转换为(或从)reflect.StructField
任何想法如何做到这一点?
解决方法
标签属于结构体字段的类型,不属于结构体类型的值。
reflect.ValueOf()
返回值 的包装器,而不是它的类型。要获取标签值,您需要从类型的包装器开始,例如通过reflect.TypeOf()
获得:
t := reflect.TypeOf(&aStruct).Elem()
以及循环中字段的类型包装器(类型为 reflect.StructTag
):
field := s.Field(i)
fieldt := t.Field(i)
并使用 fieldt
获取标签:
gormTag := fieldt.Tag.Get("gorm") // No error,this works
添加后,输出将是(在 Go Playground 上尝试):
reflect.Value
10