随着 Go 1.18 的正式发布,千呼万唤的泛型也正式推出了。很多新手老鸟都跃跃欲试,想要将泛型用到日常开发中,提升开发效率。
笔者会将日常自己构思到的,或者翻资料看到的,比较好的 Go 泛型使用姿势总结成《Go泛型骚操作》系列文章
需求
我在设计一种完全依赖于 Kubernetes ConfigMap
/ Secret
的应用程序配置加载方案,将配置条目反序列化到某个结构体上。
而实际应用中,结构体 的 字段 免不了有各种类型,比如 int, boolean 等,甚至 切片,字典 和 其他结构体 等高级类型。
而 Kubernetes 的 ConfigMap
/ Secret
作为字典,键和值都必须是字符串。
如何将键值都是字符串的字典,反序列化到复杂的结构体上,成为了一个问题
现有方案
-
json
库自带的,string
标签json
库官方文档中写到,在标签中,追加上,string
可以让float
,int
,boolean
自动从字符串值反序列化,但是不支持其他类型 -
自己手写一套 序列化/反序列化 库
太麻烦,容易出错
使用泛型
我们的目的是,用最少的代价,让一个结构体,无论字段是什么类型,都能把它序列化成一个字符串,并能反序列化出原始值。
设计一个泛型容器 Stringify
,实现 json.Marshaler
和 json.Unmarshaler
接口,覆盖默认 json
库的 序列化/反序列化 行为
type Stringify[T any] struct {
Value T
}
func (s Stringify[T]) MarshalJSON() (output []byte, err error) {
// 将 Value 编码为 JSON 字符串
var buf [