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

Go高效率開發(fā)Web參數(shù)校驗三種方式實例

 更新時間:2022年11月26日 16:42:08   作者:巫師韓  
這篇文章主要介紹了Go高效率開發(fā)Web參數(shù)校驗三種方式實例,需要的朋友可以參考下

web開發(fā)中,你肯定見到過各種各樣的表單或接口數(shù)據(jù)校驗:

  • 客戶端參數(shù)校驗:在數(shù)據(jù)提交到服務(wù)器之前,發(fā)生在瀏覽器端或者app應(yīng)用端,相比服務(wù)器端校驗,用戶體驗更好,能實時反饋用戶的輸入校驗結(jié)果。

  • 服務(wù)器端參數(shù)校驗:發(fā)生在客戶端提交數(shù)據(jù)并被服務(wù)器端程序接收之后,通常服務(wù)器端校驗都是發(fā)生在將數(shù)據(jù)寫入數(shù)據(jù)庫之前,如果數(shù)據(jù)沒通過校驗,則會直接從服務(wù)器端返回錯誤消息,并且告訴客戶端發(fā)生錯誤的具體位置和原因,服務(wù)器端校驗不像客戶端校驗?zāi)菢佑泻玫挠脩趔w驗,因為它直到整個表單都提交后才能返回錯誤信息。但是服務(wù)器端校驗是應(yīng)用對抗錯誤,惡意數(shù)據(jù)的最后防線,在這之后,數(shù)據(jù)將被持久化至數(shù)據(jù)庫。當(dāng)今所有的服務(wù)端框架都提供了數(shù)據(jù)校驗與過濾功能(讓數(shù)據(jù)更安全)。

本文主要討論服務(wù)器端參數(shù)校驗

確保用戶以正確格式輸入數(shù)據(jù),提交的數(shù)據(jù)能使后端應(yīng)用程序正常工作,同時在一切用戶的輸入都是不可信的前提下(比如xss跨域腳本攻擊,sql注入),參數(shù)驗證是不可或缺的一環(huán),也是很繁瑣效率不高的一環(huán),在對接表單提交或者api接口數(shù)據(jù)提交,程序里充斥著大量重復(fù)驗證邏輯和if else語句,本文分析參數(shù)校驗的三種方式,找出最優(yōu)解,從而提高參數(shù)驗證程序代碼的開發(fā)效率。

學(xué)習(xí)方式自下而上:提出問題 -> 分析問題 -> 解決問題 -> 總結(jié)

需求場景:

常見的網(wǎng)站登陸場景

業(yè)務(wù)需求

接口一:
場景:輸入手機(jī)號,獲取短信驗證碼
校驗需求:判斷手機(jī)號非空,手機(jī)號格式是否正確
接口二:
場景:手機(jī)收到短信驗證碼,輸入驗證碼,點擊登陸
校驗需求:1、判斷手機(jī)號非空,手機(jī)號格式是否正確;2、驗證碼非空,驗證碼格式是否正確

技術(shù)選型:web框架gin

第一種實現(xiàn)方式:自定義實現(xiàn)校驗邏輯

package main

func main() {
   engine := gin.New()

    engine := gin.New()

    ctrUser := controller.NewUser()
    engine.POST("/user/login", ctrUser.Login)

    ctrCaptcha := controller.NewCaptcha()
    engine.POST("/captcha/send", ctrCaptcha.Send)

    engine.Run()
}

--------------------------------------------------------------------------------
package controller

type Captcha struct {}

func (ctr *Captcha) Send(c *gin.Context) {
   mobile := c.PostForm("mobile")

   // 校驗手機(jī)號邏輯
   if mobile == "" {
      c.JSON(http.StatusBadRequest, gin.H{"error": "手機(jī)號不能為空"})
      return
   }

   matched, _ := regexp.MatchString(`^(1[3-9][0-9]\d{8})$`, mobile)
   if !matched {
      c.JSON(http.StatusBadRequest, gin.H{"error": "手機(jī)號格式不正確"})
      return
   }

    c.JSON(http.StatusBadRequest, gin.H{"mobile": mobile})
}

type User struct {}

