欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

快速上手GO的net/http包

 更新時(shí)間:2025年05月26日 09:09:42   作者:我的golang之路果然有問題  
本文主要介紹了快速上手GO的net/http包,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

針對(duì)GO中net/http包的學(xué)習(xí)筆記

基礎(chǔ)快速了解

創(chuàng)建簡(jiǎn)單的GOHTTP服務(wù)

func main() {  
    http.HandleFunc("/hello", sayHello)  
    http.ListenAndServe(":8080", nil) //創(chuàng)建基本服務(wù)  
}  
  
func sayHello(w http.ResponseWriter, r *http.Request) {  
    w.Write([]byte("Hello, World!"))  
}

訪問8080/hello進(jìn)行測(cè)試

Handler接口定義:(這部分后面又詳細(xì)解釋)

type Handler interface {  
    ServeHTTP(ResponseWriter, *Request)  
}
//只要有ServeHTTP方法就行

可以自己實(shí)現(xiàn)這個(gè)接口

同時(shí)http提供了handlerFunc結(jié)構(gòu)體

type HandlerFunc func(ResponseWriter, *Request)
// ServeHTTP calls f(w, r).
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
f(w, r)
}
//本質(zhì)上就是調(diào)用自身,因?yàn)橐彩且粋€(gè)函數(shù),不過serveHTTP的內(nèi)容自己可以定義改動(dòng)

和之前的HandleFunc區(qū)分,HandleFunc是用來給不同路徑綁定方法的,少一個(gè)r

那么只要滿足Handlerfunc 的簽名形式,就可以進(jìn)行類型轉(zhuǎn)換

  • 類型轉(zhuǎn)換的正常的理解例子
type yes func(int, int) int  
func (y yes) add(a, b int) int {  
    return a + b  
}  
func multiply(a, b int) int {  
	fmt.Println(a * b)
    return a * b  
}  
func main() {  
    multiply(1, 2)   //2
    ans := yes(multiply) //將multiply進(jìn)行轉(zhuǎn)換  
    res := ans.add(1, 2)  
    fmt.Println(res)   //3
}

http.HandleFunc("/hello", hello)

這個(gè)后面的簽名只要是 func(ResponseWriter, *Request)就可以了
但是

http.ListenAndServe(":8080", referer)

這個(gè)后面的函數(shù)需要是滿足Handler接口,有serveHTTP方法

嘗試搭建檢測(cè)是在query中有name = red
即http://localhost:8080/hello?name=red
發(fā)現(xiàn)會(huì)有重復(fù)覆蓋路由的問題,因?yàn)閘istenandServe會(huì)攔截所有的路由,后面再解決

type CheckQueryName struct {
	wantname string
	handler  http.Handler
}

func (this *CheckQueryName) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	queryParams := r.URL.Query() //獲取get請(qǐng)求的query
	name := queryParams.Get("name")
	if name == "red" {
		this.handler.ServeHTTP(w, r) //其實(shí)就是調(diào)用本身,下面變?yōu)閏heckforname了
	} else {
		w.Write([]byte("not this name"))
	}
}

func checkforname(w http.ResponseWriter, r *http.Request) {
	w.Write([]byte("check is ok"))
}

func hello(w http.ResponseWriter, r *http.Request) {
	w.Write([]byte("hello"))
}

func main() {
	thecheck := &CheckQueryName{ //用&因?yàn)閟erveHTTP方法定義在指針接收器上
		wantname: "red",
		handler:  http.HandlerFunc(checkforname),
	}
	http.HandleFunc("/hello", hello)       //滿足func(ResponseWriter, *Request)簽名就可以
	http.ListenAndServe(":8080", thecheck) //直接監(jiān)視8080的所有端口,攔截所有路由
}

編寫簡(jiǎn)單的GET請(qǐng)求客戶端

利用defaultclient或者自己定義client都可以

func main() {
	resp, err := http.DefaultClient.Get("https://api.github.com")
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		panic(err)
	}
	fmt.Println(string(body))
	time.Sleep(time.Second * 2)  //等待獲取請(qǐng)求
}

但是如果把網(wǎng)址換成baidu.com就會(huì)獲取不到,這是因?yàn)檗D(zhuǎn)發(fā),以及沒有User-agent的問題

編寫自定義的GET請(qǐng)求客戶端

利用http.Client可以進(jìn)行自定義

func main() {
	client := &http.Client{
		// 允許重定向
		CheckRedirect: func(req *http.Request, via []*http.Request) error {
			return nil
		},
	}

	req, err := http.NewRequest("GET", "https://www.baidu.com", nil)
	if err != nil {
		panic(err)
	}
	// 添加請(qǐng)求頭
	req.Header.Set("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36")

	resp, err := client.Do(req) 
	//do執(zhí)行HTTP請(qǐng)求的整個(gè)周期包括請(qǐng)求準(zhǔn)備,建立連接,發(fā)送請(qǐng)求,請(qǐng)求重定向,接收響應(yīng)等等
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		panic(err)
	}
	fmt.Println(string(body))
	time.Sleep(time.Second * 2)
}

