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

快速上手GO的net/http包

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

針對GO中net/http包的學習筆記

基礎快速了解

創(chuàng)建簡單的GOHTTP服務

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

訪問8080/hello進行測試

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

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

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

同時http提供了handlerFunc結構體

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 的簽名形式,就可以進行類型轉換

  • 類型轉換的正常的理解例子
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進行轉換  
    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)會有重復覆蓋路由的問題,因為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就會獲取不到,這是因為轉發(fā),以及沒有User-agent的問題

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

利用http.Client可以進行自定義

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請求的整個周期包括請求準備,建立連接,發(fā)送請求,請求重定向,接收響應等等
	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信息

編寫默認的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響應: %s\n", string(body))
}

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

對應的server.go (需要在終端中go run server.go )兩個終端分別運行服務端,客戶端

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
		}
		// 設置響應頭
		w.Header().Set("Content-Type", "application/json")
		// 構造響應數(shù)據(jù)
		response := map[string]interface{}{
			"message": "success",
			"data": map[string]interface{}{
				"name": user.Name,
				"age":  user.Age,
			},
		}

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

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

多路復用器

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{})  //多引入結構體,后面會知道有好處
	// 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進行開發(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)用對應的serveHTTP方法
	mux.Handle("/lily", &username{name: "lily"})
	//可以為不同的路徑使用相同的處理器結構體,但傳入不同的參數(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)學習過,定義就是
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是結構體,用于實現(xiàn)接口的
定義:

type HandlerFunc func(ResponseWriter, *Request)

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

  • 理解“連接連接處理器Handle和處理器函數(shù)HandleFunc”:(之前也學過)
// 方式一:普通函數(shù)
func hello(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hello!")
}
// 注冊方式一:將函數(shù)轉換為 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接口涉及方法

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

Writeheader

curl -i localhost:8080/noAuth 或者使用postman進行驗證

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

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

Header

調(diào)用了Writeheader后的話就不能對響應頭進行修改了
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)
	}
}
  • 主服務代碼
func sayHello(w http.ResponseWriter, r *http.Request) {
	w.Write([]byte("hello !!"))
}

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

write

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

除了一般的文本字符串之外,還可以返回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)
	}
}

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

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

相關文章

  • golang基于errgroup實現(xiàn)并發(fā)調(diào)用的方法

    golang基于errgroup實現(xiàn)并發(fā)調(diào)用的方法

    這篇文章主要介紹了golang基于errgroup實現(xiàn)并發(fā)調(diào)用,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-09-09
  • 通過Golang實現(xiàn)無頭瀏覽器截圖

    通過Golang實現(xiàn)無頭瀏覽器截圖

    在Web開發(fā)中,有時需要對網(wǎng)頁進行截圖,以便進行頁面預覽、測試等操作,本文為大家整理了Golang實現(xiàn)無頭瀏覽器的截圖的方法,感興趣的可以了解一下
    2023-05-05
  • Golang拾遺之實現(xiàn)一個不可復制類型詳解

    Golang拾遺之實現(xiàn)一個不可復制類型詳解

    在這篇文章中我們將實現(xiàn)一個無法被復制的類型,順便加深對引用類型、值傳遞以及指針的理解。文中的示例代碼講解詳細,感興趣的可以了解一下
    2023-02-02
  • Go語言時間管理利器之深入解析time模塊的實戰(zhàn)技巧

    Go語言時間管理利器之深入解析time模塊的實戰(zhàn)技巧

    本文深入解析了Go語言標準庫中的time模塊,揭示了其高效用法和實用技巧,通過學習time模塊的三大核心類型(Time、Duration、Timer/Ticker)以及高頻使用場景,開發(fā)者可以更好地處理時間相關的任務,感興趣的朋友一起看看吧
    2025-03-03
  • Go語言實現(xiàn)互斥鎖、隨機數(shù)、time、List

    Go語言實現(xiàn)互斥鎖、隨機數(shù)、time、List

    這篇文章主要介紹了Go語言實現(xiàn)互斥鎖、隨機數(shù)、time、List的相關資料,需要的朋友可以參考下
    2018-10-10
  • golang常用庫之字段參數(shù)驗證庫-validator使用詳解

    golang常用庫之字段參數(shù)驗證庫-validator使用詳解

    這篇文章主要介紹了golang常用庫:字段參數(shù)驗證庫-validator使用,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借價值,需要的朋友可以參考下
    2020-10-10
  • golang?struct?json?tag的使用以及深入講解

    golang?struct?json?tag的使用以及深入講解

    這篇文章主要給大家介紹了關于golang?struct?json?tag的使用以及深入講解,文中通過實例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2022-02-02
  • golang連接kafka的示例代碼

    golang連接kafka的示例代碼

    本文主要介紹了golang連接kafka的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-04-04
  • golang中單機鎖的具體實現(xiàn)詳解

    golang中單機鎖的具體實現(xiàn)詳解

    這篇文章主要為大家詳細介紹了golang中單機鎖的具體實現(xiàn)的相關知識,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習一下
    2025-03-03
  • Golang排序和查找使用方法介紹

    Golang排序和查找使用方法介紹

    排序操作和查找一樣是很多程序經(jīng)常使用的操作。盡管一個最短的快排程序只要15行就可以搞定,但是一個健壯的實現(xiàn)需要更多的代碼,并且我們不希望每次我們需要的時候都重寫或者拷貝這些代碼
    2022-12-12

最新評論