最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

快速上手GO的net/http包

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

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

基礎(chǔ)快速了解

創(chuàng)建簡單的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)行測試

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

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

可以自己實現(xiàn)這個接口

同時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)用自身,因為也是一個函數(shù),不過serveHTTP的內(nèi)容自己可以定義改動

和之前的HandleFunc區(qū)分,HandleFunc是用來給不同路徑綁定方法的,少一個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)

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

http.ListenAndServe(":8080", referer)

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

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

type CheckQueryName struct {
	wantname string
	handler  http.Handler
}

func (this *CheckQueryName) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	queryParams := r.URL.Query() //獲取get請求的query
	name := queryParams.Get("name")
	if name == "red" {
		this.handler.ServeHTTP(w, r) //其實就是調(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{ //用&因為serveHTTP方法定義在指針接收器上
		wantname: "red",
		handler:  http.HandlerFunc(checkforname),
	}
	http.HandleFunc("/hello", hello)       //滿足func(ResponseWriter, *Request)簽名就可以
	http.ListenAndServe(":8080", thecheck) //直接監(jiān)視8080的所有端口,攔截所有路由
}

編寫簡單的GET請求客戶端

利用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)  //等待獲取請求
}

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

編寫自定義的GET請求客戶端

利用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)
	}
	// 添加請求頭
	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請求的整個周期包括請求準(zhǔn)備,建立連接,發(fā)送請求,請求重定向,接收響應(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請求客戶端

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請求失敗: %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讀取。
這一類的方式比較多,不一一匯總

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

func main() {
	// 處理 /users 路徑的 POST 請求
	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
		}
		// 讀取請求體
		body, err := ioutil.ReadAll(r.Body)
		if err != nil {
			w.WriteHeader(http.StatusBadRequest)
			fmt.Fprintf(w, "讀取請求失敗: %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 對象轉(zhuǎn)換為 JSON 格式并寫入響應(yīng)
		//等價于:
		// jsonData, err := json.Marshal(response)
		// if err != nil {
		// 	w.WriteHeader(http.StatusInternalServerError)
		// 	return
		// }
		// w.Write(jsonData)
	})

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

多路復(fù)用器

DefaultServeMux一般不會使用,因為會有沖突等等問題,所以一般用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)體,后面會知道有好處
	// 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)建多個路由器實例,用于不同的目的。同時可以為不同的路由器配置不同的中間件(用著先)

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

處理器函數(shù)

Handle

注冊處理器過程中調(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"}) //會調(diào)用對應(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 { //防止錯誤
		panic(err)
	}
}

HandlleFunc

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

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

Handler

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

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

HandlerFunc

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

type HandlerFunc func(ResponseWriter, *Request)

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

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

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

處理請求

請求分為:請求頭,請求URL,請求體等

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是因為ResponseWriter實現(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)行驗證

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后的話就不能對響應(yīng)頭進(jìn)行修改了
curl -i http://localhost:8081/redirect (可以直接看到301)或者postman驗證

  • 重定向代碼
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"` //反引號
	 // 字段名首字母需要大寫才能被 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)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 詳解Go語言中空結(jié)構(gòu)體的慣用法

    詳解Go語言中空結(jié)構(gòu)體的慣用法

    空結(jié)構(gòu)體在 Go 編程中有著廣泛的應(yīng)用,本文將詳細(xì)探討空結(jié)構(gòu)體的幾種典型用法,并解釋為何它們在特定場景下非常有用,希望對大家有所幫助
    2024-11-11
  • 解決Goland 提示 Unresolved reference 錯誤的問題

    解決Goland 提示 Unresolved reference 錯誤的問題

    這篇文章主要介紹了解決Goland 提示 Unresolved reference 錯誤的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • Golang中使用Mqtt的方法示例

    Golang中使用Mqtt的方法示例

    本文介紹了Golang中使用paho.mqtt.golang庫實現(xiàn)MQTT客戶端與服務(wù)器的連接、訂閱和消息收發(fā),具有一定的參考價值,感興趣的可以了解一下
    2025-02-02
  • Go標(biāo)準(zhǔn)庫之Requests的介紹與基本使用

    Go標(biāo)準(zhǔn)庫之Requests的介紹與基本使用

    Python中的Requests庫非常強(qiáng)大,所以Go開發(fā)者模仿Python的Requests庫,由此誕生了Grequests庫,本文主要介紹了Requests的基本使用,有需要的可以參考下
    2024-04-04
  • 一文詳解Golang中net/http包的實現(xiàn)原理

    一文詳解Golang中net/http包的實現(xiàn)原理

    這篇文章主要介紹了如何用?net/http?自己編寫實現(xiàn)一個?HTTP?Server?并探究其實現(xiàn)原理,具體講解Go語言是如何接收和處理請求的,希望能夠?qū)Υ蠹业膶W(xué)習(xí)或工作具有一定的幫助
    2022-08-08
  • golang項目如何上線部署到Linu服務(wù)器(方法詳解)

    golang項目如何上線部署到Linu服務(wù)器(方法詳解)

    這篇文章主要介紹了golang項目如何上線部署到Linu服務(wù)器,本文通過兩種方法給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-10-10
  • 詳解Golang如何使用Debug庫優(yōu)化代碼

    詳解Golang如何使用Debug庫優(yōu)化代碼

    這篇文章將針對Golang的debug庫進(jìn)行全面解讀,涵蓋其核心組件、高級功能和實戰(zhàn)技巧,文中的示例代碼講解詳細(xì),有需要的小伙伴可以參考下
    2024-02-02
  • go語言規(guī)范RESTful?API業(yè)務(wù)錯誤處理

    go語言規(guī)范RESTful?API業(yè)務(wù)錯誤處理

    這篇文章主要為大家介紹了go語言規(guī)范RESTful?API業(yè)務(wù)錯誤處理方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-03-03
  • Go中獲取兩個切片交集的六種實現(xiàn)方式

    Go中獲取兩個切片交集的六種實現(xiàn)方式

    在Go開發(fā)中,切片交集(Intersection) 是高頻需求:用戶標(biāo)簽匹配、權(quán)限校驗、數(shù)據(jù)去重同步,本文系統(tǒng)梳理從基礎(chǔ)到高階的 6 種實現(xiàn)方式,含泛型、結(jié)構(gòu)體、去重、性能對比,助你寫出工業(yè)級健壯代碼,需要的朋友可以參考下
    2025-12-12
  • Go語言實戰(zhàn)之實現(xiàn)均衡器功能

    Go語言實戰(zhàn)之實現(xiàn)均衡器功能

    這篇文章主要為大家詳細(xì)介紹了如何利用Golang?實現(xiàn)一個簡單的流浪均衡器,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-04-04

最新評論

松潘县| 常熟市| 渭源县| 台中县| 大港区| 巴青县| 来安县| 宜宾县| 红原县| 鄯善县| 介休市| 天气| 淄博市| 深州市| 绥宁县| 固原市| 汾西县| 安阳县| 晴隆县| 东城区| 镇赉县| 白朗县| 九龙城区| 珲春市| 临湘市| 南川市| 元谋县| 陕西省| 华宁县| 碌曲县| 融水| 财经| 高陵县| 象州县| 信丰县| 名山县| 金沙县| 岳普湖县| 卓尼县| 武功县| 临沂市|