func (ctr *User) Login(c *gin.Context) {
   mobile := c.PostForm("mobile")
   code := c.PostForm("code")

   // 校驗手機(jī)號邏輯
   if mobile == "" {
      c.JSON(http.StatusBadRequest, gin.H{"error": "手機(jī)號不能為空"})
      return
   }

   matched, _ := regexp.MatchString(`^(1[3-9][0-9]\d{8})$`, mobile)
   if !matched {
      c.JSON(http.StatusBadRequest, gin.H{"error": "手機(jī)號格式不正確"})
      return
   }

   // 校驗手機(jī)號邏輯
   if code == "" {
      c.JSON(http.StatusBadRequest, gin.H{"error": "驗證碼不能為空"})
      return
   }

   if len(code) != 4 {
      c.JSON(http.StatusBadRequest, gin.H{"error": "驗證碼為4位"})
      return
   }

   c.JSON(http.StatusBadRequest, gin.H{"mobile": mobile, "code": code})
}

源碼鏈接

代碼分析:
參數(shù)驗證函數(shù)放在Controller層;
這是一種比較初級也是最樸素的實現(xiàn)方式,在現(xiàn)實代碼review中經(jīng)常遇到,這樣實現(xiàn)會有什么問題?
1、手機(jī)號碼驗證邏輯重復(fù);
2、違背了controller層的職責(zé),controller層充斥著大量的驗證函數(shù)(Controller層職責(zé):從HTTP請求中獲得信息,提取參數(shù),并分發(fā)給不同的處理服務(wù));

重復(fù)代碼是軟件質(zhì)量下降的重大來源?。?!

1、重復(fù)代碼會造成維護(hù)成本的成倍增加;
2、需求的變動導(dǎo)致需要修改重復(fù)代碼,如果遺漏某處重復(fù)的邏輯,就會產(chǎn)生bug(例如手機(jī)號碼增加12開頭的驗證規(guī)則);
3、重復(fù)代碼會導(dǎo)致項目代碼體積變得臃腫;

聰明的開發(fā)者肯定第一時間想到一個解決辦法:提取出驗證邏輯,工具包util實現(xiàn)IsMobile函數(shù)

package util

func IsMobile(mobile string) bool {
   matched, _ := regexp.MatchString(`^(1[3-9][0-9]\d{8})$`, mobile)
   return matched
}

代碼分析:
問題:代碼會大量出現(xiàn)util.IsMobile、util.IsEmail等校驗代碼

思考:從面向?qū)ο蟮乃枷氤霭l(fā),IsMobile屬于util的動作或行為嗎?

第二種實現(xiàn)方式:模型綁定校驗

技術(shù)選型:web框架gin自帶的模型驗證器中文提示不是很好用,這里使用govalidator 模型綁定校驗是目前參數(shù)校驗最主流的驗證方式,每個編程語言的web框架基本都支持這種模式,模型綁定時將Http請求中的數(shù)據(jù)映射到模型對應(yīng)的參數(shù),參數(shù)可以是簡單類型,如整形,字符串等,也可以是復(fù)雜類型,如Json,Json數(shù)組,對各種數(shù)據(jù)類型進(jìn)行驗證,然后拋出相應(yīng)的錯誤信息。

源碼鏈接

package request

func init() {
   validator.TagMap["IsMobile"] = func(value string) bool {
      return IsMobile(value)
   }
}

func IsMobile(value string) bool {
    matched, _ := regexp.MatchString(`^(1[1-9][0-9]\d{8})$`, value)
    return matched
}

type Captcha struct {
   Mobile string `form:"mobile" valid:"required~手機(jī)號不能為空,numeric~手機(jī)號碼應(yīng)該為數(shù)字型,IsMobile~手機(jī)號碼格式錯誤"`
}

type User struct {
   Mobile string `form:"mobile" valid:"required~手機(jī)號不能為空,numeric~手機(jī)號碼應(yīng)該為數(shù)字型,IsMobile~手機(jī)號碼格式錯誤"`
   Code string `form:"code" valid:"required~驗證碼不能為空,numeric~驗證碼應(yīng)該為數(shù)字型"`
}
-------------------------------------------------------------------------------
package controller

type Captcha struct {}

