net-http包
# 5.net-http包
# 5.1 介绍
├── ClientGet
│ └── main.go // 发送get请求
├── ClientPost
│ └── main.go // 发送post请求
├── Server
│ └── main.go // web服务
1
2
3
4
5
6
2
3
4
5
6
Go语言内置的net/http包十分的优秀,提供了HTTP客户端和服务端的实现。
# 5.2 web服务
Server/main.go
- 客户端 请求信息 封装在 http.Request 对象中
- 服务端返回的响应报文会被保存在http.Response结构体中
- 发送给客户端响应的并不是http.Response,而是通过http.ResponseWriter接口来实现的
方法签名 | 描述 |
---|---|
Header() | 用户设置或获取响应头信息 |
Write() | 用于写入数据到响应体 |
WriteHeader() | 用于设置响应状态码,若不调用则默认状态码为200 OK |
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
type Data struct {
Name string `json:"name"`
}
// 处理GET请求: http://127.0.0.1:8005/req/get?name=root
func dealGetRequestHandler(w http.ResponseWriter, r *http.Request) {
// 获取请求的参数
query := r.URL.Query()
if len(query["name"]) > 0 {
// 方式1:通过字典下标取值
name := query["name"][0]
fmt.Println("通过字典下标获取:", name)
}
// 方式2:使用Get方法,,如果没有值会返回空字符串
name2 := query.Get("name")
fmt.Println("通过get方式获取:", name2)
type data struct {
Name2 string
}
d := data{
Name2: name2,
}
//w.Write([]byte(string(d))) // 返回string
json.NewEncoder(w).Encode(d) // 返回json数据
}
// 处理POST请求: http://127.0.0.1:8005/req/post {"name": "root"}
func dealPostRequestHandler(w http.ResponseWriter, r *http.Request) {
// 请求体数据
bodyContent, _ := ioutil.ReadAll(r.Body)
strData := string(bodyContent)
var d Data
json.Unmarshal([]byte(strData), &d) // gin.ShouldBind
fmt.Printf("body content:[%s]\n", string(bodyContent))
//返回响应内容
json.NewEncoder(w).Encode(fmt.Sprintf("收到名字:%s", d.Name))
}
func main() {
http.HandleFunc("/req/post", dealPostRequestHandler)
http.HandleFunc("/req/get", dealGetRequestHandler)
http.ListenAndServe(":8005", nil)
// 在golang中,你要构建一个web服务,必然要用到http.ListenAndServe
// 第二个参数必须要有一个handler
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
postman测试
测试发送get请求:http://127.0.0.1:8005/req/get?name=root
测试发送post请求:http://127.0.0.1:8005/req/post
# 5.3 请求数据
ClientGet/main.go
package main
import (
"fmt"
"io/ioutil"
"net/http"
"net/url"
)
func main() {
requestGet()
}
func requestGet() {
apiUrl := "http://127.0.0.1:8005/req/get"
data := url.Values{}
data.Set("name", "root")
u, _ := url.ParseRequestURI(apiUrl)
u.RawQuery = data.Encode() // URL encode
fmt.Println("请求路由为:", u.String())
resp, _ := http.Get(u.String())
b, _ := ioutil.ReadAll(resp.Body)
fmt.Println("返回数据为:", string(b))
}
/*
请求路由为: http://127.0.0.1:8005/req/get?name=root
返回数据为: ["root"]
*/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
ClientPost/main.go
package main
import (
"fmt"
"io/ioutil"
"net/http"
"strings"
)
func main() {
requestPost()
}
func requestPost() {
url := "http://127.0.0.1:8005/req/post"
// 表单数据 contentType := "application/x-www-form-urlencoded"
contentType := "application/json"
data := `{"name":"rootPort"}`
resp, _ := http.Post(url, contentType, strings.NewReader(data))
b, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(b))
}
/*
"收到名字:rootPort"
*/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 5.4 示例
Server/main.go
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
/*
使用net/http模块,开发一个简单的web server
1、提供get请求
2、提供post请求
http: 协议(和web服务器进行交互的规范,规则)
Get: 从数据库读取数据,比如 查询订单
- get请求参数是从url上直接读取(一般数据都比较少)
Post: 创建新的数据,163购买票(在数据库会添加一条数据,购票记录)
- 从http的body中获取的数据
Put: 修改数据,更新支付宝上的用户信息(修改我的手机号)
Delete: 删除数据库中数据
*/
/*
开发一个web服务器主要的步骤
第一步:路由
第二步:处理函数
- 解析请求的数据(获取某一个商品,你需要把商品Id信息携带给后端)
- 根据请求数据参数查询数据库
- 响应数据(把从数据库读取的数据,给返回给浏览器或者请求方)
*/
func main() {
//第一步:路由
// http://127.0.0.1:8005 /req/get ?name=zhangsan
http.HandleFunc("/req/get", dealGetHandler)
/*
"/req/get": 路由URL除去域名的哪一块(http://www.example.com /book/1/)
dealGetHandler: 处理函数(处理服务请求)
*/
http.HandleFunc("/req/post", dealPostHandler) // POST
fmt.Println("http://127.0.0.1:8005/req/get")
// 第三步:启动服务
http.ListenAndServe(":8005", nil)
/*
addr: 当前server监听的端口号和ip
handler:处理函数
*/
}
// 处理函数的名字用驼峰命名: xxxHandler函数名
// 第二步:处理函数(处理get请求)
/*
- 1)解析请求的数据(获取某一个商品,你需要把商品Id信息携带给后端)
http.Request:解析url中的数据或者post请求中body的数据
- 2)响应数据(把从数据库读取的数据,给返回给浏览器或者请求方)
http.ResponseWriter: 本质是一个interface接口,定义三个方法,进行返回数据
*/
func dealGetHandler(w http.ResponseWriter, r *http.Request) {
//1)解析请求的数据
query := r.URL.Query() // 返回 map[string][]string
// 1.1 通过字典下标取get路由参数
if len(query["name"]) > 0 {
names := query["name"][0]
fmt.Println("字典下标取值", names)
}
// 1.2 通过Get方法取值
name2 := query.Get("name")
fmt.Println("通过get方法取值", name2)
fmt.Println(query)
//2)响应数据
//// 2.1 返回一个简单字符串
//w.Write([]byte("hello world!"))
// 2.2 返回一个json数据
// 加上我们拿到了 name=zhangsan,我们到数据库取出了zhangsan用户的信息
type Info struct {
Name string
Password string
Age int
}
// 假设这是从数据库中取出
u := Info{
Name: name2,
Password: "123456",
Age: 24,
}
json.NewEncoder(w).Encode(u)
}
type Info struct {
Name string `json:"name"`
Password string `json:"password"`
}
// 和get请求是一模一样的写法,这是一个post请求
func dealPostHandler(w http.ResponseWriter, r *http.Request) {
// r *http.Request是结构的对象
// r.URL.query()从url取请求参数
// post请求从http的body中获取数据
// r.Body是结构体 Request 中的字段 r.body 其实是*http.Request.body
bodyContent, _ := ioutil.ReadAll(r.Body) // 返回的是一个byte
//fmt.Printf("%T %v", bodyContent, bodyContent)
// 获取string
//strData := string(bodyContent)
// 如何才能解析这个string字符串(str转结构体)
var d Info
//json.Unmarshal([]byte(strData), &d)
json.Unmarshal(bodyContent, &d)
fmt.Println("获取的数据name:", d.Name)
fmt.Println(d)
w.Write([]byte("hello world Post"))
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
ClientGet/main.go
package main
import (
"fmt"
"io/ioutil"
"net/http"
"net/url"
)
/*
使用net/http模块,作为web的客户端发送get请求
应用场景:
1) 爬虫,获取页面数据
2) 调用其他服务中的接口
*/
func main() {
//// 1、直接通过url拼接处url字符串
//apiUrl := "http://127.0.0.1:8005/req/get?name=zhangsan"
apiUrl := "http://127.0.0.1:8005/req/get"
// 2、通过url进行解析
// http://127.0.0.1:8005/req/get?name=zhangsan
data := url.Values{}
data.Set("name", "zhangsan")
u, _ := url.ParseRequestURI(apiUrl)
u.RawQuery = data.Encode()
fmt.Println(u.String())
resp, err := http.Get(u.String())
if err != nil {
fmt.Println(err)
}
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
ClientPost/main.go
package main
import (
"fmt"
"io/ioutil"
"net/http"
"strings"
)
func main() {
url := "http://127.0.0.1:8005/req/post"
// 模拟form表单提交数据 contentType := "application/x-www-form-urlencoded"
// 传json数据: json contentType := "application/json"
contentType := "application/json"
data := `{
"name": "root",
"password": "123456"
}`
resp, _ := http.Post(url, contentType, strings.NewReader(data))
b, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(b))
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
上次更新: 2022/06/23, 23:41:50