Golang - 三款主流框架Gin Beego Iris 選型對比


1.常見框架

1.1 框架排名

  • Gin 31k [Lite]
  • Beego 22k
  • Iris 16k
  • Echo 15k [Lite]
  • Revel 11k
  • Martini 10k [×]
  • buffalo 5k [Lite]

1.2 框架特性

Gin:

Gin 是一個用 Go (Golang) 編寫的 web 框架。它是一個類似於 martini 但擁有更好性能的 API 框架, 由於 httprouter,速度提高了近 40 倍。如果你是性能和高效的追求者, 你會愛上 Gin.

快速:基於 Radix 樹的路由,小內存占用。沒有反射。可預測的 API 性能。

支持中間件:傳入的 HTTP 請求可以由一系列中間件和最終操作來處理。例如:Logger,Authorization,GZIP,最終操作 DB。

Crash 處理:Gin 可以 catch 一個發生在 HTTP 請求中的 panic 並 recover 它。這樣,你的服務器將始終可用。例如,你可以向 Sentry 報告這個 panic!

JSON 驗證:Gin 可以解析並驗證請求的 JSON,例如檢查所需值的存在。

路由組:更好地組織路由。是否需要授權,不同的 API 版本…… 此外,這些組可以無限制地嵌套而不會降低性能。

錯誤管理:Gin 提供了一種方便的方法來收集 HTTP 請求期間發生的所有錯誤。最終,中間件可以將它們寫入日志文件,數據庫並通過網絡發送。

內置渲染:Gin 為 JSON,XML 和 HTML 渲染提供了易於使用的 API。

可擴展性:新建一個中間件非常簡單,去查看示例代碼吧。

Beego:

bee 工具是一個為了協助快速開發 beego 項目而創建的項目,通過 bee 您可以很容易的進行 beego 項目的創建、熱編譯、開發、測試、和部署。

簡單化:RESTful 支持、MVC 模型,可以使用 bee 工具快速地開發應用,包括監控代碼修改進行熱編譯、自動化測試代碼以及自動化打包部署。

智能化:支持智能路由、智能監控,可以監控 QPS、內存消耗、CPU 使用,以及 goroutine 的運行狀況,讓您的線上應用盡在掌握。

模塊化:beego 內置了強大的模塊,包括 Session、緩存操作、日志記錄、配置解析、性能監控、上下文操作、ORM 模塊、請求模擬等強大的模塊,足以支撐你任何的應用。

高性能:beego 采用了 Go 原生的 http 包來處理請求,goroutine 的並發效率足以應付大流量的 Web 應用和 API 應用,目前已經應用於大量高並發的產品中。

Iris:

  • 專注於高性能
  • 簡單流暢的API
  • 高擴展性
  • 強大的路由和中間件生態系統
  • 使用iris獨特的表達主義路徑解釋器構建RESTful API
  • 動態路徑參數化或通配符路由與靜態路由不沖突
  • 使用重定向選項從URL中刪除尾部斜杠
  • 使用虛擬主機和子域名變得容易
  • 分組API和靜態或甚至動態子域名
  • net / http和negroni-like處理程序通過iris.FromStd兼容
  • 針對任意Http請求錯誤 定義處理函數
  • 支持事務和回滾
  • 支持響應緩存
  • 使用簡單的函數嵌入資源並與go-bindata 保持兼容
  • mvc
  • 上下文
  • 高度可擴展的試圖渲染(目前支持markdown,json,xml,jsonp等等)
  • 正文綁定器和發送HTTP響應的便捷功能
  • 限制請求正文
  • 提供靜態資源或嵌入式資產
  • 本地化i18N
  • 壓縮(Gzip是內置的)
  • 身份驗證
  • Basic Authentication
  • OAuth, OAuth2 (支持27個以上的熱門網站)
  • JWT 服務器
  • 通過TLS提供服務時,自動安裝和提供來自的證書
  • 默認為關閉狀態
  • 在關閉,錯誤或中斷事件時注冊
  • 連接多個服務器,完全兼容 net/http#Server
  • 視圖系統.支持五種模板引擎 完全兼容 html/template
  • Websocket庫,其API類似於 [如果你願意,你仍然可以使用你最喜歡的]
  • 熱重啟
  • Typescript集成 + Web IDE
  • Iris是最具特色的網絡框架之一

1.3 性能測試

  • (1):在一定的時間內實現的總調用數,越高越好
  • (2):單次操作耗時(ns/op),越低越好
  • (3):堆內存分配 (B/op), 越低越好
  • (4):每次操作的平均內存分配次數(allocs/op),越低越好

2.應用

2.1 主機服務

Gin

