我想使用Go net/http
库使用主体构造HTTP POST请求。
我用来构造http请求的函数如下:docs
http.NewRequest(method string, url string, body io.Reader)
我想出了两种解决方案,但我试图看看哪种解决方案更惯用且可扩展以支持不同的身体构造。
Solution #1
bytesObj := []byte(`{"key":"value"}`)
body := bytes.NewBuffer(bytesObj)
Solution #2
bodyMap := map[string]string{"key":"value"}
bodyBytes, _ := json.Marshal(bodyMap)
body := bytes.NewBuffer(bodyBytes)
理想情况下,我会将代码移至辅助函数,以便可以自定义主体的构造。辅助功能将类似于
func constructBody(someArgument) io.Reader {
return bodyHere
}
答案 0 :(得分:0)
如果主体已经是字符串,则选项#1对我来说更具吸引力。
如果仅使用键->仅包含字符串的值,则选项#2更好。 但是,当您嵌套struct时,这将变得很麻烦
但是根据我的经验,大多数时候我们都在处理struct。我想使该结构更接近http调用发生的位置。
func main() {
ctx := context.Background()
body := struct {
Key string `json:"key"`
}{
Key: "value",
}
out, err := json.Marshal(body)
if err != nil {
log.Fatal(err)
}
req, err := http.NewRequest("POST", "http://example.com", bytes.NewBuffer(out))
if err != nil {
log.Fatal(err)
}
req = req.WithContext(ctx)
http.DefaultClient.Do(req)
}
如果该结构在多个地方使用,则可以制作一个包级结构。
答案 1 :(得分:0)
要使其具有更高的可重用性,您可以创建一个JSONReaderFactory,它仅需要几行代码:
func jsonReaderFactory(in interface{}) (io.Reader, error) {
buf := bytes.NewBuffer(nil)
enc := json.NewEncoder(buf)
err := enc.Encode(in)
if err != nil {
return nil, fmt.Errorf("creating reader: error encoding data: %s", err)
}
return buf, nil
}