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

使用Go語言自制簡單易用的Web框架

 更新時間:2024年01月15日 10:50:49   作者:dpwgc  
這篇文章主要為大家詳細介紹了如何使用Go語言實現(xiàn)自制簡單易用的Web框架,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習一下

為什么寫這玩意

有時我要寫一些很小的應(yīng)用,比如爬蟲后端、服務(wù)器腳本又或者是BFF服務(wù),需要簡單的Web服務(wù)。用gin感覺有點重,go.mod里會有很多用不到的依賴,直接用httprouter又很麻煩。所以想整個簡單易用的Web框架。在實現(xiàn)基礎(chǔ)能力的同時,順便集成一些方便開發(fā)的功能(便捷的Websocket連接、SSE推送、自動綁定請求數(shù)據(jù)、自動序列化返回響應(yīng)數(shù)據(jù)),并且盡量不引入第三方依賴,保持極簡架構(gòu)。

大概的架構(gòu)圖

技術(shù)選型

  • 底層HTTP路由:選擇httprouter。
  • 將請求頭/表單/URI參數(shù)綁定到結(jié)構(gòu)體上:選擇mapstructure。

框架目前的go.mod依賴情況:

module github.com/dpwgc/easierweb

go 1.21.4

require (
   github.com/julienschmidt/httprouter v1.3.0
   github.com/mitchellh/mapstructure v1.5.0
   golang.org/x/net v0.17.0
   gopkg.in/yaml.v3 v3.0.1
)

基本用法

首先,運行g(shù)o get,安裝一下框架:

go get github.com/dpwgc/easierweb

然后,編寫路由代碼,寫起來和gin差不多,沒有學習成本:

package main

import (
   "github.com/dpwgc/easierweb"
   "github.com/dpwgc/easierweb/middlewares"
   "log"
   "net/http"
)

func main() {

   // 新建一個路由
   router := easierweb.New()
   
   // 使用日志中間件
   router.Use(middlewares.Logger())
   
   // GET接口
   router.GET("/hello/:name", hello)
   
   // 啟動服務(wù)
   log.Fatal(router.Run(":80"))
}

// 請求處理函數(shù)
func hello(ctx *easierweb.Context) {

   // 獲取URI Path里的name參數(shù)
   name := ctx.Path.Get("name")
   
   // 綁定URI Query參數(shù)到指定結(jié)構(gòu)體上
   req := Request{}
   err := ctx.BindQuery(&req)
   if err != nil {
      panic(err)
   }
   
   fmt.Println("request data:", req)
   
   // 響應(yīng):hello {name}
   ctx.WriteString(http.StatusOK, "hello "+name)
}

// 請求結(jié)構(gòu)體
type Request struct {
   Name   string `mapstructure:"name"`
   Mobile string `mapstructure:"mobile"`
}

進階改造(將繁瑣的流程自動化)

實際在使用的時候,每次獲取請求數(shù)據(jù)都得調(diào)用一下Bind函數(shù),然后響應(yīng)數(shù)據(jù)時又得調(diào)用下Write函數(shù)再return,感覺還是不夠簡單,因此加了個通過反射自動綁定請求數(shù)據(jù)到結(jié)構(gòu)體、自動序列化寫入響應(yīng)數(shù)據(jù)的功能。

實現(xiàn)方式參考: github.com/MikeLINGxZ/simple-server-runner 這是一個基于Gin的自動綁定請求數(shù)據(jù)+自動寫入響應(yīng)數(shù)據(jù)的庫。

最終成品有點像Spring Boot那種接口方法樣式:

package main

import (
   "fmt"
   "github.com/dpwgc/easierweb"
   "github.com/dpwgc/easierweb/middlewares"
   "log"
)

func main() {
	
   // 還是老樣子,先創(chuàng)建一個路由
   router := easierweb.New().Use(middlewares.Logger())
   
   // 使用EasyPOST函數(shù)(EasyXXX函數(shù)內(nèi)置了自動綁定+自動寫入),整一個POST提交接口
   router.EasyPOST("/submit", submit)
   
   // 啟動服務(wù)
   log.Fatal(router.Run(":80"))
}

