Golang中如何解析HTTP响应?
Golang中如何解析HTTP响应? 你好,我应该如何解析来自API的HTTP响应?
resp, err := http.Get("https://api.kraken.com/0/public/Time")
if err != nil {
// 处理错误
}
fmt.Println(resp.Body)
??? 我不知道该如何访问其中的字段。
有两件事可以做得更高效:使用 StringBuilder 而非 StringBuffer,因为前者是更快、更年轻的“兄弟”。
非常感谢,我也是用同样的方法完成的。
只是有个问题,panic(err) 是什么?
panic(err)
引用:
// read the payload, in this case, Jhon's info body, err := ioutil.ReadAll(response.Body)
应避免使用 ioutil.ReadAll(response.Body)。
应该这样做:
resp, err := http.Get("https://example.com/api/1")
if err != nil {
return errorMessage
}
type Response struct {
Type string `json:"type"`
}
if err := json.NewDecoder(resp.Body).Decode(&Response); err != nil {
return errorMessage
}
PanicAndRecover
panic 和 recover 函数的行为类似于其他语言中的异常和 try/catch,因为 panic 会导致程序栈开始展开,而 recover 可以停止它。在栈展开过程中,延迟执行的函数仍然会被执行。如果在这种延迟执行的函数内部调用 recover,栈会停止展开,并且 recover 会返回传递给 panic 的值(作为 interface{} 类型)。运行时在特殊情况下也会引发 panic,例如数组或切片索引越界。如果 panic 导致栈展开到任何正在执行的 goroutine 之外(例如,main 函数或传递给 go 的顶层函数未能从中恢复),程序将退出并打印所有正在执行的 goroutine 的堆栈跟踪。一个 panic 不能被另一个不同的 goroutine 恢复。
此外,关于这个主题还有其他很好的解释。
当你收到一个JSON作为响应时,你需要使用 encoding/json 包来进行解析。
例如,假设我发起了一个调用,端点返回了以下内容:
{
"name": "Jhon",
"age": 87
}
以下是你解析它的方法:
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
type Person struct {
Name string `json:"name"` // 首字母大写
Age int `json:"age"` // 首字母大写
}
func main() {
var p Person
response, err := http.Get("http://somewhere.com/api/people/999")
if err != nil {
panic(err)
}
defer response.Body.Close()
// 读取有效载荷,在这个例子中是Jhon的信息
body, err := ioutil.ReadAll(response.Body)
if err != nil {
panic(err)
}
// 魔法发生在这里,我传入一个Person类型的指针,Go会完成剩下的工作
err = json.Unmarshal(body, &p)
if err != nil {
panic(err)
}
fmt.Println(p.Name) // Jhon
fmt.Println(p.Age) // 87
}
现在你需要做的就是,不使用 Person 类型,而是使用一个符合你的端点所发送数据的类型。
在Golang中解析HTTP响应通常涉及读取响应体并将其解码为结构体。以下是几种常见方法:
1. 读取原始响应体
resp, err := http.Get("https://api.kraken.com/0/public/Time")
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(body))
2. 解析JSON响应到结构体
对于你的API示例,首先定义匹配响应格式的结构体:
type KrakenTimeResponse struct {
Error []string `json:"error"`
Result struct {
Unixtime int `json:"unixtime"`
Rfc1123 string `json:"rfc1123"`
} `json:"result"`
}
resp, err := http.Get("https://api.kraken.com/0/public/Time")
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
var result KrakenTimeResponse
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
log.Fatal(err)
}
fmt.Printf("Unix时间戳: %d\n", result.Result.Unixtime)
fmt.Printf(RFC1123格式: %s\n", result.Result.Rfc1123)
3. 解析到map(当结构未知时)
resp, err := http.Get("https://api.kraken.com/0/public/Time")
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
var data map[string]interface{}
if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
log.Fatal(err)
}
result := data["result"].(map[string]interface{})
fmt.Println("Unix时间戳:", result["unixtime"])
4. 完整示例代码
package main
import (
"encoding/json"
"fmt"
"log"
"net/http"
)
func main() {
resp, err := http.Get("https://api.kraken.com/0/public/Time")
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
log.Fatalf("请求失败,状态码: %d", resp.StatusCode)
}
var response struct {
Error []string `json:"error"`
Result struct {
Unixtime int `json:"unixtime"`
Rfc1123 string `json:"rfc1123"`
} `json:"result"`
}
if err := json.NewDecoder(resp.Body).Decode(&response); err != nil {
log.Fatal(err)
}
fmt.Printf("API响应:\n")
fmt.Printf("错误信息: %v\n", response.Error)
fmt.Printf("Unix时间戳: %d\n", response.Result.Unixtime)
fmt.Printf("时间字符串: %s\n", response.Result.Rfc1123)
}
关键点:
- 使用
defer resp.Body.Close()确保响应体被关闭 - 检查HTTP状态码
resp.StatusCode - 使用
json.NewDecoder(resp.Body).Decode()直接解码响应体 - 定义匹配JSON字段的结构体标签
json:"field_name"