func (ctr *Captcha) Send(c *gin.Context) {
   request := new(request.Captcha)
   if err := c.ShouldBind(request); err != nil {
      c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
      return
   }

   if _, err := validator.ValidateStruct(request); err != nil {
      c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
      return
   }

   c.JSON(http.StatusBadRequest, gin.H{"data": request})
}

type User struct {}

func (ctr *User) Login(c *gin.Context) {
   request := new(request.User)
   if err := c.ShouldBind(request); err != nil {
      c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
      return
   }

   if _, err := validator.ValidateStruct(request); err != nil {
      c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
      return
   }

   c.JSON(http.StatusBadRequest, gin.H{"data": request})
}

代碼分析:
1、mobile校驗邏輯同樣重復(fù)(注釋實現(xiàn)校驗的邏輯重復(fù),如錯誤提示"手機(jī)號不能為空"修改為"請?zhí)顚懯謾C(jī)號",需要修改兩個地方)
2、validator.ValidateStruct函數(shù)會驗證結(jié)構(gòu)體所有屬性

對于2問題不太好理解,舉例解釋
業(yè)務(wù)場景:用戶注冊功能,需要校驗手機(jī)號、短信驗證碼、密碼、昵稱、生日
type User struct {
   Mobile string `form:"mobile" valid:"required~手機(jī)號不能為空,numeric~手機(jī)號碼應(yīng)該為數(shù)字型,IsMobile~手機(jī)號碼格式錯誤"`
   Code string `form:"code" valid:"required~驗證碼不能為空,numeric~驗證碼應(yīng)該為數(shù)字型"`
   Password string `form:"password" valid:"required~密碼不能為空,stringlength(6|18)~密碼6-18個字符"`
   Nickname string `form:"nickname" valid:"required~昵稱不能為空,stringlength(2|10)~昵稱2-10個字符"`
   Birthday time.Time `form:"birthday" valid:"required~生日不能為空" time_format:"2006-01-02"`
}

代碼分析:
登陸功能需要校驗Mobile、Code屬性;
注冊功能需要校驗Mobile、Code、Password、Nickname、Birthday屬性;

如果代碼校驗共用User結(jié)構(gòu)體,就產(chǎn)生了一個矛盾點,有兩種方法可以解決這一問題:

  • 修改validator.ValidateStruct函數(shù),增加校驗白名單或黑名單,實現(xiàn)可以設(shè)置部分屬性校驗或者忽略校驗部分屬性;
// 只做Mobile、Code屬性校驗或者忽略Mobile、Code屬性校驗
validator.ValidateStruct(user, "Mobile", "Code") 

這種也是一種不錯的解決方式,但是在項目實踐中會遇到點小問題:
1、一個校驗結(jié)構(gòu)體有20個屬性,只需要校驗其中10個字段,不管用白名單還是黑名單都需要傳10個字段;
2、手寫字段名容易出錯;
  • 新建不同的結(jié)構(gòu)體,對應(yīng)相應(yīng)的接口綁定校驗
type UserLogin struct {
   Mobile string `form:"mobile" valid:"required~手機(jī)號不能為空,numeric~手機(jī)號碼應(yīng)該為數(shù)字型,IsMobile~手機(jī)號碼格式錯誤"`
   Code string `form:"code" valid:"required~驗證碼不能為空,numeric~驗證碼應(yīng)該為數(shù)字型"`
}

type UserRegister struct {
   Mobile string `form:"mobile" valid:"required~手機(jī)號不能為空,numeric~手機(jī)號碼應(yīng)該為數(shù)字型,IsMobile~手機(jī)號碼格式錯誤"`
   Code string `form:"code" valid:"required~驗證碼不能為空,numeric~驗證碼應(yīng)該為數(shù)字型"`
   Password string `form:"password" valid:"required~密碼不能為空,stringlength(6|18)~密碼6-18個字符"`
   Nickname string `form:"nickname" valid:"required~昵稱不能為空,stringlength(2|10)~昵稱2-10個字符"`
   Birthday time.Time `form:"birthday" valid:"required~生日不能為空" time_format:"2006-01-02"`
}

代碼解析:
用戶登陸接口對應(yīng):UserLogin結(jié)構(gòu)體
用戶注冊接口對應(yīng):UserRegister結(jié)構(gòu)體

同樣問題再次出現(xiàn),Mobile、Code屬性校驗邏輯重復(fù)。

