Go lang RPC返回EOF错误

问题描述 投票:0回答:1

我正在使用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将客户端请求的响应主体解码为//接口回复。

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。

go json-rpc
1个回答
1
投票

这一行:

io.Copy(ioutil.Discard, resp.Body)

读取整个resp.Body,让读者不再需要读取字节。因此,任何对resp.Body.Read的连续调用都将返回EOF,并且json.Decoder.Decode方法在解码给定读者的内容时确实使用io.Reader.Read方法,因此......

由于resp.Body是一个io.ReadCloser,这是一个不支持“倒带”的界面,并且你想要不止一次读取身体内容(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)
}
© www.soinside.com 2019 - 2024. All rights reserved.