發(fā)現(xiàn)可以接受到baidu的網(wǎng)頁html信息

編寫默認(rèn)的post請(qǐng)求客戶端

func main() {
	postData := strings.NewReader(`{"name": "張三", "age": 25}`)
	resp, err := http.DefaultClient.Post(
		"http://localhost:8080/users",
		"application/json",  
		postData,
	)
	if err != nil {
		fmt.Printf("POST請(qǐng)求失敗: %v\n", err)
		return
	}
	defer resp.Body.Close()

	body, _ := ioutil.ReadAll(resp.Body)
	fmt.Printf("POST響應(yīng): %s\n", string(body))
}

string.NewReader是一種方法將格式改為io reader可以讀取的形式,接收的話也可以postData.Read讀取。
這一類的方式比較多,不一一匯總

對(duì)應(yīng)的server.go (需要在終端中g(shù)o run server.go )兩個(gè)終端分別運(yùn)行服務(wù)端,客戶端

func main() {
	// 處理 /users 路徑的 POST 請(qǐng)求
	http.HandleFunc("/users", func(w http.ResponseWriter, r *http.Request) {
		// 只允許 POST 方法
		if r.Method != http.MethodPost {
			w.WriteHeader(http.StatusMethodNotAllowed)
			fmt.Fprintf(w, "只支持 POST 方法")
			return
		}
		// 讀取請(qǐng)求體
		body, err := ioutil.ReadAll(r.Body)
		if err != nil {
			w.WriteHeader(http.StatusBadRequest)
			fmt.Fprintf(w, "讀取請(qǐng)求失敗: %v", err)
			return
		}
		defer r.Body.Close()
		// 解析 JSON 數(shù)據(jù),放入user中
		var user User
		if err := json.Unmarshal(body, &user); err != nil {
			w.WriteHeader(http.StatusBadRequest) //寫入狀態(tài)碼
			fmt.Fprintf(w, "JSON 解析失敗: %v", err)
			return
		}
		// 設(shè)置響應(yīng)頭
		w.Header().Set("Content-Type", "application/json")
		// 構(gòu)造響應(yīng)數(shù)據(jù)
		response := map[string]interface{}{
			"message": "success",
			"data": map[string]interface{}{
				"name": user.Name,
				"age":  user.Age,
			},
		}

		// 返回 JSON 響應(yīng)
		json.NewEncoder(w).Encode(response) //將 response 對(duì)象轉(zhuǎn)換為 JSON 格式并寫入響應(yīng)
		//等價(jià)于:
		// jsonData, err := json.Marshal(response)
		// if err != nil {
		// 	w.WriteHeader(http.StatusInternalServerError)
		// 	return
		// }
		// w.Write(jsonData)
	})

	// 啟動(dòng)服務(wù)器
	fmt.Println("服務(wù)器啟動(dòng)在 :8080 端口...")
	if err := http.ListenAndServe(":8080", nil); err != nil {
		panic(err)
	}
}

多路復(fù)用器

DefaultServeMux一般不會(huì)使用,因?yàn)闀?huì)有沖突等等問題,所以一般用NewServeMux直接創(chuàng)建

type apiHandler struct{}

func (apiHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")
	fmt.Fprintf(w, `{"message": "API response"}`)
}

func main() {
	mux := http.NewServeMux()
	mux.Handle("/api/", apiHandler{})  //多引入結(jié)構(gòu)體,后面會(huì)知道有好處
	// mux.HandleFunc("/api/", func(w http.ResponseWriter, req *http.Request) {
    //     w.Header().Set("Content-Type", "application/json")
    //     fmt.Fprintf(w, `{"message": "API response from HandleFunc"}`)
    // })   //和上面等效
	mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
		if req.URL.Path != "/" {
			http.NotFound(w, req)
			return
		}
		fmt.Fprintf(w, "Welcome to the home page!")
	})

	fmt.Println("Server running on :8080")
	http.ListenAndServe(":8080", mux)
	//用server:= &http.Server創(chuàng)建地址和handler,然后server.ListenAndServe也是一種表現(xiàn)方式
	
}

mux和http.HandleFunc()的區(qū)別:
mux 可以創(chuàng)建多個(gè)路由器實(shí)例,用于不同的目的。同時(shí)可以為不同的路由器配置不同的中間件(用著先)

第三方有庫httprouter,比如可以解決url不能是變量代表的問題,了解就行
更多都是使用restful API進(jìn)行開發(fā)的~目前的了解有個(gè)概念就行

