整理自网络文章
GET请求示例
package main
import (
"fmt"
"io/ioutil"
"net/http"
)
func main() {
resp, err := http.Get("http://www.baidu.com/")
if err != nil {
fmt.Println("get failed, err:", err)
return
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println("read from resp.Body failed,err:", err)
return
}
fmt.Print(string(body))
}
带参数的GET请求示例一(建议统一使用示例二的方法)
package main
import (
"fmt"
"io/ioutil"
"net/http"
"net/url"
)
func main() {
apiUrl := "http://127.0.0.1:8080/get"
// URL param
data := url.Values{}
data.Set("name", "王二小")
data.Set("age", "18")
//把string转换为url
u, err := url.ParseRequestURI(apiUrl)
if err != nil {
fmt.Printf("parse url requestUrl failed,err:%v\n", err)
}
//将参数添加到请求url
u.RawQuery = data.Encode() // URL encode
fmt.Println(u.String())
resp, err := http.Get(u.String())
if err != nil {
fmt.Println("post failed, err:%v\n", err)
return
}
defer resp.Body.Close()
b, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println("get resp failed,err:%v\n", err)
return
}
fmt.Println(string(b))
}
接收带参请求的server端示例
package main
import (
"fmt"
"log"
"net/http"
)
func main() {
http.HandleFunc("/get", getHandler)
log.Fatal(http.ListenAndServe(":8080", nil))
}
func getHandler(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
data := r.URL.Query()
fmt.Println(data.Get("name"))
fmt.Println(data.Get("age" ))
answer := `{"status": "ok"}`
w.Write([]byte(answer))
}
带参数和Hearder的GET请求示例二
net/http包没有封装请求带header的get或者post方法,所以,要想请求中带header,只能使用NewRequest方法。不带header的请求也可以使用此方法。
package main
import (
"fmt"
"io/ioutil"
"net/http"
)
func main() {
client := &http.Client{}
apiURL := "http://127.0.0.1:8080/get"
req, err := http.NewRequest("GET", apiURL, nil)
//添加查询参数
q := req.URL.Query()
q.Add("username", "admin")
q.Add("password", "123")
req.URL.RawQuery = q.Encode()
fmt.Println(req.URL.String())
req.Header.Add("Content-Type", "application/json")
if err != nil {
fmt.Printf("post failed, err:%v\n\n", err)
return
}
resp, _ := client.Do(req)
defer resp.Body.Close()
b, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Printf("get resp failed,err:%v\n\n", err)
return
}
fmt.Println(string(b))
}
输出:
http://127.0.0.1:8080/get?password=123&username=admin
{"status": "ok"}
带参数的GET请求示例二服务端
package main
import (
"fmt"
"io/ioutil"
"log"
"net/http"
)
func main() {
http.HandleFunc("/get/", getHandler)
log.Fatal(http.ListenAndServe(":8080", nil))
}
func getHandler(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
fmt.Println(r.URL)
//获取查询参数
data := r.URL.Query()
fmt.Println(data.Get("username"))
fmt.Println(data.Get("password"))
answer := `{"status": "ok"}`
w.Write([]byte(answer))
}
get请求后的输出:
/get/?password=123&username=admin
admin
123
POST 请求
package main
import (
"fmt"
"io/ioutil"
"net/http"
"strings"
)
func main() {
url := "http://127.0.0.1:8080/post"
// 表单格式数据
//contentType := "application/x-www-form-urlencoded"
//data := "name=王二小&age=18"
// json格式数据,一般使用结构体发送或解析json格式数据
contentType := "application/json"
data := `{"name":"王二小","age":18}`
resp, err := http.Post(url, contentType, strings.NewReader(data))
if err != nil {
fmt.Println("post failed, err:%v\n", err)
return
}
defer resp.Body.Close()
b, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println("get resp failed,err:%v\n", err)
return
}
fmt.Println(string(b))
}
处理POST请求的server端
package main
import (
"fmt"
"io/ioutil"
"log"
"net/http"
)
func main() {
http.HandleFunc("/post", postHandler)
log.Fatal(http.ListenAndServe(":8080", nil))
}
func postHandler(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
// 1. 请求类型是application/x-www-form-urlencoded时解析form数据
r.ParseForm()
fmt.Println(r.PostForm) // 打印form数据
fmt.Println(r.PostForm.Get("name"), r.PostForm.Get("age"))
// 2. 请求类型是application/json时从r.Body读取数据
b, err := ioutil.ReadAll(r.Body)
if err != nil {
fmt.Println("read request.Body failed, err:%v\n", err)
return
}
fmt.Println(string(b))
answer := `{"status": "ok"}`
w.Write([]byte(answer))
}
发送带header的post同样需要使用NewRequest方法
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
type Instance struct {
Values Values `json:"values"`
}
type Values struct {
Company string
FirstName string `json:"First Name"`
LastName string `json:"Last Name"`
}
func main() {
url := "http://127.0.0.1:8080/post"
s := Instance{Values: Values{
Company: "123",
FirstName: "123",
LastName: "123",
}}
js, err := json.MarshalIndent(&s, "", "\t")
req, err := http.NewRequest("POST", url, bytes.NewBuffer(js))
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil{
panic(err)
}
defer resp.Body.Close()
b, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Printf("get resp failed,err:%v\n\n", err)
return
}
fmt.Println(string(b))
}
#对应的json body
{
"values": {
"Company": "123",
"First Name": "123",
"Last Name": "123"
}
}
结构体对应带数组的json
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
type InstanceDetail struct {
Entries []InstanceEntries `json:"entries"`
}
type InstanceEntries struct {
Values InstanceEntriesValues `json:"values"`
}
type InstanceEntriesValues struct {
IncidentNumber string `json:"Incident Number"`
Description string `json:"Description"`
ExternalReason string `json:"ExternalReason"`
DetailedDescription string `json:"Detailed Description"`
ExternalName string `json:"ExternalName"`
}
func main() {
url := "http://127.0.0.1:8080/post"
s := InstanceDetail{Entries: []InstanceEntries{{Values: InstanceEntriesValues{
IncidentNumber: "0000000001",
Description: "Test",
DetailedDescription: "Test",
ExternalName: "ExternalName",
ExternalReason: "EscaltionReason",
}},
{InstanceEntriesValues{
IncidentNumber: "0000000002",
Description: "Test",
DetailedDescription: "Test",
ExternalName: "ExternalName",
ExternalReason: "EscaltionReason",
}}}}
js, err := json.MarshalIndent(s, "", " ") // 将json形式的字符串进行格式化
req, err := http.NewRequest("POST", url, bytes.NewBuffer(js))
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil{
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println("response Body:", string(body))
}
#对应的json
{
"entries": [
{
"values": {
"Incident Number": "0000000001",
"Description": "Test",
"ExternalReason": "EscaltionReason",
"Detailed Description": "Test",
"ExternalName": "ExternalName"
}
},
{
"values": {
"Incident Number": "0000000002",
"Description": "Test",
"ExternalReason": "EscaltionReason",
"Detailed Description": "Test",
"ExternalName": "ExternalName"
}
}
]
}
解析json
json:"entries"
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
)
type InstanceDetail struct {
Entries []InstanceEntries `json:"entries"`
}
type InstanceEntries struct {
Values InstanceEntriesValues `json:"values"`
}
type InstanceEntriesValues struct {
IncidentNumber string `json:"Incident Number"`
Description string `json:"Description"`
ExternalReason string `json:"ExternalReason"`
DetailedDescription string `json:"Detailed Description"`
ExternalName string `json:"ExternalName"`
}
func main() {
http.HandleFunc("/post", postHandler)
log.Fatal(http.ListenAndServe(":8080", nil))
}
func postHandler(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
b, err := ioutil.ReadAll(r.Body)
if err != nil {
fmt.Println("read request.Body failed, err:%v\n", err)
return
}
fmt.Println("r.Body:",string(b))
answer := `{"status": "ok"}`
w.Write([]byte(answer))
var data InstanceDetail
json.Unmarshal(b, &data)
//因为entries是个数组所以用数组(下标)方式访问,对象用点(".")访问
fmt.Println(data.Entries[0].Values.IncidentNumber)
fmt.Println(data.Entries[0].Values.Description)
fmt.Println(data.Entries[1].Values.IncidentNumber)
fmt.Println(data.Entries[1].Values.Description)
//如果这里数组的元素数量不固定时,需要使用for循环去获取数组元素的值
//for _, v := range data.Entries {
// fmt.Println("Incident Number:", v.Values.IncidentNumber)
// fmt.Println("Description:", v.Values.Description)
//}
}