一、HTTP请求
根据 HTTP 标准,HTTP 请求可以使用多种请求方法。在日常开发中大多数会用到 5 种请求方法: GET、POST、PUT、PATCH 和 DELETE
| 方法 | 描述 |
| GET | 请求指定的页面信息,并返回实体主体 |
| POST | 向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST 请求可能会导致新的资源的建立和/或已有资源的修改 |
| PUT | 从客户端向服务器传送的数据取代指定的文档的内容 |
| DELETE | 请求服务器删除指定的页面 |
| PATCH | 是对 PUT 方法的补充,用来对已知资源进行局部更新 |
在一次http请求(request)中可携带参数的地方:
| 部分 | 用途 |
| URL部分 | 即以?和&分割的url参数 |
| header部分 | 在http头中的字段,比如常用的cookie |
| content-body部分 | 请求正文,如果是get请求则为空;如果是post请求,则请求头中的Content-Type字段规定了content-body部分应该怎么被解析 |
二、GET请求
2.1 不带参数的GET请求
package main import ( "fmt" "io/ioutil" "net/http" ) func HttpGet(url string) []byte { //发起请求 res, err := http.Get(url) if err != nil { fmt.Println("get请求失败:", err) } //延迟关闭(返回response的body尽量关闭,避免内存泄露) defer res.Body.Close() // 请求头 fmt.Println(res.Header) // 请求相应码 fmt.Println(res.Status) //读取body数据 body, err := ioutil.ReadAll(res.Body) if err != nil { fmt.Println("读取body失败:", err) return nil } return body } func main() { UrlPath := "https://xxx/instance" body := HttpGet(UrlPath) //打印body,以字符串形式 fmt.Printf(string(body)) }
2.2 带参数的GET请求
2.2.1 静态参数
若参数是固定的,则将1.1中的UrlPath设置为完整的请求即可,例: UrlPath := "https://xxx/instance?name=xxx&age=18"
2.2.2 动态参数
package main import ( "fmt" "io/ioutil" "net/http" ) func HttpGetUrl(url string) []byte { //正常来说,GET请求所有的参数都应该是放在url上,body请求体中是没有数据的 //请求头可能会携带token之类的参数 //新建一个GET请求 request, err := http.NewRequest("GET", url, nil) if err != nil { panic(err) } //请求头部信息 //Set时候,如果原来这一项已存在,后面的就修改已有的 //Add时候,如果原本不存在,则添加,如果已存在,就不做任何修改 //最终服务端获取的应该是token2 request.Header.Set("User-Agent", "自定义浏览器1...") request.Header.Set("User-Agent", "自定义浏览器2...") request.Header.Add("Host", "www.xxx.com") //header: map[User-Agent:[自定义浏览器2...]] request.Header.Add("name", "alnk") request.Header.Add("name", "alnk2") //header: map[Name:[alnk alnk2] User-Agent:[自定义浏览器2...]] request.Header.Add("Authorization", "token1...") //token fmt.Println("header: ", request.Header) //url参数 query := request.URL.Query() query.Add("id", "1") query.Add("id", "2") query.Add("name", "wan") request.URL.RawQuery = query.Encode() fmt.Println("request.URL: ", request.URL) //request.URL: https://xxx/instance?id=1&id=2&name=wan //发送请求给服务端,实例化一个客户端 client := &http.Client{} res, err := client.Do(request) if err != nil { panic(err) } defer res.Body.Close() //服务端返回数据 b, err := ioutil.ReadAll(res.Body) if err != nil { panic(err) } return b } func main() { UrlPath := "https://xxx/instance" body := HttpGetUrl(UrlPath) //打印body,以字符串形式 fmt.Printf(string(body)) }
2.3 解析json类型的返回结果
有些请求返回的数据是json格式,无法直接使用,需要进行反序列化
type result struct { Name string `json:"name"` Age int `json:"age"` } func main() { UrlPath := "https://xxx/instance" body := HttpGetUrl(UrlPath) //打印body,以字符串形式 fmt.Printf(string(body)) var res result err := json.Unmarshal(body, &res) if err != nil { fmt.Println(err) return } // 拿到数据以后,就可以自行处理数据了,比如存到数据库里 fmt.Printf("%#v", res) }
三、POST请求
3.1 Content-Type类型
| Content-Type | 用途 |
| application/x-www-form-urlencoded | 默认的方式, 比如 title=test&id=1010 |
| multipart/form-data | 如果你的请求里包含多个文件等二进制信息,则form 的 enctyped 需要等于这个值,浏览器生成一个 boundary 用于分割不同的字段 |
| application/json | 以json格式传送 |
| raw | 纯二进制格式,这需要服务器拿到消息后自己定义解析方式,比如protobuf |
3.2 使用 http.Post() + application/x-www-form-urlencoded
package main import ( "fmt" "io/ioutil" "net/http" "net/url" "strings" ) func HttpPost(urlP string) []byte { //url.Values用来存放body参数,无参数不加 urlValues := url.Values{} //urlValues ---> map[string][]string urlValues.Add("user", "test") urlValues.Add("password", "test123") //编码 reqBody := urlValues.Encode() //最终http报文里面的body是 user=test&password=test123 resp, err := http.Post(urlP, "application/x-www-form-urlencoded", strings.NewReader(reqBody)) if err != nil { fmt.Println(err) return nil } defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) return body } func main() { var urlP = "https://www.xxx.com/json" body := HttpPost(urlP) fmt.Println(string(body)) }
3.3 使用 http.Post() + application/json
package main import ( "bytes" "encoding/json" "fmt" "io/ioutil" "net/http" ) func HttpPost(urlP string) []byte { // 参数 data := make(map[string]interface{}) data["user"] = "test" data["password"] = "test123" // 序列化 bytesData, _ := json.Marshal(data) resp, err := http.Post(urlP, "application/json", bytes.NewReader(bytesData)) if err != nil { fmt.Println(err) return nil } defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) return body } func main() { var urlP = "https://www.xxx.com/json" body := HttpPost(urlP) fmt.Println(string(body)) }
3.4 http.PostForm()
提交post表单
package main import ( "fmt" "io/ioutil" "net/http" "net/url" ) func HttpPost(urlP string) []byte { urlValues := url.Values{} urlValues.Add("user", "test") urlValues.Add("password", "test123") resp, err := http.PostForm(urlP, urlValues) //resp, err := http.PostForm(urlP, url.Values{ // "user": {"test"}, // "password": {"test123"}, //}) if err != nil { fmt.Println(err) return nil } defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) return body } func main() { var urlP = "https://www.xxx.com/json" body := HttpPost(urlP) fmt.Println(string(body)) }
四、http.NewRequest()
如2.2.2,复杂的http请求,可以通过http.NewRequest 来创建请求,再用client.Do发送,http.NewRequest支持各种请求方法
get请求如2.2.2
4.1 POST
package main import ( "fmt" "io/ioutil" "net/http" "net/url" "strings" ) func HttpPost(urlP string) []byte { //请求body urlMap := url.Values{} urlMap.Add("user", "test") urlMap.Add("password", "test123") //新建请求 request, err := http.NewRequest("POST", urlP, strings.NewReader(urlMap.Encode())) if err != nil { fmt.Println(err) return nil } fmt.Println("request.url: ", request.URL) fmt.Println("request.method: ", request.Method) //请求头部信息 request.Header.Add("Authorization", "token1...") //post formdata表单请求 request.Header.Add("Content-Type", "application/x-www-form-urlencoded") ////发送json格式的参数 //data := map[string]interface{}{ // "user": "test", // "password": 123, //} //// 序列化 //bytesData, _ := json.Marshal(data) //request, _ := http.NewRequest("POST", urlP, strings.NewReader(string(bytesData))) //请求头设置 //request.Header.Add("Authorization", "token1...") //token //request.Header.Add("Content-Type", "application/json") //json请求 //实例化一个客户端 client := &http.Client{} //发送请求到服务端 resp, err := client.Do(request) if err != nil { fmt.Println(err) return nil } defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) return body } func main() { var urlP = "https://www.xxx.com/json" body := HttpPost(urlP) fmt.Println(string(body)) }
4.2 DELETE
package main import ( "fmt" "io/ioutil" "net/http" ) func HttpDelete(urlD string) []byte { //携带tonken //通过ID删除 request, err := http.NewRequest("DELETE", urlD, nil) if err != nil { panic(err) } //请求头部信息 request.Header.Add("Authorization", "token1...") //token //url参数 query := request.URL.Query() query.Add("id", "1") query.Add("id", "2") query.Add("id", "3") request.URL.RawQuery = query.Encode() //发送请求给服务端 client := &http.Client{} res, err := client.Do(request) if err != nil { panic(err) } defer res.Body.Close() //服务端返回数据 b, err := ioutil.ReadAll(res.Body) if err != nil { panic(err) } return b } func main() { var urlD = "https://www.xxx.com/json" body := HttpDelete(urlD) fmt.Println(string(body)) }
4.3 PUT
package main import ( "encoding/json" "fmt" "io/ioutil" "net/http" "strings" ) func HttpPut(urlP string) []byte { //通过ID修改用户数据 //数据格式化 data := map[string]interface{}{ "name": "wang", "age": 18, } dataStr, err := json.Marshal(data) if err != nil { panic(err) } //创建一个新的请求 request, err := http.NewRequest("PUT", urlP, strings.NewReader(string(dataStr))) if err != nil { panic(err) } //请求头设置 request.Header.Add("Authorization", "token1...") //token request.Header.Add("Content-Type", "application/json") //json请求 //url参数 query := request.URL.Query() query.Add("id", "1") request.URL.RawQuery = query.Encode() //发送请求给服务端 client := &http.Client{} res, err := client.Do(request) if err != nil { panic(err) } defer res.Body.Close() //服务端返回数据 b, err := ioutil.ReadAll(res.Body) if err != nil { panic(err) } return b } func main() { var urlP = "https://www.xxx.com/json" body := HttpPut(urlP) fmt.Println(string(body)) }
4.4 PATCH
package main import ( "encoding/json" "fmt" "io/ioutil" "net/http" "strings" ) func HttpPatch(urlP string) []byte { data := map[string]interface{}{ "user": "test", "password": 123, } dataStr, err := json.Marshal(data) if err != nil { panic(err) } //创建一个新的请求 request, err := http.NewRequest("PATCH", urlP, strings.NewReader(string(dataStr))) if err != nil { panic(err) } //请求头设置 request.Header.Add("Authorization", "token1...") //token request.Header.Add("Content-Type", "application/json") //json请求 //发送请求给服务端 client := &http.Client{} res, err := client.Do(request) if err != nil { panic(err) } defer res.Body.Close() //服务端返回数据 b, err := ioutil.ReadAll(res.Body) if err != nil { panic(err) } return b } func main() { var urlP = "https://www.xxx.com/json" body := HttpPatch(urlP) fmt.Println(string(body)) }