Gin 擁有靈活的開發環境,在運行時可以選擇默認的服務器來運行,也可以選擇原生的http.ListenAndServe(":8080", router) 來開啟服務,這是因為其本身使用 gin.Default()創建的 router 對象實現了 Handler 接口,這就以為着其可以選擇其他的 HTTP 服務器,如 fvbock/endless 、 manners 或者原生的 http.Server 內置的 Shutdown 方法進行服務重啟。

r := gin.Default() _ = r.Run() // 或者啟動原生服務 manners.ListenAndServe(":8888", r)

BeeGo

Beego 提供了一個構建工具,有着標准的開發環境規范,可以一鍵生成工程目錄,並在工程目錄使用 run指令可以直接運行項目,並且支持開發模式下的熱更新。

beego.Run()

Iris

Iris 的主機有多種拓展功能,包括自定義監聽服務、主機配置,同時也支持多主機服務。與 Gin 相似的 iris.Router與 net/http/Handler 功能兼容,它可以在任何net/http服務器上進行調整:

app := iris.New() app.Run(iris.Addr(":8080")) // 或者自定義鏈接方式與端口號 l, err := listenerCfg.NewListener("tcp", ":8080") if err != nil { app.Logger().Fatal(err) } app.Run(iris.Listener(l)) // 或者啟動原生服務 app.Run(iris.Raw(&http.Server{Addr:":8080"}).ListenAndServe)

2.2 路由

Gin

Gin 在路由系統上集成了 HttpRouter 擁有高性能的優勢,同時擁有其豐富的功能,包括組合路由、路由驗證、CORS 等。

簡單路由:

r := gin.Default() r.GET("/ping", func(c *gin.Context) { c.String(http.StatusOK, "pong") })

分層路由:

someGroup := router.Group("/someGroup") { someGroup.GET("/someGet", getting) someGroup.POST("/somePost", posting) }

BeeGo

BeeGo 的路由功能較為豐富,擁有基礎路由、固定路由、正則路由、注解路由、namespace等多個功能,其 REST 風格性較強,且有固定的路由層規范。

簡單路由:

beego.Get("/",func(ctx *context.Context){ ctx.Output.Body([]byte("hello world")) })

固定路由:

beego.Router("/", &controllers.MainController{}) beego.Router("/admin", &admin.UserController{}) beego.Router("/admin/index", &admin.ArticleController{}) beego.Router("/admin/addpkg", &admin.AddController{})

namespace(分層路由):

//初始化 namespace ns := beego.NewNamespace("/v1", beego.NSCond(func(ctx *context.Context) bool { if ctx.Input.Domain() == "api.beego.me" { return true } return false }), beego.NSBefore(auth), beego.NSGet("/notallowed", func(ctx *context.Context) { ctx.Output.Body([]byte("notAllowed")) }), beego.NSRouter("/version", &AdminController{}, "get:ShowAPIVersion"), beego.NSRouter("/changepassword", &UserController{}), beego.NSNamespace("/shop", beego.NSBefore(sentry), beego.NSGet("/:id", func(ctx *context.Context) { ctx.Output.Body([]byte("notAllowed")) }), ), beego.NSNamespace("/cms", beego.NSInclude( &controllers.MainController{}, &controllers.CMSController{}, &controllers.BlockController{}, ), ), ) //注冊 namespace beego.AddNamespace(ns)

Irisi

簡單路由:

app.Get("/", func(ctx iris.Context) { ctx.HTML("<h1> Hello from /contact </h1>") })

分層路由:

users := app.Party("/users", myAuthMiddlewareHandler) // http://localhost:8080/users/42/profile users.Get("/{id:int}/profile", userProfileHandler) // http://localhost:8080/users/inbox/1 users.Get("/inbox/{id:int}", userMessageHandler) // 或者使用嵌套風格 app.PartyFunc("/users", func(users iris.Party) { users.Use(myAuthMiddlewareHandler) // http://localhost:8080/users/42/profile users.Get("/{id:int}/profile", userProfileHandler) // http://localhost:8080/users/messages/1 users.Get("/inbox/{id:int}", userMessageHandler) })

2.3 上下文對象

在進行路由匹配之后,可以獲取到上下文對象,三套框架都對 Context 進行了封裝。

Gin 與 Iris 對 context 的封裝均是為其增加了必要的新功能,同時可以返回原生的http.Request對象。但 Beego 的 context 模塊是對原生的 http.ResponseWriter 和 http.Request 對象進行了徹底的封裝,將其分為兩個部分,分別為 Input 對象與 Output 對象,對應的將常用方法進行封裝,並不能調出原生的對象。

2.4 數據操作

原生

在原生開發中,Go 支持解析 JSON 格式的數據處理能力:

// 解析 JSON func Unmarshal(data []byte, v interface{}) error // 生成 JSON func Marshal(v interface{}) ([]byte, error)

如果使用simplejson可以簡化 JSON 數據的操作:

js, err := NewJson([]byte(`{ "test": { "array": [1, "2", 3], "int": 10, "float": 5.150, "bignum": 9223372036854775807, "string": "simplejson", "bool": true } }`)) arr, _ := js.Get("test").Get("array").Array() i, _ := js.Get("test").Get("int").Int() ms := js.Get("test").Get("string").MustString()

Gin

Gin 可以使用 c.ShouldBind方法,可以將參數自動綁定到 struct.該方法是會檢查 Url 查詢字符串和 POST 的數據,而且會根據 content-type類型,優先匹配JSON或者 XML,之后才是 Form

接收數據:

func main() { route := gin.Default() route.POST("/testing", (c *gin.Context) { var person Person // 定義結構體步驟省略 // 綁定到 person if c.ShouldBind(&person) == nil { log.Println(person.Name) log.Println(person.Address) log.Println(person.Birthday) } c.String(200, "Success") }) route.Run(":8085") }

發送數據:

Gin 輸出這 JSON、 XML、 YAML 三種格式非常方便,直接使用對用方法並賦值一個結構體給它就行了。

同時還可以使用gin.Hgin.H 是一個很巧妙的設計,你可以像javascript定義json一樣,直接一層層寫鍵值對,只需要在每一層加上 gin.H即可:

func main() { r := gin.Default() // gin.H 本質是 map[string]interface{} r.GET("/someJSON", func(c *gin.Context) { // 會輸出頭格式為 application/json; charset=UTF-8 的 json 字符串 c.JSON(http.StatusOK, gin.H{"message": "hey", "status": http.StatusOK}) }) r.GET("/moreJSON", func(c *gin.Context) { // 直接使用結構體定義 var msg struct { Name string `json:"user"` Message string Number int } msg.Name = "Lena" msg.Message = "hey" msg.Number = 123 // 會輸出 {"user": "Lena", "Message": "hey", "Number": 123} c.JSON(http.StatusOK, msg) }) r.GET("/someXML", func(c *gin.Context) { // 會輸出頭格式為 text/xml; charset=UTF-8 的 xml 字符串 c.XML(http.StatusOK, gin.H{"message": "hey", "status": http.StatusOK}) }) r.GET("/someYAML", func(c *gin.Context) { // 會輸出頭格式為 text/yaml; charset=UTF-8 的 yaml 字符串 c.YAML(http.StatusOK, gin.H{"message": "hey", "status": http.StatusOK}) }) r.Run(":8080") }

Gin 支持返回的數據格式有:HTML, String,JSON, XML, YAML

BeeGo

Beego 對與JSON 數據處理則比較復雜,如果接受數據則需要從 context.RequestBody 中取出數據,之后需要使用斷言解析數據,實際上,這里的處理方式與原生的是一樣的,並未進行功能優化:

var body map[string]interface{} _ = json.Unmarshal(ctx.Input.RequestBody, &body) // 將 json 數據解析到 body 變量中 username := body["name"].(string) // 使用斷言取出單個數據

對於返回一個 json 數據,BeeGo 只是將我們創建的 json 結構對象存放於context.Data下的“json”字段中,然后調用context.ServeJSON()方法時,會去獲取c.Data["json"]下存放的結構然后將結果轉換成 json 的數據格式並發送:

type User struct { Name string `json:"name"` Age int `json:"age"` } func (c *TestController) TestData() { user := User{ Name: "huahua", Age: 18, } c.Data["json"] = user c.ServeJSON() }

起始在處理 json 這一步,Beego 只是做了非常簡單的替換工作,context.ServeJSON()的方法調用后,取到我們設置的結構體后調用了:

func (output *BeegoOutput) JSON(data interface{}, hasIndent bool, encoding bool) error

該方法將結構體通過 json.Marshal()轉成了 json 格式,同時又為響應報文添加了相應響應數據格式信息,之后將數據送出。

此外,BeeGo 支持返回的數據類型由有:JSON、XML、JSONP

Iris

Irisi 對處理 JSON 數據的方法進行了封裝,同時也擁有驗證數據的能力。

發送數據與前兩者無差別,都是先定義結構體,然后底層使用 JSON 庫的能力對 JSON 數據進行解析並賦值於創建的對象。

接收數據:

func MyHandler(ctx iris.Context) { var c Company // 定義結構體省略 if err := ctx.ReadJSON(&c); err != nil { ctx.StatusCode(iris.StatusBadRequest) ctx.WriteString(err.Error()) return } ctx.Writef("Received: %#+v\n", c) }

在對於返回數據的處理上,與 Gin 相似,采用了在 iris.Context.JSON()方法可以將對象轉化為 JSON 數據輸出。

返回數據:

app.Get("/encode", func(ctx iris.Context) { peter := User{ Firstname: "John", Lastname: "Doe", City: "Neither FBI knows!!!", Age: 25, } //手動設置內容類型: ctx.ContentType("application/javascript") ctx.JSON(peter) })

此外,Iris 支持返回的數據格式有:binary, text, json, jsonp, xml, markdown

2.5 模板引擎

原生

Go web 能力中包含了模板引擎的支持,可以使用 template 包來進行模板處理,使用類似 ParseParseFileExecute 等方法從文件或者字符串加載模板,然后執行類似下圖展示的模板的 merge 操作:

func handler(w http.ResponseWriter, r *http.Request) { t := template.New("some template") // 創建一個模板 t, _ = t.ParseFiles("tmpl/welcome.html") // 解析模板文件 user := GetUser() // 獲取當前用戶信息 t.Execute(w, user) // 執行模板的 merger 操作 }

原生的模板引擎支持以下的能力:

  • 字段操作:{{.}}
  • 數據遍歷:{{with …}}…{{end}} {{range …}}{{end}}
  • 條件處理:if ... else ...
  • 管道符 (基於模板函數)
  • 模板函數
  • 模板變量
  • Must 操作:作用是檢測模板是否正確,例如大括號是否匹配,注釋是否正確的關閉,變量是否正確的書寫。
  • 嵌套模板

Gin

Gin 可以通過配置 LoadHTMLGlob() 或者 LoadHTMLFiles() 啟用模板渲染,這兩個方法掛載與 gin.Defalut()生成的 router 對象上,用於設置,模板目錄 。匹配完成后可以調用 Context.HTML 進行渲染和數據注入。

同時,與原生不同的是,Gin 可以使用 gin.H()來向模板注入 json 格式的數據,而不需要創建額外的結構體。

func main() { router := gin.Default() router.LoadHTMLGlob("templates/*") //router.LoadHTMLFiles("templates/template1.html", "templates/template2.html") router.GET("/index", func(c *gin.Context) { c.HTML(http.StatusOK, "index.tmpl", gin.H{ "title": "Main website", }) }) router.Run(":8080") }

Gin 的模板引擎支持以下能力:

  • 使用自定義的 html 模板渲染
  • 自定義分隔符(模板標簽)
  • 繼承原生能力

相比原生,Gin 定義模板的方式是采用創建全局模板對象(LoadHTMLGlob),然后在上下文對象中使用 c.HTML 去直接調用模板路徑下的文件渲染模板。而原生則是在路由的上下文對象中創建 Template 對象,然后在上下文對象中渲染 Template 對象完成渲染工作。

Beego

beego 的模板處理引擎采用的是 Go 內置的 html/template 包進行處理,而且 beego 的模板處理邏輯是采用了緩存編譯方式,也就是所有的模板會在 beego 應用啟動的時候全部編譯然后緩存在 map 里面,Beego 的模板引擎支持以下能力:

  • 自定義模板目錄
  • 自動渲染
  • 自定義模板標簽
  • 模板數據:模板中的數據是通過在 Controller 中 this.Data 獲取的
  • 自定義模板名稱
  • layout 設計、LayoutSection:實際上是模板的組合、嵌套
  • renderform

Iris

Iris 自身並沒有創建一種直接可用的模板引擎,而是交給用戶可以選擇任意一種模板引擎,且完全兼容 html/template。

官方推薦使用 Hero 引擎,可以預編譯html模板以獲取代碼,其擁有以下特性:

  • 高性能.
  • 非常易用.
  • 功能強大,支持模板繼承和模板include.
  • 自動編譯.

同時可以選用 quicktemplate 引擎,其擁有以下特性:

  1. 非常快。模板轉換為Go代碼然后編譯
  2. Quicktemplate語法非常接近Go - 在開始使用quicktemplate之前無需學習另一種模板語言
  3. 在模板編譯期間幾乎所有錯誤都被捕獲,因此生產受模板相關錯誤的影響較小
  4. 使用方便。有關詳細信息,請參閱快速入門和示例
  5. 強大。任意Go代碼可以嵌入到模板中並與模板混合。小心這個功能 - 不要從模板中查詢數據庫and/or外部資源,除非你錯過Go中的PHP方式:)這種功能主要用於任意數據轉換
  6. 易於使用的模板繼承由Go接口提供支持。請參閱此示例以獲取詳細信
  7. 模板被編譯為單個二進制文件,因此無需將模板文件復制到服務器

2.6 MVC 架構

Gin

Gin 不支持 MVC 架構模式,需要開發者自行實現,具有一定的靈活性。

Beego

Beego 是標准的 MVC 框架,對 MVC 有着良好的支持,同時提供了 Model 層的 ORM 引擎。

Iris

Iris對MVC(模型視圖控制器)模式有一流的支持,Iris web框架支持請求數據、模型、持久數據和以最快的速度執行的綁定。其模式流程圖如下:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM