Golang中结构体字段标签与reflect.StructTag.Get不兼容问题:结构体标签对语法错误解析
Golang中结构体字段标签与reflect.StructTag.Get不兼容问题:结构体标签对语法错误解析 以下是我的代码:
package main
import (
"bytes"
"fmt"
"reflect"
"strconv"
"strings"
)
type User struct {
Name string `name`
Age int64 `age`
}
func main() {
var u User = User{"bob", 10}
res, err := JSONEncode(u)
if err != nil {
panic(err)
}
fmt.Println(string(res))
}
func JSONEncode(v interface{}) ([]byte, error) {
refObjVal := reflect.ValueOf(v)
refObjTyp := reflect.TypeOf(v)
buf := bytes.Buffer{}
if refObjVal.Kind() != reflect.Struct {
return buf.Bytes(), fmt.Errorf(
"val of kind %s is not supported",
refObjVal.Kind(),
)
}
buf.WriteString("{")
pairs := []string{}
for i := 0; i < refObjVal.NumField(); i++ {
structFieldRefObj := refObjVal.Field(i)
structFieldRefObjTyp := refObjTyp.Field(i)
switch structFieldRefObj.Kind() {
case reflect.String:
strVal := structFieldRefObj.Interface().(string)
pairs = append(pairs, `"`+string(structFieldRefObjTyp.Tag)+`":"`+strVal+`"`)
case reflect.Int64:
intVal := structFieldRefObj.Interface().(int64)
pairs = append(pairs, `"`+string(structFieldRefObjTyp.Tag)+`":`+strconv.FormatInt(intVal, 10))
default:
return buf.Bytes(), fmt.Errorf(
"struct field with name %s and kind %s is not supprted",
structFieldRefObjTyp.Name,
structFieldRefObj.Kind(),
)
}
}
buf.WriteString(strings.Join(pairs, ","))
buf.WriteString("}")
return buf.Bytes(), nil
}
它运行得很好,输出如下:
{"name":"bob","age":10}
但在VS Code中,它给我显示了以下问题:

可能是什么问题?
注意
我知道结构体标签应该是 key:"value" 的形式,例如 field:"name",并且尝试了:
type User struct {
Name string `field:"name"`
Age int64 `field:"age"`
}
但这次的输出是错误的,我得到了:
{"field:"name"":"bob","field:"age"":10}
更多关于Golang中结构体字段标签与reflect.StructTag.Get不兼容问题:结构体标签对语法错误解析的实战教程也可以访问 https://www.itying.com/category-94-b0.html
您必须使用正确的语法(成对的引号和分号)来指定标签:
type User struct {
Name string `name:"welcome"`
Age int64 `age:"hello"`
}
reflect package - reflect - Go Packages
Package reflect implements run-time reflection, allowing a program to manipulate objects with arbitrary types.
更多关于Golang中结构体字段标签与reflect.StructTag.Get不兼容问题:结构体标签对语法错误解析的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
我在 Stack Overflow 上找到了答案,并复制到这里供社区参考。
请注意,这只是一个警告,提示你没有遵循约定。正如你已经知道的,代码可以编译、运行并输出你想要的结果:Go Playground - The Go Programming Language。
要避免这个警告,可以禁用你的 linter,或者,更好的做法是遵循约定,在结构体标签中使用 key:"value",然后通过 Get 方法提取值:Go Playground - The Go Programming Language。
reflect package - reflect - Go Packages
Package reflect implements run-time reflection, allowing a program to manipulate objects with arbitrary types.
StructTag 是结构体字段中的标签字符串。
按照约定,标签字符串是由可选的、以空格分隔的 key:“value” 对连接而成的。 每个 key 都是一个非空字符串,由除空格 (U+0020 ’ ')、引号 (U+0022 ‘"’) 和冒号 (U+003A ‘:’) 之外的非控制字符组成。每个 value 都使用 U+0022 ‘"’ 字符和 Go 字符串字面量语法进行引用。
你的代码存在两个关键问题:
- 结构体标签语法错误:你的标签缺少引号,应该是反引号包裹的键值对形式
- 标签解析方式错误:直接使用
string(structFieldRefObjTyp.Tag)会输出完整的标签字符串,而不是特定的键值
以下是修正后的代码:
package main
import (
"bytes"
"fmt"
"reflect"
"strconv"
"strings"
)
type User struct {
Name string `json:"name"`
Age int64 `json:"age"`
}
func main() {
var u User = User{"bob", 10}
res, err := JSONEncode(u)
if err != nil {
panic(err)
}
fmt.Println(string(res))
}
func JSONEncode(v interface{}) ([]byte, error) {
refObjVal := reflect.ValueOf(v)
refObjTyp := reflect.TypeOf(v)
buf := bytes.Buffer{}
if refObjVal.Kind() != reflect.Struct {
return buf.Bytes(), fmt.Errorf(
"val of kind %s is not supported",
refObjVal.Kind(),
)
}
buf.WriteString("{")
pairs := []string{}
for i := 0; i < refObjVal.NumField(); i++ {
structFieldRefObj := refObjVal.Field(i)
structFieldRefObjTyp := refObjTyp.Field(i)
// 使用Get方法获取特定键的值
tagValue := structFieldRefObjTyp.Tag.Get("json")
if tagValue == "" {
// 如果没有json标签,使用字段名
tagValue = structFieldRefObjTyp.Name
}
switch structFieldRefObj.Kind() {
case reflect.String:
strVal := structFieldRefObj.Interface().(string)
pairs = append(pairs, `"`+tagValue+`":"`+strVal+`"`)
case reflect.Int64:
intVal := structFieldRefObj.Interface().(int64)
pairs = append(pairs, `"`+tagValue+`":`+strconv.FormatInt(intVal, 10))
default:
return buf.Bytes(), fmt.Errorf(
"struct field with name %s and kind %s is not supported",
structFieldRefObjTyp.Name,
structFieldRefObj.Kind(),
)
}
}
buf.WriteString(strings.Join(pairs, ","))
buf.WriteString("}")
return buf.Bytes(), nil
}
输出:
{"name":"bob","age":10}
关键修改:
- 使用正确的结构体标签语法:
`json:"name"` - 使用
structFieldRefObjTyp.Tag.Get("json")获取特定键的值,而不是直接转换整个标签字符串 - 添加了标签值为空时的回退逻辑,使用字段名作为JSON键
这样既解决了VS Code的语法检查警告,也正确解析了结构体标签。

