我正在编写一个 Go 库,它将 JSON 解码为一个结构体。JSON 有一个相当简单的通用模式,但我希望这个库的使用者能够将额外的字段解码成他们自己的嵌入通用结构的结构,避免使用映射的需要。理想情况下,我只想对 JSON 解码一次。目前它看起来像这样。(为简洁起见,删除了错误处理。)JSON:{ "CommonField": "foo", "Url": "http://example.com", "Name": "Wolf" }图书馆代码:// The base JSON request.type BaseRequest struct { CommonField string}type AllocateFn func() interface{}type HandlerFn func(interface{})type Service struct { allocator AllocateFn handler HandlerFn} func (Service *s) someHandler(data []byte) { v := s.allocator() json.Unmarshal(data, &v) s.handler(v)}应用程序代码:// The extended JSON requesttype MyRequest struct { BaseRequest Url string Name string}func allocator() interface{} { return &MyRequest{}}func handler(v interface{}) { fmt.Printf("%+v\n", v);}func main() { s := &Service{allocator, handler} // Run s, eventually s.someHandler() is called}我不喜欢这个设置的是allocator功能。所有实现都将简单地返回一个新的BaseRequest“子类型”。在更动态的语言中,我会传递MyRequestin的类型,并在库内实例化。我在 Go 中有类似的选择吗?
3 回答
守着一只汪
TA贡献1872条经验 获得超3个赞
有几种方法可以处理这个问题。一个既简单又方便的想法是定义一个更丰富的请求类型,提供给处理程序,而不是传递原始类型。通过这种方式,您可以以友好的方式实现默认行为,并支持边缘情况。这也将避免在自定义类型上嵌入默认类型的需要,并允许您在不破坏客户端的情况下扩展功能。
灵感:
type Request struct {
CommonField string
rawJSON []byte
}
func (r *Request) Unmarshal(value interface{}) error {
return json.Unmarshal(r.rawJSON, value)
}
func handler(req *Request) {
// Use common data.
fmt.Println(req.CommonField)
// If necessary, poke into the underlying message.
var myValue MyType
err := req.Unmarshal(&myValue)
// ...
}
func main() {
service := NewService(handler)
// ...
}
- 3 回答
- 0 关注
- 152 浏览
添加回答
举报
0/150
提交
取消