用go实现get/post请求调用api
Heroine 1 发布于 2022-09-01 上海最近的一次demo,相当于一次复习吧,把踩的坑都记录一遍
先复习一下调用接口的过程
- 需要url
- 是get方法,还是post方法?
- url需要加参数吗?
- 序列化?
1. 返回的response 的body 默认类型是[]byte
body, err := ioutil.ReadAll(resp.Body) //查看返回值的类型 fmt.Println(reflect.TypeOf(body)) //终端显示body的类型是[]uint8
2. 将[]byte转换成string
转换过程中根据《go专家编程》讲的来看,需要进行内存拷贝
fmt.Println(string(body))
3.将获取到的json中提取某一个对象
注意在获取的response时,body的默认数据类型是[]byte,需要转换成string,才能显示成json好看的格式,通过变成的string格式来获取某一个key-value
//go get "github.com/thedevsaddam/gojsonq" jsonX := string(body) t := gojsonq.New().FromString(jsonX).Find("unique_token") //由于返回的t是一个空接口类型,需要类型断言转换成string类型 return t.(string)
4.go发送post请求调用api
func SubmitOrder(params []byte) { //声明下单的url PostOrderUrl := "https://www.testapi.com/test" //设置post请求,第三个参数传byte类型,很关键! req, err := http.NewRequest("POST", PostOrderUrl, bytes.NewBuffer(params)) if err != nil { log.Println(err) } //授权!!! //这里也很关键,千万不要设置漏了,否则可能后端接口返回不出正确的结果! req.Header.Set("Content-Type", "application/json") req.Header.Set("authorization", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiMzdlYWMwMTMtOTM5Yy00NThjLTgxMDktYmM5MDFjMTIyY2I0IiwiZXhwIjoxNzMzODQ2NTEzfQ._p6nCjIx1nq6sbMa4B-yJ9P_vThJESsF5tLIRoMRZXA") //获取客户端对象,发送请求 client := &http.Client{} resp, err := client.Do(req) if err != nil { log.Println(err) } defer resp.Body.Close() //读取返回值 res, err := ioutil.ReadAll(resp.Body) if err != nil { fmt.Println(err) } fmt.Println(string(res)) }
5. 获取空接口类型 的类型或者值
xx1:=reflect.Typeof(x) xx2:=reflect.Valueof(x)
6. 强制转换空接口类型
tt是interface{}类型,每一个interface{}类型中都保存了他本身的value和type,需要通过发射获取值,实现方法见上面
tt := int(t.(float64))
7.定义的一个方法返回不同类型的值怎么实现?
将这些返回值用一个struct封装起来
然后定义返回参数为interface{}实现
如何获取返回的值变为原来的struct类型呢?
类型断言!
比如:
type Mystruct struct{ a int b string } func test() interface{}{ //处理逻辑 .... var mystruct =new(Mystruct) mystruct.a=1 mystruct.b="balabala" return mystruct } Value := test() //不确定空接口实际的类型可以用reflect.Typeof()来确定 //reflect.Typeof(Value)===>他会返回Mystruct,好像也可能是*Mystruct,可以测试一下! V:=Value.(Mystruct)
8. 将定义好的结构体序列化
//定义的结构体 type Product struct { Type int `json:"type" ` ProductNo string `json:"product_no" ` Amount int `json:"amount"` ElectricityHours int `json:"electricity_hours" ` HashRateNo string `json:"hashrate_no" ` } type CreateOrderParams struct { Products []Product `json:"products"` UniqueToken string `json:"unique_token" ` } //构造需要传递的参数 params := new(CreateOrderParams) //给构造好的结构体赋值 params.UniqueToken = uniqueToken var p Product p.Type = tt.Type p.ProductNo = tt.Code p.Amount = 10 p.ElectricityHours = 240 var products []Product products = append(products, p) params.Products = products //将结构体序列化,转化为json格式,返回的结果是[]byte类型 res, err := json.Marshal(¶ms) if err != nil { println(err.Error()) }
9. go发送get请求调用api
func GetToken() string { //声明要获取unique_token的接口 reqUniqueTokenUrl := "https://this.is.test.url:8888/v1/users/token" //设置get请求类型,所以第三个参数为nil req, err := http.NewRequest("GET", reqUniqueTokenUrl, nil) if err != nil { log.Println(err) } //设置请求头header,携带token身份认证 req.Header.Set("authorization", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ1.eyJuYW1lIjoiMzdlYWMwMTMtOTM5Yy00NThjLTgxMDktYmM5MDFjMTIyY2I0IiwiZXhwIjoxNzMzODQ2NTEzfQ._p6nCjIx1nq6sbMa4B-yJ9P_vThJESsF5tLIRoMRZXA") //获取客户端对象,执行请求 client := &http.Client{} resp, err := client.Do(req) if err != nil { log.Println(err) panic("ops!,get unique token url err!") } defer resp.Body.Close() //打印结果 body, err := ioutil.ReadAll(resp.Body) if err != nil { log.Println(err) panic("ops!,get unique token url err!") } fmt.Println(string(body)) //在返回的JSON对象中根据key获取value jsonX := string(body) t := gojsonq.New().FromString(jsonX).Find("unique_token") //由于返回的t是一个空接口类型,需要类型断言转换成string类型 return t.(string) }
最后,展示我做实验的所有代码,有些数据是伪数据,按需替换哈!
package main import ( "bytes" "encoding/json" "fmt" "github.com/thedevsaddam/gojsonq" "io/ioutil" "log" "net/http" ) type Product struct { Type int `json:"type" ` ProductNo string `json:"product_no" ` Amount int `json:"amount"` ElectricityHours int `json:"electricity_hours" ` HashRateNo string `json:"hashrate_no" ` } type CreateOrderParams struct { Products []Product `json:"products"` UniqueToken string `json:"unique_token" ` } type Response struct { Code string Type int } func main() { //获取token uniqueToken := GetToken() //获取商品类型 t := GetGoodsInfo() //这里是个大坑,通过reflect.Typeof(t)发现类型是t的实际类型是*Response,所以类型断言一定要是指针类型的! tt := t.(*Response) //构造需要传递的参数 params := new(CreateOrderParams) //给构造好的结构体赋值 params.UniqueToken = uniqueToken var p Product p.Type = tt.Type p.ProductNo = tt.Code p.Amount = 10 p.ElectricityHours = 240 var products []Product products = append(products, p) params.Products = products //将结构体序列化,转化为json格式,返回的结果是[]byte类型 res, err := json.Marshal(¶ms) if err != nil { println(err.Error()) } //提交订单 SubmitOrder(res) } // GetGoodsInfo 获取商品信息 func GetGoodsInfo() interface{} { //声明要调用获取商品信息的接口 reqGoodsUrl := "https://this.is.test.url/test" //调用接口 req, err := http.NewRequest("GET", reqGoodsUrl, nil) client := &http.Client{} resp, err := client.Do(req) if err != nil { log.Println(err) } defer resp.Body.Close() //打印返回结果 body, err := ioutil.ReadAll(resp.Body) if err != nil { log.Println(err) } // Todo:如何将结果转换成映射到Products jsonX := string(body) t := gojsonq.New().FromString(jsonX).Find("type") //Todo: 要点!!!接口类型的 float64 转换成int //reflect.TypeOf(t) => float64 tt := int(t.(float64)) c := gojsonq.New().FromString(jsonX).Find("code") code := c.(string) fmt.Println("test", code) res := new(Response) res.Type = tt res.Code = code return res } // GetToken 获取token func GetToken() string { //声明要获取unique_token的接口 reqUniqueTokenUrl := "https://this.is.test.url:8888/v1/users/token" //设置get请求类型,所以第三个参数为nil req, err := http.NewRequest("GET", reqUniqueTokenUrl, nil) if err != nil { log.Println(err) } //设置请求头header,携带token身份认证 req.Header.Set("authorization", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ1.eyJuYW1lIjoiMzdlYWMwMTMtOTM5Yy00NThjLTgxMDktYmM5MDFjMTIyY2I0IiwiZXhwIjoxNzMzODQ2NTEzfQ._p6nCjIx1nq6sbMa4B-yJ9P_vThJESsF5tLIRoMRZXA") //获取客户端对象,执行请求 client := &http.Client{} resp, err := client.Do(req) if err != nil { log.Println(err) panic("ops!,get unique token url err!") } defer resp.Body.Close() //打印结果 body, err := ioutil.ReadAll(resp.Body) if err != nil { log.Println(err) panic("ops!,get unique token url err!") } fmt.Println(string(body)) //在返回的JSON对象中根据key获取value jsonX := string(body) t := gojsonq.New().FromString(jsonX).Find("unique_token") //由于返回的t是一个空接口类型,需要类型断言转换成string类型 return t.(string) } // SubmitOrder 提交订单 func SubmitOrder(params []byte) { //声明下单的url PostOrderUrl := "https://dev.cookiehash.org:31145/v1/orders" //设置post请求,第三个参数传byte类型 req, err := http.NewRequest("POST", PostOrderUrl, bytes.NewBuffer(params)) if err != nil { log.Println(err) } //授权 req.Header.Set("Content-Type", "application/json") req.Header.Set("authorization", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiMzdlYWMwMTMtOTM5Yy00NThjLTgxMDktYmM5MDFjMTIyY2F0IiwiZXhwIjoxNzMzODQ2NTEzfQ._p6nCjIx1nq6sbMa4B-yJ9P_vThJESsF5tLIRoMRZXA") //获取客户端对象,发送请求 client := &http.Client{} resp, err := client.Do(req) if err != nil { log.Println(err) } defer resp.Body.Close() //读取返回值 res, err := ioutil.ReadAll(resp.Body) if err != nil { fmt.Println(err) } fmt.Println(string(res)) }
参考链接:
go发送get请求
go发送post请求