我正在编写一个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 request
type 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
“子类型”。用一种更动态的语言,我将MyRequest
改为传入in 的类型,并在库中实例化。Go中是否有类似的选项?
有几种方法可以解决此问题。一个既简单又方便的想法是定义一个提供给处理程序的更丰富的Request类型,而不是传递原始类型。这样,您可以以友好的方式实现默认行为,并支持边缘情况。这样还可以避免将默认类型嵌入自定义类型中,并允许您在不破坏客户端的情况下扩展功能。
寻求灵感:
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)
// ...
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句