我正在将HTTP API中的JSON数据解组为以下Golang结构:
type ResponseBody struct {
Version string `json:"jsonrpc"`
Result Result `json:"result"`
Error Error `json:"error"`
Id int `json:"id"`
}
type Result struct {
Random struct {
Data interface{} `json:"data"`
CompletionTime string `json:"completionTime"`
} `json:"random"`
BitsUsed int `json:"bitsUsed"`
BitsLeft int `json:"bitsLeft"`
RequestsLeft int `json:"requestsLeft"`
AdvisoryDelay int `json:"advisoryDelay"`
}
type Error struct {
Code int `json:"code"`
Message string `json:"message"`
Data []int `json:"data,omitempty"`
}
Run Code Online (Sandbox Code Playgroud)
我已经实现了错误接口,Error如下所示:
func (e Error) Error() string {
return fmt.Sprintf("Error: %+v", e)
}
Run Code Online (Sandbox Code Playgroud)
到目前为止的相关代码:
func Request(method string, params interface{}) (Result, error) {
// `error` in return types is _not_ a typo
body, err := json.Marshal(RequestBody{Version: "2.0", Params: params, Method: method, Id: 1})
if err != nil {
return Result{}, err
}
resp, err := http.Post(endpoint, "application/json-rpc", bytes.NewReader(body))
if err != nil {
return Result{}, fmt.Errorf("Request failed, error was %s", err)
}
defer resp.Body.Close()
text, err := ioutil.ReadAll(resp.Body)
if err != nil {
return Result{}, fmt.Errorf("Failed to read response into memory, error was: %s", err)
}
if resp.StatusCode != 200 {
var errorMessage Error
if err := json.Unmarshal(text, &errorMessage); err != nil {
return Result{}, Error{
Code: 409,
Message: fmt.Sprintf("Client could not decode JSON error response, received %s, error was: %s", text, err),
Data: []int{},
}
}
return Result{}, errorMessage
}
response := ResponseBody{}
if err := json.Unmarshal(text, &response); err != nil {
return Result{}, fmt.Errorf("Failed to JSON-decode response body, received %s from source, error was: %s", text, err)
}
return response.Result, response.Error
}
Run Code Online (Sandbox Code Playgroud)
以下代码无限期挂起成功通话而不会发生恐慌:
// `body` here is just any old struct
result, err := Request("generateIntegers", body)
if err != nil {
return []int{}, err // hangs here
}
Run Code Online (Sandbox Code Playgroud)
实际上,当我调用时,代码总是挂起err.没有引起恐慌并且没有返回错误 - 它只是被冻结[1].
[1]严格地说,它会导致堆栈溢出错误,但那是因为该函数永远不会返回,因此递延resp.Body.Close()中Request不会被调用.
它变得更奇怪了.添加以下调试行:
response := ResponseBody{}
if err := json.Unmarshal(text, &response); err != nil {
return Result{}, fmt.Errorf("Failed to JSON-decode response body, received %s from source, error was: %s", text, err)
}
fmt.Println(response.Result.BitsUsed)
fmt.Println(response.Result) // this prints!
return response.Result, response.Error
Run Code Online (Sandbox Code Playgroud)
工作,但改变这些行只是
response := ResponseBody{}
if err := json.Unmarshal(text, &response); err != nil {
return Result{}, fmt.Errorf("Failed to JSON-decode response body, received %s from source, error was: %s", text, err)
}
fmt.Println(response.Result) // this no longer prints! :O
return response.Result, response.Error
Run Code Online (Sandbox Code Playgroud)
导致Request函数本身挂起此调试语句.
go test -trace以查看所调用的内容.这会失败,因为go tool trace无法解析生成的跟踪文件.*error而不是常规error.这没有用.为什么这段代码片段挂起了?
注意:我正在运行Go 1.7
问题在于Error界面的定义.当您尝试使用值时Error() string,Error类型上的函数会以递归方式调用自身:fmt.Sprintfe
func (e Error) Error() string {
return fmt.Sprintf("Error: %+v", e) // calls e.Error again
}
Run Code Online (Sandbox Code Playgroud)
尝试通过Error明确访问类型的成员来返回错误:
func (e Error) Error() string {
return fmt.Sprintf("Error: %+v", e.Message)
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
257 次 |
| 最近记录: |