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
你说得对,我更新了示例。谢谢。
更多关于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 语言习惯的方式处理了错误。
你的代码有几个关键问题需要修复:
主要问题:
- 结构体字段映射错误 - JSON字段名与结构体标签不匹配
- API响应格式理解错误 - 实际返回的是单个对象,不是数组
- 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)
}
关键修正点:
-
结构体修正:
- 修正了字段名和JSON标签的映射
- 移除了不必要的
Response包装结构
-
API响应处理:
- 该API返回的是单个JSON对象,不是数组
- 使用
json.Unmarshal直接解析到结构体
-
错误处理完善:
- 添加了完整的错误检查
- 检查HTTP状态码
- 添加响应体读取错误处理
-
HTTP请求修正:
- 修正了请求头设置(
application/json) - 修正了请求创建和执行的逻辑流程
- 修正了请求头设置(
运行这个修正后的代码,你应该能正确获取到IP地址的ASN信息。

