说明
系统提供服务能力离不开网络,数据通过网络传输离不开数据的编码和解码
网络请求
go 中网络请求
和其他语言一样,go 语言也自带了网络请求库 net/http
使用 net/http
GET 请求
func main() {
// 请求地址
const url = "https://api.apiopen.top/getJoke?page=1&count=2&type=video"
res, err := http.Get(url)
if err != nil {
fmt.Println(err)
return
}
// 延迟关闭流
defer res.Body.Close()
fmt.Println(res)
fmt.Println(res.Body)
}
- url 为请求地址,浏览器访问返回
-
通过
http.Get发起 GET 方式请求 -
http.Get会返回resp *Response, err error- resp 响应数据
- err 这次请求是否发生了错误
- 打印 res
&{200 200 HTTP/1.1 1 1 map[Access-Control-Allow-Headers:[Content-Type, x-requested-with, X-Custom-Header, Authorization] Access-Control-Allow-Methods:[POST, GET, OPTIONS, DELETE] Access-Control-Allow-Origin:[*] Access-Control-Max-Age:[3600] Cache-Control:[private] Content-Type:[application/json;charset=UTF-8] Date:[Wed, 24 Mar 2021 02:07:32 GMT] Expires:[Thu, 01 Jan 1970 00:00:00 GMT]] 0xc0001a2040 -1 [chunked] false false map[] 0xc000108000 0xc000234000}
- res 还有常用的状态码、Header 信息
读取 Body 信息
res.Body 中就是请求回来的数据流 field Body io.ReadCloser
可以使用 I\O 操作工具类 ioutil 包来便利读取流信息
...
data, err := ioutil.ReadAll(res.Body)
...
- ioutil.ReadAll 返回 []byte, error
- [] type 就是返回数据
字节转字符串
使用内建 string 进行字节和字符串转换
fmt.Println(string(data))
输出转换后的内容
POST 请求
使用写好的 SpringBoot 服务提供 POST 登录
moose服务是 SpringBoot + OAuth2.0 + Mybatis,提供了一些基本的 API 操作,有兴趣的可以看下 源码地址:gitee.com/shizidada/m…
启动服务,使用 go http 访问登录 http://localhost:7000/api/v1/account/login
PostForm 方式
func TestPostLogin() {
loginUrl := "http://localhost:7000/api/v1/account/login"
values := url.Values{}
values.Add("accountName", "江景")
values.Add("password", "123")
values.Add("loginType", "password")
res, err := http.PostForm(loginUrl, values)
if err != nil {
fmt.Println(err)
return
}
data, err := ioutil.ReadAll(res.Body)
fmt.Println(string(data))
// {"code":200,"message":"请求成功","data":"790e6c22-2ec8-4d1a-a852-163efbc144cc"}
}
func main() {
TestPostLogin()
}
- 封装一个函数
TestPostLogin loginUrl登录地址url.Values{}是一个 map 类型,封装 POST 请求参数
type Values map[string][]string
http.PostForm发送表单形式请求- 与 GET 请求一样,请求会返回
resp *Response, err error - 解析数据一样
JSON 反序列化
使用 go 语言自带包 encoding/json 解析
解析本地 json 文件
创建测试 json 文件
{
"name": "测试用户",
"age": 12,
"sport": ["篮球", "羽毛球"]
}
Student 结构体
type Student struct {
Name string
Age int16
Sport []string
}
解析
func JsonParseFile() {
filepath := `E:\Code\moose-workspace\go-learn\http\test.json`
file, err := os.Open(filepath)
if err != nil {
return
}
var stu Student
if err = json.NewDecoder(file).Decode(&stu); err != nil {
return
}
fmt.Println(stu)
}
- 从文件中读取数据
- json.NewDecoder 创建解码对象,Decode 解码
- 运行输出
$ go run "e:\Code\moose-workspace\go-learn\http\main.go"
{测试用户 12 [篮球 羽毛球]}
解析简单数据结构
在登录之后,获取到数据,把返回的数据封装成一个结构体
修改,函数返回值 return data, nil
func TestPostLogin() ([]byte, error) {
loginUrl := "http://localhost:7000/api/v1/account/login"
values := url.Values{}
values.Add("accountName", "江景")
values.Add("password", "123")
values.Add("loginType", "password")
res, err := http.PostForm(loginUrl, values)
if err != nil {
fmt.Println(err)
return nil, err
}
data, err := ioutil.ReadAll(res.Body)
fmt.Println(string(data))
// 790e6c22-2ec8-4d1a-a852-163efbc144cc
return data, nil
}
LoginResponse 结构体
type LoginResponse struct {
Code int `json:"code"`
Message string `json:"message"`
Data string `json:"data"`
}
反序列化方法
func json.Unmarshal(data []byte, v interface{}) error
func ParseSimple() {
var loginResponse LoginResponse
data, err := TestPostLogin()
if err != nil {
fmt.Println(err)
return
}
err = json.Unmarshal(data, &loginResponse)
if err != nil {
fmt.Println("JSON解析错误")
return
}
fmt.Println("解析出来 :: ", loginResponse.Data)
}
- 定义
LoginResponse变量 - 调用
TestPostLogin回去请求的数据 - 调用
json.Unmarshal解析数据,传递数据(byte)和需要解析成那种数据格式,传递地址(&loginResponse) - 如果解析没有发送错误,就表示解析成功,那么
loginResponse变量就会值 - fmt.Println("解析出来 :: ", loginResponse.Data)
解析复杂一点数据
解析 GET 请求返回的数据封装结构体
看上一步 GET 请求
修改 TestGet,返回值和 POST 一致
分析返回的数据
- code,message 为 string 类型
- result 字段返回了一个数组,数组中是一个个对象
- 定义一个结构体,result 字段用切面,切面数据类型可以定义一个结构体或者用 map 映射类型
VideoResponse 结构体
type VideoResponse struct {
Code int `json:"code"`
Message string `json:"message"`
Result []VideoItem `json:"result"`
}
VideoItem 结构体
type VideoItem struct {
Sid string `json:"sid"`
Text string `json:"text"`
Type string `json:"type"`
Thumbnail string `json:"thumbnail"`
Video string `json:"video"`
Up string `json:"up"`
Down string `json:"down"`
Comment string `json:"comment"`
Uid string `json:"uid"`
Name string `json:"name"`
Header string `json:"header"`
TopCommentsContent string `json:"top_comments_content"`
TopCommentsVoiceuri string `json:"top_comments_voiceuri"`
TopCommentsUid string `json:"top_comments_uid"`
TopCommentsName string `json:"top_comments_name"`
TopCommentsHeader string `json:"top_comments_header"`
Passtime string `json:"passtime"`
}
解析测试
func ParseComplicated() {
var result VideoResponse
data, err := TestGet()
if err != nil {
fmt.Println(err)
return
}
err = json.Unmarshal(data, &result)
if err != nil {
fmt.Println("JSON解析错误")
return
}
for _, value := range result.Result {
fmt.Println(value.Comment)
fmt.Println(value.TopCommentsName)
}
}
- 遍历
result.Result,看是否能够拿到对应的值
JSON 序列化
func JsonSerialize() {
videoItems := make([]VideoItem, 2)
videoRsponse := VideoResponse{
Code: 200,
Message: "请求成功",
Result: videoItems,
}
fmt.Printf("%#v", videoRsponse)
}
序列化方法
func json.Marshal(v interface{}) ([]byte, error)
data, err := json.Marshal(videoRsponse)
if err != nil {
return
}
fmt.Printf("%v", string(data))
// fmt.Println(string(data))
第三方 json 解析库
总结
网络是传递数据的纽带;数据解析是交互的过程。
往期
文件操作、终端输入、文件存储~ 够浪|Go主题月 客户端和服务端建立长链接、实现消息推送|Go主题月 Gin 框架在实践中学习 ~ 够浪|Go主题月