處理器函數(shù)

Handle

注冊(cè)處理器過程中調(diào)用的函數(shù):Handle

type username struct {
	name string
}

func (this *username) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "%s", this.name)
}

func main() {
	mux := http.NewServeMux()
	mux.Handle("/jack", &username{name: "jack"}) //會(huì)調(diào)用對(duì)應(yīng)的serveHTTP方法
	mux.Handle("/lily", &username{name: "lily"})
	//可以為不同的路徑使用相同的處理器結(jié)構(gòu)體,但傳入不同的參數(shù)
	//這就是比用handleFunc()更靈活的地方
	server := &http.Server{
		Addr:    ":8080",
		Handler: mux,
	}
	if err := server.ListenAndServe(); err != nil { //防止錯(cuò)誤
		panic(err)
	}
}

HandlleFunc

處理器函數(shù):HandleFunc
(注意不是HandlerFunc,沒有r !! HandleFunc 是處理器函數(shù))
之前已經(jīng)學(xué)習(xí)過,定義就是
func HandleFunc(pattern string, handler func(ResponseWriter, *Request))

深入源代碼會(huì)發(fā)現(xiàn)內(nèi)部也是借助serveMux對(duì)象,從而實(shí)現(xiàn)了Handler的ServeHTTP()方法的

Handler

Handler就是處理器接口,實(shí)現(xiàn)ServeHTTP方法的,之前展示過

type Handler interface {
	ServeHTTP(ResponseWriter, *Request)
}

HandlerFunc

HandlerFunc是結(jié)構(gòu)體,用于實(shí)現(xiàn)接口的
定義:

type HandlerFunc func(ResponseWriter, *Request)

用于連接處理器Handle和處理器函數(shù)HandleFunc,它實(shí)現(xiàn)了 Handler 接口,使得函數(shù)可以直接當(dāng)作處理器使用:

  • 理解“連接連接處理器Handle和處理器函數(shù)HandleFunc”:(之前也學(xué)過)
// 方式一:普通函數(shù)
func hello(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hello!")
}
// 注冊(cè)方式一:將函數(shù)轉(zhuǎn)換為 HandlerFunc
http.Handle("/hello", http.HandlerFunc(hello))

// 方式二:直接使用 HandleFunc
http.HandleFunc("/hello", hello)

處理請(qǐng)求

請(qǐng)求分為:請(qǐng)求頭,請(qǐng)求URL,請(qǐng)求體等

html表單的enctype屬性

在postman的body部分可以查看

  • application/x-www-form-urlencode
    url方式編碼,較為通用,get和post都可以用
  • multipart/form-data
    通常適配post方法提交
  • text/plain
    適合傳遞大量數(shù)據(jù)

ResponseWriter接口涉及方法

  • 補(bǔ)充:
    fmt.Fprint和fmt.Fprintln能夠?qū)懭隦esponseWriter是因?yàn)镽esponseWriter實(shí)現(xiàn)了io.Writer接口,fmt.Fprint/Fprintln將數(shù)據(jù)按格式轉(zhuǎn)換為字節(jié)流(如字符串、數(shù)字等),最終調(diào)用io.Writer的Write方法

Writeheader

curl -i localhost:8080/noAuth 或者使用postman進(jìn)行驗(yàn)證

func noAuth(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(401)
	fmt.Fprint(w, "沒有授權(quán),你需要認(rèn)證后訪問")
}

func main() {
	http.HandleFunc("/noAuth", noAuth)
	err := http.ListenAndServe(":8080", nil)
	if err != nil {
		fmt.Println(err)
	}
}

Header

調(diào)用了Writeheader后的話就不能對(duì)響應(yīng)頭進(jìn)行修改了
curl -i http://localhost:8081/redirect (可以直接看到301)或者postman驗(yàn)證

  • 重定向代碼
func Redirect(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Location", "http://localhost:8080/hello")
	// 必須使用包括http的完整的URL!
	w.WriteHeader(301)
}
func main() {
	http.HandleFunc("/redirect", Redirect)
	if err := http.ListenAndServe(":8081", nil); err != nil {
		panic(err)
	}
}
  • 主服務(wù)代碼
func sayHello(w http.ResponseWriter, r *http.Request) {
	w.Write([]byte("hello !!"))
}

func main() {
	http.HandleFunc("/hello", sayHello)
	http.ListenAndServe(":8080", nil) //創(chuàng)建基本服務(wù)
}

write

之前都有demo,就是寫入返回,注意需要是[]byte()這樣的表示形式
如果不知道content-type格式可以通過數(shù)據(jù)的前512 比特進(jìn)行確認(rèn)

除了一般的文本字符串之外,還可以返回html和json,下面給出json的示范