再介紹第三種參數(shù)校驗方式之前,先審視一下剛才的一段代碼:

if err := c.ShouldBind(&request); err != nil {
  c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
  return
}

if _, err := validator.ValidateStruct(request); err != nil {
  c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
  return
}

參數(shù)綁定校驗的地方都需要出現(xiàn)這幾行代碼,我們可以修改gin源碼,把govalidator庫集成在gin中;
如何修改第三方庫源代碼參照項目 源碼鏈接

在gin根目錄增加context_validator.go文件,代碼如下:
package gin

import (
   "github.com/asaskevich/govalidator"
)

type Validator interface {
   Validate() error
}

func (c *Context) ShouldB(data interface{}) error {
   if err := c.ShouldBind(data); err != nil {
      return err
   }

   if _, err := govalidator.ValidateStruct(data); err != nil {
      return err
   }

   var v Validator
   var ok bool
   if v, ok = data.(Validator); !ok {
      return nil
   }

   return v.Validate()
}

controller層的參數(shù)綁定校驗代碼如下:

type User struct {}

func (ctr *User) Register(c *gin.Context) {
   request := new(request.UserRegister)
   if err := c.ShouldB(request); err != nil {
      c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
      return
   }

   c.JSON(http.StatusBadRequest, gin.H{"data": request})
}

代碼分析:
增加了Validator接口,校驗?zāi)P蛯崿F(xiàn)Validator接口,可以完成更為復(fù)雜的多參數(shù)聯(lián)合校驗檢查邏輯,如檢查密碼和重復(fù)密碼是否相等

type UserRegister struct {
   Mobile string `form:"mobile" valid:"required~手機(jī)號不能為空,numeric~手機(jī)號碼應(yīng)該為數(shù)字型,IsMobile~手機(jī)號碼格式錯誤"`
   Code string `form:"code" valid:"required~驗證碼不能為空,numeric~驗證碼應(yīng)該為數(shù)字型"`
   Password string `form:"password" valid:"required~密碼不能為空,stringlength(6|18)~密碼6-18個字符"`
   RePassword string `form:"rePassword" valid:"required~重復(fù)密碼不能為空,stringlength(6|18)~重復(fù)密碼6-18個字符"`
   Nickname string `form:"nickname" valid:"required~昵稱不能為空,stringlength(2|10)~昵稱2-10個字符"`
   Birthday time.Time `form:"birthday" valid:"required~生日不能為空" time_format:"2006-01-02"`
}

func (req *UserRegister) Validate() error {
   if req.Password != req.RePassword {
      return errors.New("兩次密碼不一致")
   }

   return nil
}

模型校驗是通過反射機(jī)制來實現(xiàn),眾所周知反射的效率都不高,現(xiàn)在gin框架集成govalidator,gin原有的校驗功能就顯得多余,小伙伴們可以從ShouldBind函數(shù)從下追,把自帶的校驗功能屏蔽,提高框架效率。

第三種實現(xiàn)方式:拆解模型字段,組合結(jié)構(gòu)體

解決字段校驗邏輯重復(fù)的最終方法就是拆解字段為獨立結(jié)構(gòu)體,通過多個字段結(jié)構(gòu)體的不同組合為所需的校驗結(jié)構(gòu)體,代碼如下:
源碼鏈接

package captcha

type CodeS struct {
   Code string `form:"code" valid:"required~驗證碼不能為空,numeric~驗證碼應(yīng)該為數(shù)字型"`
}


package user

type PasswordS struct {
   Password string `form:"password" valid:"required~密碼不能為空,stringlength(6|18)~密碼6-18個字符"`
}

type RePasswordS struct {
   RePassword string `form:"rePassword" valid:"required~重復(fù)密碼不能為空,stringlength(6|18)~重復(fù)密碼6-18個字符"`
}

type NicknameS struct {
   Nickname string `form:"nickname" valid:"required~昵稱不能為空,stringlength(2|10)~昵稱2-10個字符"`
}

type BirthdayS struct {
   Birthday time.Time `form:"birthday" valid:"required~生日不能為空" time_format:"2006-01-02"`
}

type UserLogin struct {
   MobileS
   captcha.CodeS
}

