Golang中Http Post请求返回nil的解决方案
Golang中Http Post请求返回nil的解决方案 大家好。
我正在尝试通过一个 HTTP(使用 net/http 模块)的 POST 请求来获取 PayPal 的令牌。 示例链接:example 我尝试了解码和解组,以及在网上找到的各种方法。
respBody, err := ioutil.ReadAll(resp.Body)
json.Unmarshal([]byte(respBody), &info) // info == []
json.NewDecoder(resp.Body).Decode(&res) // res == nil
我可以看到字节形式的整数或转换后的字符串,但看不到 JSON 结构。 我尝试使用了所有这些:
var res interface{}
var res []interface{}
var res map[string]interface{}
我是 Go 语言的新手。
更多关于Golang中Http Post请求返回nil的解决方案的实战教程也可以访问 https://www.itying.com/category-94-b0.html
Lejla94:
"grant_type=client_credentials"
不是有效的 JSON 语法
更多关于Golang中Http Post请求返回nil的解决方案的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
我认为它内部没有引号来使其成为一个真正的JSON字符串,但由于他试图将其解析为映射,字符串很可能不是他所期望的。
为澄清说明:我正确地将
"grant_type=client_credentials"
传递给了请求,但没有尝试获取响应,所以我必须执行
res, _ := client.Do(req)
它本身是一个有效的JSON字符串值。
不过,从行内注释很难判断,string(respBody) 到底是JSON值 "foo=bar"(在Go中为 "\"foo=bar\"")还是Go值 "foo=bar"…
感谢大家的帮助。
我重新审视了一下,发现我之前做错了。
我在GitHub上看到了一些示例,意识到我错误地使用了req和resp。
因此,我将这段代码:
req, err := http.NewRequest("POST", "https://api-m.sandbox.paypal.com/v1/oauth2/token", (strings.NewReader(data.Encode())))
修改为这样做:
client := &http.Client{}
res, _ := client.Do(req)
最后是:
json.NewDecoder(res.Body).Decode(&info)
我想获取POST请求的响应。
但结果总是空的,即 == [] 或 == nil。
例如:
resp, err := http.NewRequest("POST", "https://api-m.sandbox.paypal.com/v1/oauth2/token", (strings.NewReader(data.Encode())))
respBody, err := io.ReadAll(resp.Body) // string(respBody) 是 "grant_type=client_credentials"
var info []interface{}
json.Unmarshal([]byte(string(respBody)), &info) // info 是 []
var res interface{}
var someErr = json.NewDecoder(resp.Body).Decode(&res) // res 和 someErr 都是 <nil>
如果我使用 map[string]interface{},结果是 map[]。
所以我猜测响应返回的是该类型的默认值。
期望的结果应该是一个包含访问令牌和其他字段的对象(结构体)。
我已经看过如何反序列化JSON等示例。
我到底遗漏了什么。
在Golang中处理HTTP POST请求返回nil的问题,通常是由于响应体读取或JSON解码的问题。根据你的代码,这里有几个关键点需要注意:
- 响应体只能读取一次:
resp.Body是一个io.ReadCloser,读取后会被消耗。如果你多次读取,第二次会得到空数据。 - 检查HTTP状态码:确保请求成功(状态码200)。
- 关闭响应体:使用
defer确保响应体被关闭。
以下是修复后的示例代码:
package main
import (
"encoding/json"
"fmt"
"io"
"net/http"
"strings"
)
func main() {
url := "https://api.sandbox.paypal.com/v1/oauth2/token"
payload := strings.NewReader("grant_type=client_credentials")
req, err := http.NewRequest("POST", url, payload)
if err != nil {
fmt.Printf("创建请求失败: %v\n", err)
return
}
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
req.SetBasicAuth("CLIENT_ID", "SECRET")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
fmt.Printf("请求失败: %v\n", err)
return
}
defer resp.Body.Close()
// 检查HTTP状态码
if resp.StatusCode != http.StatusOK {
bodyBytes, _ := io.ReadAll(resp.Body)
fmt.Printf("请求失败,状态码: %d, 响应: %s\n", resp.StatusCode, string(bodyBytes))
return
}
// 方法1: 使用io.ReadAll和json.Unmarshal
bodyBytes, err := io.ReadAll(resp.Body)
if err != nil {
fmt.Printf("读取响应体失败: %v\n", err)
return
}
var result map[string]interface{}
if err := json.Unmarshal(bodyBytes, &result); err != nil {
fmt.Printf("JSON解码失败: %v\n", err)
return
}
fmt.Printf("响应数据: %v\n", result)
// 或者方法2: 使用json.NewDecoder
// 注意:resp.Body已经被读取,这里需要重新创建请求或使用保存的bodyBytes
// var result2 map[string]interface{}
// if err := json.NewDecoder(strings.NewReader(string(bodyBytes))).Decode(&result2); err != nil {
// fmt.Printf("JSON解码失败: %v\n", err)
// return
// }
}
关键修改:
- 添加了HTTP状态码检查,PayPal API通常会在错误时返回非200状态码。
- 使用
defer resp.Body.Close()确保资源释放。 - 使用
map[string]interface{}来接收JSON对象。 - 如果响应是数组,使用
[]interface{}。
如果PayPal返回的是数组格式,修改解码部分:
var result []interface{}
if err := json.Unmarshal(bodyBytes, &result); err != nil {
fmt.Printf("JSON解码失败: %v\n", err)
return
}
调试建议:先打印原始响应字符串查看实际返回的数据格式:
bodyBytes, _ := io.ReadAll(resp.Body)
fmt.Printf("原始响应: %s\n", string(bodyBytes))
这样可以帮助你确定PayPal API实际返回的数据结构。


