Golang中如何解析HTTP响应?

Golang中如何解析HTTP响应? 你好,我应该如何解析来自API的HTTP响应?

resp, err := http.Get("https://api.kraken.com/0/public/Time")
if err != nil {
    // 处理错误
}
fmt.Println(resp.Body)

??? 我不知道该如何访问其中的字段。

7 回复

那么第二件事是什么?

更多关于Golang中如何解析HTTP响应?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


有两件事可以做得更高效:使用 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

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"
回到顶部