type UserRegister struct {
   MobileS
   captcha.CodeS
   user.PasswordS
   user.RePasswordS
   user.NicknameS
   user.BirthdayS
}

func (req *UserRegister) Validate() error {
   if req.Password() != req.RePassword() {
      return errors.New("兩次密碼不一致")
   }

   return nil
}

代碼解析:
為什么字段結(jié)構(gòu)體都加了S?
1、結(jié)構(gòu)體包含匿名結(jié)構(gòu)體不能調(diào)用匿名結(jié)構(gòu)體同名屬性,匿名結(jié)構(gòu)體加S標(biāo)識為結(jié)構(gòu)體

示例代碼不能很好的展示項目結(jié)構(gòu),可以查看源代碼

代碼分析:

  • 獨立的字段結(jié)構(gòu)體通常以表名為包名定義范圍,比如商品名稱和分類名稱字段名都為Name,但是所需定義的校驗邏輯(字符長度等)很有可能不同;
  • 每一個接口建立對應(yīng)的驗證結(jié)構(gòu)體:
接口user/login:    對應(yīng)請求結(jié)構(gòu)體UserLogin
接口user/register: 對應(yīng)請求結(jié)構(gòu)體UserRegister
接口captcha/send:  對應(yīng)請求結(jié)構(gòu)體CaptchaSend 
  • 公用的字段結(jié)構(gòu)體例如ID、Mobile建立單獨的文件;

總結(jié):
一、驗證邏輯封裝在各自的實體中,由request層實體負(fù)責(zé)驗證邏輯,驗證邏輯不會散落在項目代碼的各個地方,當(dāng)驗證邏輯改變時,找到對應(yīng)的實體修改就可以了,這就是代碼的高內(nèi)聚;

二、通過不同實體的嵌套組合就可以實現(xiàn)多樣的驗證需求,使得代碼的可重用性大大增強(qiáng),這就是代碼的低耦合

獨立字段結(jié)構(gòu)體組合成不同的校驗結(jié)構(gòu)體,這種方式在實際項目開發(fā)中有很大的靈活性,可以滿足參數(shù)校驗比較多變復(fù)雜的需求場景,小伙伴可以在項目開發(fā)中慢慢體會。

參數(shù)綁定校驗在項目中遇到的幾個問題

源碼鏈接1、需要提交參數(shù)為json或json數(shù)組如何校驗綁定?

type ColumnCreateArticle struct {
   IDS
   article.TitleS
}

type ColumnCreate struct {
   column.TitleS
   Article *ColumnCreateArticle `form:"article"`
   Articles []ColumnCreateArticle `form:"articles"`
}

2、嚴(yán)格遵循一個接口對應(yīng)一個校驗結(jié)構(gòu)體

func (ctr *Column) Detail(c *gin.Context) {
   request := new(request.IDS)
   if err := c.ShouldB(request); err != nil {
      c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
      return
   }

   c.JSON(http.StatusBadRequest, gin.H{"data": request})
}

示例代碼獲取文章專欄詳情的接口,參數(shù)為專欄id,因為只有一個id參數(shù),如果剛開始圖省事,沒有建立對應(yīng)獨立的ColumnDetail校驗結(jié)構(gòu)體,后期接口增加參數(shù)(例如來源等),還是要改動這一塊代碼,增加代碼的不確定性

3、布爾參數(shù)的三種狀態(tài)

type ColumnDetail struct {
   IDS
   // 為真顯示重點文章,為否顯示非重點文章,為nil都顯示
   ArticleIsImportant *bool `form:"articleIsImportant"`
}

column?id=1&articleIsImportant=true    ArticleIsImportant為true
column?id=1&articleIsImportant=false   ArticleIsImportant為false
column?id=1                            ArticleIsIm

 更多關(guān)于GO語言Web參數(shù)校驗方法請查看下面的相關(guān)鏈接

