You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Go语言json包为何刻意不编组未导出结构体字段?

Go JSON编解码中未导出字段的限制与问题解决

在Go的encoding/json包中,若要让结构体字段通过tag参与JSON编组(Marshal)和解组(Unmarshal),字段必须是导出的。不少开发者误以为这是reflect包的限制,但实际上是JSON编码包主动拒绝处理未导出字段。

这种限制会带来两个常见的实践痛点:

  • 为了支持JSON编解码不得不导出过多字段,导致外部代码可以直接修改这些字段的值,绕开了原本设计的getter/setter方法,破坏了结构体的封装性
  • 若要维持封装性,专门创建一个仅用于JSON编解码的同名结构体(仅调整字段导出性),又会产生大量重复冗余代码

以下是一个可以读取未导出字段tag的实现示例:

package main

import (
	"reflect"
	"unsafe"
)

type MyStruct struct {
	field string `json:"my_field"`
}

func getUnexportedFieldTag(obj interface{}, fieldName string) string {
	val := reflect.ValueOf(obj)
	if val.Kind() == reflect.Ptr {
		val = val.Elem()
	}
	// 获取未导出字段的反射值
	field := val.FieldByName(fieldName)
	// 通过unsafe包绕过访问限制,获取字段的元信息
	fieldPtr := unsafe.Pointer(field.UnsafeAddr())
	reflectField := reflect.NewAt(field.Type(), fieldPtr).Elem()
	return reflectField.Type().Field(0).Tag.Get("json")
}

func main() {
	s := MyStruct{field: "demo"}
	println(getUnexportedFieldTag(&s, "field")) // 输出: my_field
}

编辑补充:感谢@mkopriva提供更简洁高效的实现方案。


内容的提问来源于stack exchange,提问作者Stephen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 23:36:22