// 請求處理函數(shù)(自動綁定請求數(shù)據(jù)+自動寫入響應(yīng)數(shù)據(jù))
// 這個請求處理函數(shù)和上文的基礎(chǔ)版不大一樣,除了上下文入?yún)⒁酝?,還有個請求數(shù)據(jù)入?yún)⒑晚憫?yīng)數(shù)據(jù)返回體
// 當這個函數(shù)被調(diào)用時,會通過反射將POST請求的Body數(shù)據(jù)自動解析并綁定到req參數(shù)上(如果是GET請求就綁定Query參數(shù))
// 當這個函數(shù)返回時,同樣通過反射獲取到返回的結(jié)構(gòu)體,將其序列化成Json字符串后,寫入響應(yīng)
func submit(ctx *easierweb.Context, req Request) *Response {
	
   // 打印req的參數(shù)
   fmt.Printf("json body -> name: %s, mobile: %s \n", req.Name, req.Mobile)
   
   // 直接return結(jié)構(gòu)體
   return &Response{Code: 1000, Msg:  "hello"}
}

type Request struct {
   Name   string `json:"name"`
   Mobile string `json:"mobile"`
}

type Response struct {
   Code int    `json:"code"`
   Msg  string `json:"msg"`
}

請求入?yún)⒑晚憫?yīng)返回值在反射賦值/取值時都做了動態(tài)化識別,可傳可不傳,不傳req入?yún)r就不會自動綁定請求數(shù)據(jù),不返回Response且沒有報錯時就響應(yīng)204,返回了error或者函數(shù)拋出異常了就返回400/500,Response可以是對象也可以是切片。

func TestAPI(ctx *easierweb.Context, req Request) (*Response, error)
func TestAPI(ctx *easierweb.Context, req Request) *Response
func TestAPI(ctx *easierweb.Context, req Request) error
func TestAPI(ctx *easierweb.Context, req Request)
func TestAPI(ctx *easierweb.Context) (*Response, error)
func TestAPI(ctx *easierweb.Context) *Response
func TestAPI(ctx *easierweb.Context) error
func TestAPI(ctx *easierweb.Context)

實際開發(fā)中,不一定以Json格式來接收/呈現(xiàn)數(shù)據(jù),所以留了個插件口子,可以讓用戶自定義自動綁定/寫入數(shù)據(jù)的序列化與反序列化方式。

// 使用XML格式來處理自動綁定和自動寫入的數(shù)據(jù)
router := easierweb.New(easierweb.RouterOptions{
   RequestHandle: plugins.XMLRequestHandle(),
   ResponseHandle: plugins.XMLResponseHandle(),
})

追加功能(常用方法封裝)

我寫瀏覽器Js爬蟲經(jīng)常要用Websocket來連接后端并持續(xù)傳輸數(shù)據(jù),還有些表單動態(tài)賦值的需求經(jīng)常要用到SSE,那就順便給框架整個websocket和SSE的快捷使用方式,同時把連接升級、跨域、SSE請求頭設(shè)置、連接關(guān)閉之類的操作全部都封裝到底層,不需要使用者操心這么多事情。

func main() {

   // 新建路由
   router := easierweb.New()
   
   // 快速使用websocket
   router.WS("/demoWS/:id", DemoWS)

   // 快速使用SSE
   router.SSE("/demoSSE/:id", DemoSSE)

   // 啟動
   log.Fatal(router.Run(":80"))
}
// 快速使用websocket
func DemoWS(ctx *easierweb.Context) {

   // 處理websocket連接
   for {
   
      // 接收客戶端消息
      msg, err := ctx.ReceiveString()
      if err != nil {
         panic(err)
      }

      fmt.Println("read websocket msg:", msg)

      // 發(fā)送消息給客戶端
      err = ctx.SendString("hello")
      if err != nil {
         panic(err)
      }

      time.Sleep(1 * time.Second)

      // 函數(shù)返回時,websocket連接會自動關(guān)閉,不勞煩用戶手動調(diào)close了
      return
   }
}
// 快速使用SSE
func DemoSSE(ctx *easierweb.Context) {

   // 循環(huán)推送數(shù)據(jù)
   for i := 0; i < 5; i++ {

      // SSE推送數(shù)據(jù), data: hello, id: {i}
      err := ctx.Push(fmt.Sprintf("data: hello\nid: %v\n\n", i))
      if err != nil {
         panic(err)
      }

      time.Sleep(1 * time.Second)
   }
}

