本文主要通过net/http实现简单server,另外根据net/http,区分简单请求和带参数的复杂请求实现客户端。
1.server端
| package main |
| |
| import ( |
| "encoding/json" |
| "log" |
| "net/http" |
| ) |
| |
| func main() { |
| http.HandleFunc("/index", index) |
| http.HandleFunc("/login", login) |
| |
| log.Println("http server is starting now...") |
| http.ListenAndServe(":8080", nil) |
| } |
| |
| type Auth struct { |
| User string `json:"user"` |
| Pass string `json:"pass"` |
| } |
| |
| type LoginResp struct { |
| Msg string `json:"msg"` |
| Code int `json:"code"` |
| } |
| |
| func index(w http.ResponseWriter, r *http.Request) { |
| log.Printf("calling %s from %s", r.URL,r.RemoteAddr) |
| clientIP := r.Host |
| respData, _ := json.Marshal(map[string]string{"msg": "hello index", "user": clientIP}) |
| |
| w.Write(respData) |
| |
| |
| } |
| |
| func login(w http.ResponseWriter, r *http.Request) { |
| log.Printf("calling %s from %s", r.URL,r.RemoteAddr) |
| var auth Auth |
| if err := json.NewDecoder(r.Body).Decode(&auth); err != nil { |
| defer r.Body.Close() |
| log.Println(err) |
| } |
| |
| var resp LoginResp |
| resp.Msg = "login success." |
| resp.Code = 0 |
| if err := json.NewEncoder(w).Encode(resp); err != nil { |
| log.Println(err) |
| } |
| } |
2.client端
2.1 简单请求
| package main |
| |
| import ( |
| "io/ioutil" |
| "log" |
| "net/http" |
| ) |
| |
| func main() { |
| |
| GetIndex() |
| } |
| |
| const ( |
| url string = "http://localhost:8080" |
| ) |
| |
| func GetIndex() { |
| indexUrl := url + "/index" |
| resp, _ := http.Get(indexUrl) |
| defer resp.Body.Close() |
| |
| data, _ := ioutil.ReadAll(resp.Body) |
| |
| |
| |
| |
| |
| log.Printf("recv from server: %s, data type: %T", data, data) |
| } |
| |
2.2 带参数的请求
| package main |
| |
| import ( |
| "bytes" |
| "encoding/json" |
| "io" |
| "io/ioutil" |
| "log" |
| "net/http" |
| "strings" |
| "time" |
| ) |
| |
| func main() { |
| GetIndex() |
| PostLogin() |
| PostLoginVersion2() |
| } |
| |
| const ( |
| url = "http://127.0.0.1:8080" |
| ) |
| |
| func GetIndex() string { |
| indexUrl := url + "/index" |
| client := &http.Client{Timeout: 10*time.Second} |
| resp, err := client.Get(indexUrl) |
| if err != nil { |
| log.Println(err) |
| } |
| defer resp.Body.Close() |
| |
| |
| var buf [1024]byte |
| res := bytes.NewBuffer(nil) |
| for { |
| n, err := resp.Body.Read(buf[0:]) |
| res.Write(buf[0:n]) |
| if err != nil && err == io.EOF { |
| break |
| } else if err != nil { |
| log.Println(err) |
| } |
| } |
| |
| log.Println(res.String()) |
| return res.String() |
| } |
| |
| type Auth struct { |
| User string `json:"user"` |
| Pass string `json:"pass"` |
| } |
| |
| func PostLogin() string { |
| |
| loginUrl := url + "/login" |
| client := &http.Client{Timeout: 10 * time.Second} |
| data := Auth{"name", "passwd"} |
| jsonStr, _ := json.Marshal(data) |
| resp, err := client.Post(loginUrl, "application/json", bytes.NewBuffer(jsonStr)) |
| defer resp.Body.Close() |
| if err != nil { |
| log.Println(err) |
| } |
| |
| res, _ := ioutil.ReadAll(resp.Body) |
| log.Println(string(res)) |
| return string(res) |
| } |
| |
| func PostLoginVersion2() { |
| |
| loginUrl := url + "/login" |
| data := Auth{"name", "passwd"} |
| bytes, _ := json.Marshal(data) |
| body := strings.NewReader(string(bytes)) |
| client := &http.Client{} |
| req, err := http.NewRequest("POST", loginUrl, body) |
| |
| req.Header.Set("Content-Type", "application/json") |
| |
| resp, err := client.Do(req) |
| defer resp.Body.Close() |
| |
| respData, err := ioutil.ReadAll(resp.Body) |
| if err != nil { |
| log.Println(err) |
| } |
| |
| log.Println("PostLoginVersion2's response data:", string(respData)) |
| } |
3.响应数据的解析
| |
| data, _ := ioutil.ReadAll(resp.Body) |
| |
| |
| var data interface{} |
| _ = json.NewDecoder(resp.Body).Decode(&data) |
| |
| |
| ... |
| var buf [1024]byte |
| res := bytes.NewBuffer(nil) |
| for { |
| n, err := resp.Body.Read(buf[0:]) |
| res.Write(buf[0:n]) |
| if err != nil && err == io.EOF { |
| break |
| } else if err != nil { |
| log.Println(err) |
| } |
| } |
| ... |
4.通过NewClient || client 构建req
构建带请求参数的请求时,即带上了body,只要实现了io.Reader接口的都可以, 这里介绍几种方法侯建body:
| 1.通过bytes包实现 |
| data := Auth{"name", "passwd"} |
| jsonStr, _ := json.Marshal(data) |
| body := bytes.NewBuffer(jsonStr) |
| |
| 2.通过strings包实现 |
| data := Auth{"name", "passwd"} |
| bytes, _ := json.Marshal(data) |
| body := strings.NewReader(string(bytes)) |
| |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了