相關(guān)文章

  • go實現(xiàn)圖片拼接與文字書寫的方法實例

    go實現(xiàn)圖片拼接與文字書寫的方法實例

    這篇文章主要給大家介紹了關(guān)于go實現(xiàn)圖片拼接與文字書寫的相關(guān)資料,文中通過實例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2022-01-01
  • 實時通信的服務(wù)器推送機(jī)制 EventSource(SSE) 簡介附go實現(xiàn)示例代碼

    實時通信的服務(wù)器推送機(jī)制 EventSource(SSE) 簡介附go實現(xiàn)示例代碼

    EventSource是一種非常有用的 API,適用于許多實時應(yīng)用場景,它提供了一種簡單而可靠的方式來建立服務(wù)器推送連接,并實現(xiàn)實時更新和通知,這篇文章主要介紹了實時通信的服務(wù)器推送機(jī)制 EventSource(SSE)簡介附go實現(xiàn)示例,需要的朋友可以參考下
    2024-03-03
  • Go語言中map使用和并發(fā)安全詳解

    Go語言中map使用和并發(fā)安全詳解

    golang?自帶的map不是并發(fā)安全的,并發(fā)讀寫會報錯,所以下面這篇文章主要給大家介紹了關(guān)于Go語言中map使用和并發(fā)安全的相關(guān)資料,文中通過實例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-07-07
  • Go并發(fā)編程sync.Cond的具體使用

    Go并發(fā)編程sync.Cond的具體使用

    Go 標(biāo)準(zhǔn)庫提供 Cond 原語的目的是,為等待 / 通知場景下的并發(fā)問題提供支持,本文主要介紹了Go并發(fā)編程sync.Cond的具體使用,具有一定的參考價值,感興趣的可以了解一下
    2022-05-05
  • Go并發(fā)讀寫文件、分片寫、分片下載文件的實現(xiàn)示例

    Go并發(fā)讀寫文件、分片寫、分片下載文件的實現(xiàn)示例

    讀寫文件在很多項目中都可以用到,本文主要介紹了Go并發(fā)讀寫文件、分片寫、分片下載文件的實現(xiàn)示例,具有一定的參考價值,感興趣的可以了解一下
    2024-01-01
  • 詳解Go語言如何實現(xiàn)并發(fā)安全的map

    詳解Go語言如何實現(xiàn)并發(fā)安全的map

    go語言提供的數(shù)據(jù)類型中,只有channel是并發(fā)安全的,基礎(chǔ)map并不是并發(fā)安全的,本文為大家整理了三種實現(xiàn)了并發(fā)安全的map的方案,有需要的可以參考下
    2023-12-12
  • Go語言中使用反射的方法

    Go語言中使用反射的方法

    這篇文章主要介紹了Go語言中使用反射的方法,實例分析了Go語言實現(xiàn)反射的技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-02-02
  • 細(xì)說Go語言中空結(jié)構(gòu)體的奇妙用途

    細(xì)說Go語言中空結(jié)構(gòu)體的奇妙用途

    Go語言中,我們可以定義空結(jié)構(gòu)體,即沒有任何成員變量的結(jié)構(gòu)體,使用關(guān)鍵字?struct{}?來表示。這種結(jié)構(gòu)體似乎沒有任何用處,但實際上它在?Go?語言中的應(yīng)用非常廣泛,本文就來詳解講講
    2023-05-05
  • go語言題解LeetCode1122數(shù)組的相對排序

    go語言題解LeetCode1122數(shù)組的相對排序

    這篇文章主要為大家介紹了go語言題解LeetCode1122數(shù)組的相對排序,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12
  • Golang實現(xiàn)簡單http服務(wù)器的示例詳解

    Golang實現(xiàn)簡單http服務(wù)器的示例詳解

    這篇文章主要為大家詳細(xì)介紹了如何利用Golang實現(xiàn)簡單http服務(wù)器,文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)Golang有一定的幫助,需要的可以參考一下
    2023-03-03

最新評論

富蕴县| 邓州市| 叶城县| 凤台县| 南阳市| 务川| 陇西县| 柏乡县| 普陀区| 昔阳县| 务川| 潼南县| 太湖县| 汶川县| 临猗县| 县级市| 滦平县| 宜城市| 石河子市| 上饶县| 玉溪市| 富蕴县| 疏勒县| 佛学| 鄂州市| 长沙县| 建水县| 石嘴山市| 铜鼓县| 新宁县| 南澳县| 太康县| 九寨沟县| 卢氏县| 新余市| 莱芜市| 嘉定区| 桑日县| 德庆县| 拉孜县| 天津市|