我正在編寫一個 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條經驗 獲得超4個贊
有幾種方法可以處理這個問題。一個既簡單又方便的想法是定義一個更豐富的請求類型,提供給處理程序,而不是傳遞原始類型。通過這種方式,您可以以友好的方式實現默認行為,并支持邊緣情況。這也將避免在自定義類型上嵌入默認類型的需要,并允許您在不破壞客戶端的情況下擴展功能。
靈感:
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 關注
- 178 瀏覽
添加回答
舉報
0/150
提交
取消