整理自网络文章

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)
		//}
}