以上就是使用Go語言自制簡單易用的Web框架的詳細內(nèi)容,更多關(guān)于Go Web框架的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 如何在Go語言中高效使用Redis的Pipeline

    如何在Go語言中高效使用Redis的Pipeline

    在 Redis 中,Pipeline 就像一條流水線,它允許我們將多個命令一次性發(fā)送到服務(wù)器,下面我們就來看看如何在Go語言中高效使用Redis的Pipeline吧
    2024-11-11
  • go如何刪除字符串中的部分字符

    go如何刪除字符串中的部分字符

    這篇文章主要介紹了go刪除字符串中的部分字符操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-04-04
  • Golang內(nèi)存模型教科書級講解

    Golang內(nèi)存模型教科書級講解

    go官方介紹go內(nèi)存模型的時候說:探究在什么條件下,goroutine?在讀取一個變量的值的時,能夠看到其它?goroutine?對這個變量進行的寫的結(jié)果,Go內(nèi)存模型規(guī)定了一些條件,在這些條件下,在一個goroutine中讀取變量返回的值能夠確保是另一個goroutine中對該變量寫入的值
    2023-03-03
  • Golang接口型函數(shù)使用小結(jié)

    Golang接口型函數(shù)使用小結(jié)

    接口函數(shù)指的是用函數(shù)實現(xiàn)接口,這樣在調(diào)用的時候就會非常簡便,這種方式適用于只有一個函數(shù)的接口,這里以迭代一個map為例,演示這一實現(xiàn)的技巧,對Golang接口型函數(shù)使用知識感興趣的朋友一起看看吧
    2022-06-06
  • Golang定時任務(wù)框架GoCron的源碼分析

    Golang定時任務(wù)框架GoCron的源碼分析

    本文主要介紹了Golang定時任務(wù)框架GoCron的源碼分析,原生的gocron存在一些問題,如任務(wù)列表維護不當、并發(fā)操作不可預測等,經(jīng)過改進的gocron解決了這些問題,感興趣的可以了解一下
    2025-03-03
  • golang panic及處理機制

    golang panic及處理機制

    Go語言追求簡潔優(yōu)雅,所以,Go語言不支持傳統(tǒng)的 try…catch…finally 這種異常,因為Go語言的設(shè)計者們認為,將異常與控制結(jié)構(gòu)混在一起會很容易使得代碼變得混亂,今天給大家介紹golang panic及處理機制,需要的朋友參考下吧
    2021-08-08
  • go使用SQLX操作MySQL數(shù)據(jù)庫的教程詳解

    go使用SQLX操作MySQL數(shù)據(jù)庫的教程詳解

    sqlx 是 Go 語言中一個流行的操作數(shù)據(jù)庫的第三方包,它提供了對 Go 標準庫 database/sql 的擴展,簡化了操作數(shù)據(jù)庫的步驟,下面我們就來學習一下go如何使用SQLX實現(xiàn)MySQL數(shù)據(jù)庫的一些基本操作吧
    2023-11-11
  • Go基礎(chǔ)教程系列之import導入包(遠程包)和變量初始化詳解

    Go基礎(chǔ)教程系列之import導入包(遠程包)和變量初始化詳解

    這篇文章主要介紹了Go基礎(chǔ)教程系列之import導包和初始化詳解,需要的朋友可以參考下
    2022-04-04
  • golang版本升級的簡單實現(xiàn)步驟

    golang版本升級的簡單實現(xiàn)步驟

    個人感覺Go在眾多高級語言中,是在各方面都比較高效的,下面這篇文章主要給大家介紹了關(guān)于golang版本升級的簡單實現(xiàn)步驟,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2023-02-02
  • go語言中如何使用select的實現(xiàn)示例

    go語言中如何使用select的實現(xiàn)示例

    本文主要介紹了go語言中如何使用select的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-05-05

最新評論