https://twitter.com/ThePracticalDev/status/930878898245722112
如果你只是想寫一個自己用的小網站,或許你不需要框架,但如果你是要開發一個投入生產運營的網站,那么你肯定會需要一個框架,而且是需要一個好的 Web 框架。
如果你已經掌握所有必要的知識和經驗,你會冒險自己去重新開發所有的功能么?你有時間去找滿足生產級別要求的庫來用於開發么?另外,你確定這個庫可以滿足你后續所有的要求?
這些都是促使我們去使用框架的原因,哪怕是那些最牛的開發者也不會一直想要重新造輪子,我們可以站在前人的肩膀上,走得更快更好。
介紹
Go 是一門正在快速增長的編程語言,專為構建簡單、快速且可靠的軟件而設計。 點擊 此處 查看有哪些優秀的公司正在使用 Go 語言來驅動他們的業務。
本文將會提供一切必要的信息來幫助開發人員了解更多關於使用 Go 語言來開發 Web 應用程序的最佳選擇。
本文包含了最詳盡的框架比較,從流行度、社區支持及內建功能等多個不同角度出發做對比。
Beego:開源的高性能 Go 語言 Web 框架。
Buffalo:使用 Go 語言快速構建 Web 應用。
Echo:簡約的高性能 Go 語言 Web 框架。
Gin:Go 語言編寫的 Web 框架,以更好的性能實現類似 Martini 框架的 API。
Iris:全宇宙最快的 Go 語言 Web 框架。完備 MVC 支持,未來盡在掌握。
Revel:Go 語言的高效、全棧 Web 框架。
流行度
按照流行度排行(根據 GitHub Star 數量)
https://github.com/speedwheel/awesome-go-web-frameworks/blob/master/README.md#popularity
學習曲線
https://github.com/speedwheel/awesome-go-web-frameworks/blob/master/README.md#learning-curve
astaxie 和 kataras 分別為 Beego 和 Iris 做了超棒的工作,希望其他的框架也能迎頭趕上,為開發者提供更多的例子。至少對於我來說,如果我要切換到一個新的框架,那些例子就是最豐富的資源,來獲取盡可能多的有用信息。一個實例勝千言啊。
核心功能
根據功能支持的多寡排行
https://github.com/speedwheel/awesome-go-web-frameworks/blob/master/README.md#core-features
幾個知名的 Go 語言 Web 框架並不是真正意義上的框架,也就是說: Echo,Gin 和 Buffalo 並不是真正意義上的 Web 框架(因為沒有完備支持所有功能)但是大部分的 Go 社區認為它們是的,因此這些框架也可以和 Iris,Beego 或 Revel 做比較。所以,我們有義務將這幾個框架(Echo,Gin 和 Buffalo)也列在這個表中。
以上所有這些框架,除了 Beego 和 Revel 之外,都可以適配任意
net/http
中間件。其中一部分框架可以輕松地做適配,另外一些可能就需要額外的努力 [即使這里的痛苦不是一定的]。
技術性詞匯
路由:命名的路徑參數和通配符
可以處理動態的路徑。
命名的路徑參數例子:
"/user/{username}" 匹配 "/user/me","/user/speedwheel" 等等
上面路徑參數 username
的值分別是 "me"
和 "speedwheel"
。
通配符的例子:
"/user/{path *wildcard}" 匹配
"/user/some/path/here",
"/user/this/is/a/dynamic/multi/level/path" 等等
上面的路徑參數 path
對應的分別是 "some/path/here"
和 "this/is/a/dynamic/multi/level/path"
。
Iris 也支持一個叫
macros
的功能,它可以被表示為/user/{username:string}
或者/user/{username:int min(1)}
。
路由:正則表達式
過濾動態的路徑。
例如:
"/user/{id ^[0-9]$}" 能匹配 "/user/42" ,但不會匹配 "/user/somestring"
這里的路徑參數 id
的值為 42
。
路由:分組
通過共用邏輯或中間件來處理有共同前綴的路徑組。
例如:
myGroup := Group("/user", userAuthenticationMiddleware) myGroup.Handle("GET", "/", userHandler) myGroup.Handle("GET", "/profile", userProfileHandler) myGroup.Handle("GET", "/signup", getUserSignupForm)
- /user
- /user/profile
- /user/signup
你甚至可以從一個組中創建子分組:
myGroup.Group("/messages", optionalUserMessagesMiddleware) myGroup.Handle("GET', "/{id}", getMessageByID)
- /user/messages/{id}
路由:上述所有規則相結合而沒有沖突
這是一個高級且有用的的功能,我們許多人都希望路由模塊或 Web 框架能支持這點,但目前,在 Go 語言框架方面,只有 Iris 能支持這一功能。
這意味着類似如 /{path *wildcard}
, /user/{username}
和 /user/static
以及 /user/{path *wildcard}
等路徑都可以在同一個路由中通過靜態路徑(/user/static
)或通配符(/{path *wildcard}
)來正確匹配。
路由:自定義 HTTP 錯誤
指可以自行處理請求錯誤的情況。 Http 的錯誤狀態碼均 >=400
,比如 NotFound 404
,請求的資源不存在。
例如:
OnErrorCode(404, myNotFoundHandler)
上述的大多數 Web 框架只支持 404
,405
及 500
錯誤狀態的處理,但是例如 Iris,Beego 和 Revel
等框架,它們完備支持 HTTP 錯誤狀態碼,甚至支持 any error
任意錯誤。( any error
-- 任意錯誤,只有 Iris 能夠支持)。
100% 兼容 net/http
這意味著:
- 這些框架能夠讓你直接獲取
*http.Request
和http.ResponseWriter
的所有相關信息。 - 各框架提供各自相應處理
net/http
請求的方法。
中間件生態系統
框架會為你提供一個完整的引擎來定義流程、全局、單個或一組路由,而不需要你自己用不同的中間件來封裝每一部分的處理器。框架會提供比如 Use(中間件)、Done(中間件) 等函數。
類 Sinatra 的 API 設計(譯者注:Sinatra 是一門基於 Ruby 的領域專屬語言)
可以在運行時中注入代碼來處理特定的 HTTP 方法 (以及路徑參數)。
例如:
.Get or GET("/path", gethandler) .Post or POST("/path", postHandler) .Put or PUT("/path", putHandler) and etc.
服務器程序:默認啟用 HTTPS
框架的服務器支持注冊及自動更新 SSL 證書來管理新傳入的 SSL/TLS 連接 (https)。 最著名的默認啟用 https 的供應商是 letsencrypt。
服務器程序:平滑關閉(Gracefully Shutdown)
當按下 CTRL + C
關閉你的終端應用程序時,服務器將等待 (一定的等待時間)其他的連接完成相關任務或觸發一個自定義事件來做清理工作(比如:關閉數據庫),最后平滑地停止服務。
服務器程序:多重監聽
框架的服務器支持自定義的 net.Listener
或可以啟動一個有多個 http 服務和地址的 Web 應用。
完全支持 HTTP/2
框架可以很好地支持處理 https 請求的 HTTP/2 協議,並且支持服務器 Push
功能。
子域名
你可以直接在你的 Web 應用中注入子域名的路徑。
輔助功能(secondary)
意味着這個功能並不被這個框架原生支持,但是你仍舊可以通過啟用多個 http 服務器來實現。這樣做的缺點在於:主程序和子域名程序之間並不是連通的,默認情況下,它們不能共享邏輯。
會話(Sessions)
支持 http sessions,且可以在自定義的處理程序中使用 sessions。
- 有一些 Web 框架支持后台數據庫來儲存 sessions,以便在服務器重啟之后仍舊能獲得持久的 sessions。
- Buffalo 使用 gorilla 的 sessions 庫,它比其他框架的實現略微慢了一點。
例如:
func setValue(context http_context){ s := Sessions.New(http_context) s.Set("key", "my value") } func getValue(context http_context){ s := Sessions.New(http_context) myValue := s.Get("key") } func logoutHandler(context http_context){ Sessions.Destroy(http_context) }
Wiki: https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#HTTP_session
網絡套接字(Websockets)
框架支持 websocket 通信協議。不同的框架對於這點有各自不同的實現方式。
你應該通過它們的例子來看看哪個適合你。我的一個同事,在試過了上述所有框架中的 websocket 功能之后告訴我:Iris 實現了最多的 websocket 特性,並且提供了相對更容易使用的 API 。
Wiki: https://en.wikipedia.org/wiki/WebSocket
程序內嵌對視圖(又名模版)的支持
通常情況下,你必須根據 Web 應用的可執行文件一一對應地轉換模版文件。內嵌到應用中意味着這個框架集成了 go-bindata ,因此在最終的可執行文件中可以以 []byte
的形式將模版包含進來。
什么是視圖引擎
框架支持模版加載、自定義及內建模版功能,以此來節省我們的開發時間。
視圖引擎:STD
框架支持標准的 html/template
解析器加載模版。
視圖引擎:Pug
框架支持 Pug
解析器加載模版。
視圖引擎:Django
框架支持 Django
解析器加載模版。
視圖引擎:Handlebars
框架支持 Handlebars
解析器加載模版。
視圖引擎:Amber
框架支持 Amber
解析器加載模版。
渲染:Markdown, JSON, JSONP, XML...
框架提供一個簡單的方法來發送和自定義各種內容類型的響應。
MVC
Model–view–controller (MVC) 模型是一種用於在計算機上實現用戶界面的軟件架構模式,它將一個應用程序分為互相關聯的三部分。這樣做的目的是為了:將信息的內部處理邏輯、信息呈現給用戶以及從用戶獲取信息三者分離。MVC 設計模式將這三個組件解耦合,從而實現高效的代碼復用和並行開發。
- Iris 支持完備的 MVC 功能, 可以在運行時中注入。
- Beego 僅支持方法和數據模型的匹配,可以在運行時中注入。
- Revel 支持方法,路徑和數據模型的匹配,只可以通過生成器注入(生成器是另外一個不同的軟件用於構建你的 Web 應用)。
Wiki: https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller
緩存
Web 緩存(或 http 緩存)是一種用於臨時存儲(緩存)網頁文檔,如 HTML 頁面和圖像,來減緩服務器延時。一個 Web 緩存系統緩存網頁文檔,使得后續的請求如果滿足特定條件就可以直接得到緩存的文檔。Web 緩存系統既可以指設備,也可以指軟件程序。
Wiki: https://en.wikipedia.org/wiki/Web_cache
文件服務器
可以注冊一個(物理的)目錄到一個路徑,使得這個路徑下的文件可以自動地提供給客戶端。
文件服務器:內嵌入應用
通常情況下,你必須將所有的靜態文件(比如靜態資產,assets:CSS,JavaScript 文件等)與應用程序的可執行文件一起傳輸。支持此項功能的框架為你提供了在應用中,以 []byte
的形式,內嵌所有這些數據的機會。由於服務器可以直接使用這些數據而無需在物理位置查找文件,它們的響應速度也將更快。
響應可以在發送前的生命周期中被多次修改
目前只有 Iris 通過 http_context 中內建的的響應寫入器(response writer)支持這個功能。
當框架支持此功能時,你可以在返回給客戶端之前檢索、重置或修改狀態碼、正文(body)及頭部(headers)。默認情況下,在基於 net/http
的 Web 框架中這是不可能的,因為正文和狀態碼一經寫定就不能被檢索或修改。
Gzip
當你在一個路由的處理程序中,並且你可以改變響應寫入器(response writer)來發送一個用 gzip 壓縮的響應時,框架會負責響應的頭部。如果發生任何錯誤,框架應該把響應重置為正常,框架也應該能夠檢查客戶端是否支持 gzip 壓縮。
gzip 是用於壓縮和解壓縮的文件格式和軟件程序。
Wiki: https://en.wikipedia.org/wiki/Gzip
測試框架
可以使用框架特定的庫,來幫助你輕松地編寫更好的測試代碼來測試你的 HTTP 。
例如(目前僅 Iris 支持此功能):
func TestAPI(t *testing.T) { app := myIrisApp() tt := httptest.New(t, app) tt.GET("/admin").WithBasicAuth("name", "pass").Expect(). Status(httptest.StatusOK).Body().Equal("welcome") }
myIrisApp
返回你虛構的 Web 應用,它有一個針對 /admin
路徑的 GET 方法,它有基本的身份驗證邏輯保護。
上面這個簡單的測試,用 "name"
和 "pass"
通過身份驗證並訪問 GET /admin
,檢查它的響應狀態是否為 Status OK
,並且響應的主體是否為 "welcome"
。
TypeScript 轉譯器
TypeScript 的目標是成為 ES6 的超集。除了標准定義的所有新特性外,它還增加了靜態類型系統。TypeScript 還有轉換器用於將 TypeScript 代碼(即 ES6 + 類型)轉換為 ES5 或 ES3 JavaScript 代碼,如此我們就可以在現今的瀏覽器中運行這些代碼了。
在線編輯器
在在線編輯器的幫助下,你可以快速輕松地在線編譯和運行代碼。
日志系統
自定義日志系統通過提供有用的功能,如彩色日志輸出、格式化、日志級別分離及不同的日志記錄后端等,來擴展原生日志包。
維護和自動更新
以非侵入的方式通知框架的用戶即時更新。
再見!
謝謝你的閱讀,如果你喜歡這篇文章,請用表情符號和我互動哦