我正在使用 http 通过以下代码调用 RPC
func (c *CallClient) Wallet(method string, req, rep interface{}) error {
client := &http.Client{}
data, _ := EncodeClientRequest(method, req)
reqest, _ := http.NewRequest("POST", c.endpoint, bytes.NewBuffer(data))
resp, err := client.Do(reqest)
if err != nil {
return err
}
defer resp.Body.Close()
io.Copy(ioutil.Discard, resp.Body)
return DecodeClientResponse(resp.Body, rep)
}
使用 EncodeClientRquest && DecodeClientResponse
//EncodeClientRequest 为 JSON-RPC 客户端请求编码参数。
func EncodeClientRequest(method string, args interface{}) ([]byte, error) {
c := &clientRequest{
Version: "2.0",
Method: method,
Params: [1]interface{}{args},
Id: uint64(rand.Int63()),
}
return json.Marshal(c)
}
//DecodeClientResponse 将客户端请求的响应体解码为 //接口(interface)回复。
func DecodeClientResponse(r io.Reader, reply interface{}) error {
var c clientResponse
if err := json.NewDecoder(r).Decode(&c); err != nil {
return err
}
if c.Error != nil {
return fmt.Errorf("%v", c.Error)
}
if c.Result == nil {
return errors.New("result is null")
}
return json.Unmarshal(*c.Result, reply)
}
我收到错误 EOF。
最佳答案
这一行:
io.Copy(ioutil.Discard, resp.Body)
读取整个 resp.Body
,让读取器没有更多的字节要读取。因此,对 resp.Body.Read
的任何连续调用都将返回 EOF 并且 json.Decoder.Decode
方法确实使用了 io。 Reader.Read
解码给定阅读器内容时的方法,所以...
而且由于resp.Body
是一个io.ReadCloser
,它是一个不支持“倒带”的接口(interface),你想要阅读正文内容超过一次(ioutil.Discard 和 json.Decode),您必须将正文读入一个变量,之后您可以重新读取该变量。这取决于你如何做到这一点,一片字节,或 bytes.Reader
,或其他东西。
使用 bytes.Reader
的例子:
func (c *CallClient) Wallet(method string, req, rep interface{}) error {
client := &http.Client{}
data, err := EncodeClientRequest(method, req)
if err != nil {
return err
}
reqest, err := http.NewRequest("POST", c.endpoint, bytes.NewBuffer(data))
if err != nil {
return err
}
resp, err := client.Do(reqest)
if err != nil {
return err
}
defer resp.Body.Close()
// get a reader that can be "rewound"
buf := bytes.NewBuffer(nil)
if _, err := io.Copy(buf, resp.Body); err != nil {
return err
}
br := bytes.NewReader(buf.Bytes())
if _, err := io.Copy(ioutil.Discard, br); err != nil {
return err
}
// rewind
if _, err := br.Seek(0, 0); err != nil {
return err
}
return DecodeClientResponse(br, rep)
}
关于Golang GRPC 返回 EOF 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47970463/