Golang中处理JSON和HTTP GET请求的方法

Golang中处理JSON和HTTP GET请求的方法 这个脚本目前无法正常运行(希望您能帮助找出原因),其目标是:给定一个IP地址,获取其ASN并保存到数组中。为简化审查,我们假设IP地址是 104.27.149.119,并使用 https://api.iptoasn.com 的API来查找ASN,该API会返回一个JSON。

这是脚本,可能我在脚本的多个部分都做错了,我认为结构体部分也有问题。

package main

import (
	"encoding/json"
	"fmt"
	"net/http"
)

type asnrecordEntry struct {
	Domain 		bool `json:"announced"`
	CC    		string `json:"as_country_code"`
	Description string `json:"as_description"`
	Type     	int `json:"as_number"`
    First  		string `json:"first_ip"`
    Last 		string `json:"last_ip"`
}

type Response struct {
	Records []asnrecordEntry 
}


func main () {
	url := fmt.Sprintf("https://api.iptoasn.com/v1/as/ip/104.27.149.119")
	asnrecord := make([]asnrecordEntry, 0)

	client := &http.Client{}

	if res, err := http.NewRequest("GET", url, nil); err == nil { 
		res.Header.Set("Accept", `application\json`)
		resp, err := client.Do(res)
		defer resp.Body.Close()

		decoder := json.NewDecoder(resp.Body)
		r := Response{}

		if err = decoder.Decode(&r); err == nil {
			asnrecord = r.Response
		}
	}

	fmt.Println(asnrecord)
}

更多关于Golang中处理JSON和HTTP GET请求的方法的实战教程也可以访问 https://www.itying.com/category-94-b0.html

6 回复

你说得对,我更新了示例。谢谢。

更多关于Golang中处理JSON和HTTP GET请求的方法的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


geosoft1:

resp, err := client.Do(res)

你需要在这里检查 err

非常感谢,我真的很感激你的帮助。我还有一个问题:我需要将本例中值为13335的ASN保存到一个变量中,我该如何操作?

那么,在解码响应之后,你已经得到了一个 AsnrecordEntry 类型的变量。你需要做的就是访问对应的字段,例如:

type := asnrecord.Type

我简化了你的代码,以弄清楚它是如何工作的。基本上,数据结构中存在一些错误(注意返回的数据类型),而且我不明白你为什么需要一个数组来接收响应。无论如何,下面是一个可运行的代码。

package main

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
)

type AsnrecordEntry struct {
	Domain      bool   `json:"announced"`
	CC          string `json:"as_country_code"`
	Description string `json:"as_description"`
	Type        int    `json:"as_number"`
	First       string `json:"first_ip"`
	Last        string `json:"last_ip"`
}

func main() {
	url := fmt.Sprintf("https://api.iptoasn.com/v1/as/ip/104.27.149.119")

	client := &http.Client{}

	res, err := http.NewRequest("GET", url, nil)
	if err != nil {
		log.Println(err)
		return
	}

	res.Header.Set("Accept", `application\json`)
	resp, err := client.Do(res)
    if err != nil {
    	log.Println(err)
    	return
    }
	defer resp.Body.Close()

	var asnrecord AsnrecordEntry
	if err := json.NewDecoder(resp.Body).Decode(&asnrecord); err != nil {
		log.Println(err)
		return
	}

	fmt.Println(asnrecord)
}

响应如下:

{true US CLOUDFLARENET - Cloudflare, Inc. 13335 104.23.208.0 104.31.95.255}

补充说明: 虽然 err == nil 的写法也可以,但我以更符合 Go 语言习惯的方式处理了错误。

你的代码有几个关键问题需要修复:

主要问题:

  1. 结构体字段映射错误 - JSON字段名与结构体标签不匹配
  2. API响应格式理解错误 - 实际返回的是单个对象,不是数组
  3. HTTP请求处理逻辑问题 - 错误处理不完整

修正后的代码:

package main

import (
	"encoding/json"
	"fmt"
	"io"
	"net/http"
)

type ASNRecord struct {
	Announced   bool   `json:"announced"`
	CountryCode string `json:"as_country_code"`
	Description string `json:"as_description"`
	ASNumber    int    `json:"as_number"`
	FirstIP     string `json:"first_ip"`
	LastIP      string `json:"last_ip"`
}

func main() {
	ip := "104.27.149.119"
	url := fmt.Sprintf("https://api.iptoasn.com/v1/as/ip/%s", ip)
	
	client := &http.Client{}
	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		fmt.Printf("创建请求失败: %v\n", err)
		return
	}
	
	req.Header.Set("Accept", "application/json")
	
	resp, err := client.Do(req)
	if err != nil {
		fmt.Printf("请求失败: %v\n", err)
		return
	}
	defer resp.Body.Close()
	
	if resp.StatusCode != http.StatusOK {
		body, _ := io.ReadAll(resp.Body)
		fmt.Printf("API返回错误状态码 %d: %s\n", resp.StatusCode, body)
		return
	}
	
	body, err := io.ReadAll(resp.Body)
	if err != nil {
		fmt.Printf("读取响应失败: %v\n", err)
		return
	}
	
	var asnRecord ASNRecord
	if err := json.Unmarshal(body, &asnRecord); err != nil {
		fmt.Printf("JSON解析失败: %v\n", err)
		fmt.Printf("原始响应: %s\n", body)
		return
	}
	
	// 保存到数组(根据你的需求)
	asnRecords := []ASNRecord{asnRecord}
	
	fmt.Printf("ASN记录: %+v\n", asnRecords)
	fmt.Printf("AS号码: %d\n", asnRecord.ASNumber)
	fmt.Printf("国家代码: %s\n", asnRecord.CountryCode)
	fmt.Printf("描述: %s\n", asnRecord.Description)
}

关键修正点:

  1. 结构体修正

    • 修正了字段名和JSON标签的映射
    • 移除了不必要的Response包装结构
  2. API响应处理

    • 该API返回的是单个JSON对象,不是数组
    • 使用json.Unmarshal直接解析到结构体
  3. 错误处理完善

    • 添加了完整的错误检查
    • 检查HTTP状态码
    • 添加响应体读取错误处理
  4. HTTP请求修正

    • 修正了请求头设置(application/json
    • 修正了请求创建和执行的逻辑流程

运行这个修正后的代码,你应该能正确获取到IP地址的ASN信息。

回到顶部