要将一个结构体转换为 io.Reader并将其作为HTTP POST请求体发送,您需要将该对象编码为字节表示,例如JSON。编码的结果应该存储在 bytes.Buffer或 bytes.Reader对象中,这些对象实现了 io.Reader接口中。
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"log"
"net/http"
)
type Fruit struct {
Name string `json:"name"`
Color string `json:"color"`
}
func main() {
// encode a Fruit object to JSON and write it to a buffer
f := Fruit{
Name: "Apple",
Color: "green",
}
var buf bytes.Buffer
err := json.NewEncoder(&buf).Encode(f)
if err != nil {
log.Fatal(err)
}
client := &http.Client{}
req, err := http.NewRequest(http.MethodPost, "https://postman-echo.com/post", &buf)
if err != nil {
log.Fatal(err)
}
resp, err := client.Do(req)
if err != nil {
log.Fatal(err)
}
bytes, err := io.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(bytes))
}
在第19-27 行中,我们创建了一个新的Fruit 结构实例,并通过以下方式将其编码为JSON json.Encoder.其结果被写入一个 bytes.Buffer,它实现了 io.Writer和 io.Reader接口。通过这种方式,我们不仅可以把这个缓冲区作为一个 io.Writer来存储JSON结果,还可以作为 io.Reader当进行POST请求时,需要用到这个结构。
另外,你也可以使用函数将该结构编码为JSON字节片,并创建一个新的 json.Marshal()函数将结构体编码为JSON字节片,并创建一个新的 bytes.Reader的结构,用于从该片段中读取数据,该结构实现了所需的 io.Reader接口。
f := Fruit{
Name: "Apple",
Color: "green",
}
data, err := json.Marshal(f)
if err != nil {
log.Fatal(err)
}
reader := bytes.NewReader(data)
client := &http.Client{}
req, err := http.NewRequest(http.MethodPost, "https://postman-echo.com/post", reader)