Golang模塊之HTTP


0、前言

Go語言中內置net/http包提供了HTTP客戶端和服務端的實現

1、HTTP服務端

模擬一個HTTP服務端。

package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
)

// 定義客戶端提交的post請求的json數據內容
type  Auth struct {
	Username string `json: username`
	Password string `json: password`
}

// 定義服務端返回json數據給客戶端的內容
type Resp struct {
	Code string `json: code`
	Msg string `json: msg`
}


func f1(w http.ResponseWriter,r *http.Request){
	str := `from home`
	w.Write([]byte(str))
}

func f2(w http.ResponseWriter,r *http.Request){
	b,err := ioutil.ReadFile("./html/index.html")  // 讀取到html文件(byte類型切片)
	if err != nil {
		w.Write([]byte(fmt.Sprintf("%v",err)))
	}
	w.Write(b)  // 返回響應數據(必須傳入byte類型切片)
}

func f3(w http.ResponseWriter,r *http.Request){
	// 對於GET請求,參數都放在URL上(query param),請求體中是沒有數據的
	queryParam := r.URL.Query() // 自動幫我們識別URL中的urlParam
	query := queryParam.Get("query")
	page  := queryParam.Get("page")
	fmt.Println(query,page)
	fmt.Println(r.URL)     // 查看請求url
	fmt.Println(r.Method)  // 查看請求方法
	fmt.Println(ioutil.ReadAll(r.Body)) // 查看請求的body
	w.Write([]byte("ok"))
}


// post接口接收json數據
func f4(w http.ResponseWriter,r *http.Request){

	// 檢查是否為POST請求
	if r.Method != "POST"{
		w.WriteHeader(405) // 返回錯誤代碼
		return
	}
	body,_ := ioutil.ReadAll(r.Body)
	//body_str := string(body)
	//fmt.Println(body_str)

	var auth Auth
	var result Resp
	if err := json.Unmarshal(body,&auth);err == nil {
		// 拿到json數據
		fmt.Printf("用戶名:%v 密碼:%v",auth.Username,auth.Password)
		
		result.Code = "200"
		result.Msg = "Success"
		// 將返回的數據轉化成json格式
		ret,_ := json.Marshal(result)
		w.Write(ret)
	}else{
		result.Code = "500"
		result.Msg = "Failed"
		ret,_ := json.Marshal(result)
		w.Write(ret)
	}
}

func main(){
	http.HandleFunc("/home",f1)
	http.HandleFunc("/index",f2)
	http.HandleFunc("/xxx",f3)
	http.HandleFunc("/login",f4)

	// 啟動HTTP服務(監聽地址和端口)
	http.ListenAndServe("0.0.0.0:9090",nil)
}

2、HTTP客戶端

HTTP客戶端能夠發送HTTP請求,如:GET/POST

2.1、GET請求示例

package main

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
)

// net/http client

func main(){
	resp,err := http.Get("http://127.0.0.1:9090/index")
	if err != nil {
		fmt.Printf("get url failed,err:%v\n",err)
		return
	}
	body,err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Printf("read resp.Body failed,err:%v",err)
	}
	fmt.Println(string(body))

}

2.2、GET請求URL帶參數示例

我們可以在發送Get請求的時候在url上攜帶參數,例如:http://xx/xx?query=xx&page=xx

package main

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
)

// net/http client

func main(){
	//resp,err := http.Get("http://127.0.0.1:9090/xxx?query=jack&page=1")
	data := url.Values{} // url encode(攜帶get請求參數)
	urlObj,_ := url.Parse("http://127.0.0.1:9090/xxx")
	data.Set("query","jack")
	data.Set("page","1")
	queryStr := data.Encode()  // url encode之后的地址
	fmt.Println(queryStr)
	urlObj.RawPath = queryStr // 添加url
	req,err := http.NewRequest("GET",urlObj.String(),nil)

	// 發送請求
	resp,err := http.DefaultClient.Do(req)

	if err != nil {
		fmt.Printf("get url failed,err:%v\n",err)
		return
	}
	defer resp.Body.Close() // 關閉連接

	body,err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Printf("read resp.Body failed,err:%v",err)
	}
	fmt.Println(string(body))
}

短連接

默認情況下瀏覽器開啟了長連接,如果請求頻繁的話,可能會存在長連接還沒有關閉,又啟動了新的連接,一直這樣循環下去,就會導致連接超額,每個連接都會占用資源/網絡IO,那么其實可以通過關閉長連接的方式來避免這個問題

// 禁用KeepAlive的client
tr := &http.Transport{
	DisableKeepAlives:      true,
}
client := http.Client{
	Transport:     tr,
}
client.Do(req)

2.3、POST請求攜帶Json數據示例1

很多時候,我們在實現POST請求都需要攜帶對應規范的json格式數據,例如

{
	"username":"admin",
	"password":"123456"	
}

實現上面的規范來提交json數據

package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
)

type auth struct {
	Username string `json: username`
	Password string `json: password`
}

func main(){
	// post請求
	auths := auth{"admin","123456"}
	bs,_ := json.Marshal(auths) // 將結構體數據轉換成json格式
	resp,_ := http.Post("http://127.0.0.1:9090/login","application/json", bytes.NewBuffer([]byte(bs)))
	body, _ := ioutil.ReadAll(resp.Body)
	fmt.Printf("Post request with json result: %s\n", string(body))
}

2.4、POST請求攜帶Json數據示例1

很多時候,我們在實現POST請求都需要攜帶對應規范的json格式數據,例如

{
	"username":"admin",
	"password":"123456"	
}

實現上面的規范來提交json數據

package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
)

// 我們需要在結構體中添加注解來映射對應的key
type  auth struct {
	Username string `json: username`
	Password string `json: password`
}

func main(){
	// post請求
	auths := auth{"admin","123456"}
	bs,_ := json.Marshal(auths) // 將結構體數據轉換成json格式
	resp,_ := http.Post("http://127.0.0.1:9090/login","application/json", bytes.NewBuffer([]byte(bs)))
	body, _ := ioutil.ReadAll(resp.Body)
	fmt.Printf("Post request with json result: %s\n", string(body))
}

2.5、POST請求攜帶Json數據示例2

很多時候,我們在實現POST請求都需要攜帶對應規范的json格式數據,例如

{
	"username":"admin",
	"password":"123456"	
}

實現上面的規范來提交json數據

package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"go_dev/Project/EyeSkyAgent/conf"
	"io/ioutil"
	"net/http"
)

type  auth struct {
	Username string `json: username`
	Password string `json: password`
}

func main(){
	// post請求
	var data auth
	data.Username = "Jack"
	data.Password = "Jack123"
	bs, err := json.Marshal(data)

	reader := bytes.NewReader(bs)
	request, err := http.NewRequest("POST", "http://127.0.0.1:9090/login", reader)
	if err != nil{
		conf.Logger.Error("請求server端失敗...")
	}
	// 攜帶頭部
	request.Header.Set("Content-Type", "application/json;charset=UTF-8")
	client := http.Client{}
	// 返回服務端的響應數據
	resp, err := client.Do(request)
	if err != nil {
		fmt.Println("請求獲取響應失敗")
	}
	body, _ := ioutil.ReadAll(resp.Body)
	fmt.Printf("Post request with json result: %s\n", string(body))
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM