On this page
    
    
                                                
                                                article
                                                
                                                
                                            
                                                4.Go-net-http
Go net-http包介绍
net-http介绍
.
├─ ClientGet
│ └── main.go // 发送get请求
├─ ClientPost
│ └── main.go // 发送post请求
├─ Server
│ └── main.go // web服务
      Go语言内置的net/http包十分的优秀,提供了HTTP客户端和服务端的实现。
1.Server/main.go
- 客户端 请求信息 封装在
http.Request对象中 - 服务端返回的 响应报文 会被保存在
http.Response结构体中 - 发送给客户端响应的并不是
http.Response,而是通过http.ResponseWriter接口来实现的 
| 方法签名 | 描述 | 
|---|---|
Header() | 
用户设置或获取响应头信息 | 
Write() | 
用于写入数据到响应体 | 
WriteHeader() | 
用于设置响应状态码,若不调用则默认状态码为200 OK。 | 
package main
import (
	"encoding/json"
	"io"
	"log"
	"net/http"
)
// 定义入参结构体
type Data struct {
	Speak string `json:"speak"`
}
// 处理get请求
func dealGetReqHandler(w http.ResponseWriter, r *http.Request) {
	query := r.URL.Query()
	//获取请求参数两种方法
	if len(query["name"]) > 0 {
		name := query["name"][0]
		log.Printf("1.通过map中切片的下标获取:%s\n", name)
	}
	name2 := query.Get("name") //没有的话就会返回空值
	log.Printf("2.通过Get方法获取:%s\n", name2)
	data := &Data{
		name2 + "是笨蛋",
	}
	//响应json数据:序列化了一下data对象,并写入响应体w中
	json.NewEncoder(w).Encode(data)
        //也可以w.Write([]byte(··json数据··))
}
// 处理post请求
func dealPostReqHandler(w http.ResponseWriter, r *http.Request) {
	//获取请求体数据
	bodyByte, err := io.ReadAll(r.Body)
	if err != nil {
		w.Write([]byte(err.Error()))
	}
	//转成结构体示范,为了可以更好的处理数据,而不是必须转结构体才能json返回
	bodyStr := string(bodyByte)
	data := &Data{}
	json.Unmarshal([]byte(bodyStr), &data)
	log.Printf("从post请求体中获取到的数据:%s\n", data.Speak)
	//返回响应内容
	data.Speak = data.Speak + "是笨蛋"
	//返回响应体内容
	json.NewEncoder(w).Encode(data)
}
// 启动http服务
func main() {
	//注册全局路由
	http.HandleFunc("/req/post", dealPostReqHandler)
	http.HandleFunc("/req/get", dealGetReqHandler)
	http.ListenAndServe(":8000", nil)
}
      - 一个路由对应一个handler:
/api/xxx对应的是一个处理方法 http.ResponseWriter用来响应内容*http.Request用来拿到请求头或者请求参数
测试
fei@feideMBP Server % go run main.go
2024/10/02 02:43:58 1.通过map中切片的下标获取:虞锋
2024/10/02 02:43:58 2.通过Get方法获取:虞锋
2024/10/02 02:44:04 从post请求体中获取到的数据:虞锋
fei@feideMBP ~ % curl http://127.0.0.1:8000/req/get?name=虞锋
{"speak":"虞锋是笨蛋"}
fei@feideMBP ~ % curl -X POST http://127.0.0.1:8000/req/post \
-H 'Content-Type: application/json' \
-d '{"speak":"虞锋"}'
{"speak":"虞锋是笨蛋"}
      2.ClientGet/main.go
package main
import (
	"io"
	"log"
	"net/http"
	"net/url"
)
func main() {
	apiUrl := "http://localhost:8000/req/get"
	//定义url参数
	data := url.Values{}
	data.Set("name", "httpGet-root")
	//组装url
	u, err := url.ParseRequestURI(apiUrl)
	if err != nil {
		panic(err)
	}
	u.RawQuery = data.Encode()
	log.Printf("请求路由为:%s\n", u.String())
	//发起请求
	resp, err := http.Get(u.String())
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()
	//读取
	byteBody, _ := io.ReadAll(resp.Body)
	log.Printf("返回数据为:%s\n", string(byteBody))
}
      测试
# 启动server
fei@feideMBP Server % go run main.go 
2024/10/02 03:39:08 1.通过map中切片的下标获取:httpGet-root
2024/10/02 03:39:08 2.通过Get方法获取:httpGet-root
# 启动getclient
fei@feideMBP ClientGet % go run main.go 
2024/10/02 03:39:08 请求路由为:http://localhost:8000/req/get?name=httpGet-root
2024/10/02 03:39:08 返回数据为:{"speak":"httpGet-root是笨蛋"}
      3.ClientPost/main.go
package main
import (
	"io"
	"log"
	"net/http"
	"strings"
)
func main() {
	apiUrl := "http://localhost:8000/req/post"
	//定义请求体及header
	contentType := "application/json"
	data := `{"speak":"httpPost"}`
	resp, err := http.Post(apiUrl, contentType, strings.NewReader(data))
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()
	//读取
	byteBody, _ := io.ReadAll(resp.Body)
	log.Printf("返回数据为:%s\n", string(byteBody))
}
      测试
# 启动server
fei@feideMBP Server % go run main.go
2024/10/02 03:51:39 从post请求体中获取到的数据:httpPost
# 启动postclient
fei@feideMBP ClientPost % go run main.go
2024/10/02 03:51:39 返回数据为:{"speak":"httpPost是笨蛋"}
      Last updated 02 Oct 2024, 03:56 +0800 .