type language struct {
	Language string `json:"language"` //反引號(hào)
	 // 字段名首字母需要大寫才能被 JSON 序列化?。。?!
}

func uselanguage(w http.ResponseWriter, r *http.Request) {
	uselanguageis := language{Language: "en"}
	message, err := json.Marshal(uselanguageis)
	if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
	w.Header().Set("Content-Type", "application/json") //通過json形式傳遞
	w.Write(message)
}

func main() {
	http.HandleFunc("/lan", uselanguage)
	if err := http.ListenAndServe(":8080", nil); err != nil {
		panic(err)
	}
}

注意一些格式上的細(xì)節(jié),比如字段名首字母需要大寫才能被 JSON 序列化

到此這篇關(guān)于快速上手GO的net/http包的文章就介紹到這了,更多相關(guān)GO net/http包內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Go語言實(shí)現(xiàn)猜數(shù)字小游戲

    Go語言實(shí)現(xiàn)猜數(shù)字小游戲

    這篇文章主要為大家詳細(xì)介紹了Go語言實(shí)現(xiàn)猜數(shù)字小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-10-10
  • Go+Vue開發(fā)一個(gè)線上外賣應(yīng)用的流程(用戶名密碼和圖形驗(yàn)證碼)

    Go+Vue開發(fā)一個(gè)線上外賣應(yīng)用的流程(用戶名密碼和圖形驗(yàn)證碼)

    這篇文章主要介紹了Go+Vue開發(fā)一個(gè)線上外賣應(yīng)用(用戶名密碼和圖形驗(yàn)證碼),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-11-11
  • 一文帶你掌握Go語言并發(fā)模式中的Context的上下文管理

    一文帶你掌握Go語言并發(fā)模式中的Context的上下文管理

    在?Go?的日常開發(fā)中,Context?上下文對(duì)象無處不在,無論是處理網(wǎng)絡(luò)請(qǐng)求、數(shù)據(jù)庫操作還是調(diào)用?RPC?等場(chǎng)景,那你真的熟悉它的正確用法嗎,隨著本文一探究竟吧
    2023-05-05
  • goland安裝1.7版本報(bào)錯(cuò)Unpacked?SDK?is?corrupted解決

    goland安裝1.7版本報(bào)錯(cuò)Unpacked?SDK?is?corrupted解決

    這篇文章主要為大家介紹了goland安裝1.7版本報(bào)錯(cuò)Unpacked?SDK?is?corrupted解決,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-11-11
  • Go語言庫系列之flag的具體使用

    Go語言庫系列之flag的具體使用

    這篇文章主要介紹了Go語言庫系列之flag的具體使用,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-04-04
  • Go語言時(shí)間相關(guān)操作合集(超詳細(xì))

    Go語言時(shí)間相關(guān)操作合集(超詳細(xì))

    在開發(fā)應(yīng)用程序的過程中,經(jīng)常需要記錄某些操作的時(shí)間或者格式化時(shí)間戳,因此大部分編程語言都會(huì)有操作時(shí)間的庫,Go語言當(dāng)然也不例外,本文我們就一起來學(xué)習(xí)一下time包的使用
    2023-08-08
  • Go語言共享內(nèi)存讀寫實(shí)例分析

    Go語言共享內(nèi)存讀寫實(shí)例分析

    這篇文章主要介紹了Go語言共享內(nèi)存讀寫方法,實(shí)例分析了共享內(nèi)存的原理與讀寫技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-02-02
  • 詳解Go語言如何解析帶注釋的json

    詳解Go語言如何解析帶注釋的json

    標(biāo)準(zhǔn)的json格式是不帶注釋,但是有時(shí)候?yàn)榱朔奖憷斫鈐son中各字段的含義,需要支持帶注釋的json,這篇文章主要介紹了Go語言解析帶注釋json的相關(guān)方法,希望對(duì)大家有所幫助
    2024-03-03
  • 使用Go語言實(shí)現(xiàn)遠(yuǎn)程傳輸文件

    使用Go語言實(shí)現(xiàn)遠(yuǎn)程傳輸文件

    本文主要介紹如何利用Go語言實(shí)現(xiàn)遠(yuǎn)程傳輸文件的功能,有需要的小伙伴們可以參考學(xué)習(xí)。下面跟著小編一起來學(xué)習(xí)學(xué)習(xí)。
    2016-08-08
  • 舉例講解Go語言中函數(shù)的閉包使用

    舉例講解Go語言中函數(shù)的閉包使用

    這篇文章主要介紹了Go語言中函數(shù)的閉包使用示例,函數(shù)閉包c(diǎn)losure是編程語言中十分重要的特性,需要的朋友可以參考下
    2016-03-03

最新評(píng)論