wegoGo 語(yǔ)言 Web 框架
wego是一個(gè)Go語(yǔ)言編寫的高性能的Web框架,可以用來(lái)快速開(kāi)發(fā)RESTful服務(wù)以及后端服務(wù)等各種應(yīng)用。
wego框架是一個(gè)完整的MVC框架,包括路由模塊、數(shù)據(jù)庫(kù)ORM模塊、view模板處理以及Session模塊。
wego具有性能高、方便易用,兼容性好,擴(kuò)展性強(qiáng)等特點(diǎn),具體特征如下:
- 基于Radix樹開(kāi)發(fā)的路由模塊,路由查詢性能高。
- 支持路由組。
- 為路由參數(shù)、Query參數(shù)、Form參數(shù)的訪問(wèn)提供率方便易于使用的API,并可以將參數(shù)映射到Struct。
- 為JSON、XML和HTML渲染提供了易于使用的API。
- 支持過(guò)濾器中間件,方便您對(duì)Web框架進(jìn)行擴(kuò)展。
- 支持BeforeRoute、BeforeExec、AfterExec攔截器,方便您進(jìn)行身份驗(yàn)證、日志輸出。
- 內(nèi)置Crash處理機(jī)制,wego可以recover一個(gè)HTTP請(qǐng)求中的panic,這樣可確保您的服務(wù)器始終可用。
- 內(nèi)置Config模塊,方便對(duì)應(yīng)用的參數(shù)進(jìn)行管理。
- 內(nèi)置Session模塊,您可以選擇cookie、redis、memcache、memory緩存引擎存儲(chǔ)Session數(shù)據(jù)。
- 支持混合路由,固定路由、參數(shù)路由、通配符路由可以混合,不沖突。
- 內(nèi)置log模塊,用于生成應(yīng)用日志。
- 采用緩存來(lái)管理HTML的Template,既方便輸出Html頁(yè)面,又可以使用緩存提升系統(tǒng)性能。
- 良好的兼容性,wego支持go原生的func(http.ResponseWriter, *http.Request)路由處理函數(shù),這樣您的代碼少量修改就可以使用wego了。
- wego兼容兩種編碼習(xí)慣,可以使用普通函數(shù)作為路由處理函數(shù),也可以使用strcut的成員函數(shù)作為路由處理函數(shù)。
安裝
go get github.com/haming123/wego
使用文檔
請(qǐng)點(diǎn)擊:詳細(xì)文檔
簡(jiǎn)單http server
創(chuàng)建一個(gè)main.go文件,代碼如下:
package main import ( "wego" log "wego/dlog" ) func main() { web, err := wego.NewWeb() if err != nil{ log.Error(err) return } web.GET("/hello", func(c *wego.WebContext) { c.WriteText(200, "world") }) err = web.Run(":8080") if err != nil { log.Error(err) } }
然后運(yùn)行它,打開(kāi)瀏覽器,輸入http://localhost:8080/hello, 就可以看到如下內(nèi)容:
world
項(xiàng)目結(jié)構(gòu)
wego框沒(méi)有對(duì)項(xiàng)目結(jié)構(gòu)做出限制,這里給出一個(gè)MVC框架項(xiàng)目的建議結(jié)構(gòu):
demo
├── app
│ └── router.go - 路由配置文件
│ └── templfun.go - 模板函數(shù)文件
├── controllers - 控制器目錄,必要的時(shí)候可以繼續(xù)劃分子目錄
│ └── controller_xxx.go
├── models - 模型目錄
│ └── model_xxx.go
├── logs - 日志文件目錄,主要保存項(xiàng)目運(yùn)行過(guò)程中產(chǎn)生的日志
│ └── applog_20211203.log
├── static - 靜態(tài)資源目錄
│ ├── css
│ ├── img
│ └── js
├── utils - 公共代碼目錄
│ └── util_xxx.go
├── views - 視圖模板目錄
│ └── html_xxx.html
├── app.conf - 應(yīng)用配置文件
└── main.go - 入口文件
注冊(cè)參數(shù)路由
func main() { web, err := wego.NewWeb() if err != nil{ log.Error(err) return } web.PATH("/user/:id", func(c *wego.WebContext) { c.WriteTextF(200, "param id=%s", c.RouteParam.GetString("id").Value) }) err = web.Run(":8080") if err != nil { log.Error(err) } }
注冊(cè)模糊匹配路由
func main() { web, err := wego.NewWeb() if err != nil{ log.Error(err) return } web.PATH("/files/*name", func(c *wego.WebContext) { c.WriteTextF(200, "param name=%s", c.RouteParam.GetString("name").Value) }) err = web.Run(":8080") if err != nil { log.Error(err) } }
注冊(cè)RESTful路由
func main() { web, err := wego.NewWeb() if err != nil{ log.Error(err) return } web.GET("/users/:id", func(c *wego.WebContext) { //查詢一個(gè)用戶 }) web.POST("/users/:id", func(c *wego.WebContext) { //創(chuàng)建一個(gè)用戶 }) web.PUT("/users/:id", func(c *wego.WebContext) { //更新用戶信息 }) web.PATCH("/users/:id", func(c *wego.WebContext) { //更新用戶的部分信息 }) web.DELETE("/users/:id", func(c *wego.WebContext) { //刪除用戶 }) err = web.Run(":8080") if err != nil { log.Error(err) } }
獲取參數(shù)
在wego中通過(guò)c.Param.GetXXX函數(shù)來(lái)獲取請(qǐng)求參數(shù):
func main() { web, err := wego.NewWeb() if err != nil{ log.Error(err) return } web.GET("/user", func(c *WebContext) { name := c.Param.GetString("name") if name.Error != nil { t.Error(name.Error) } age := c.Param.GetInt("age") if age.Error != nil { t.Error(age.Error) } c.WriteText(200, name.Value) }) err = web.Run(":8080") if err != nil { log.Error(err) } }
使用MustXXX便捷函數(shù)獲取參數(shù)
func main() { web, err := wego.NewWeb() if err != nil{ log.Error(err) return } web.GET("/user", func(c *WebContext) { name := c.Param.MustString("name") t.Log(name) age := c.Param.MustInt("age") t.Log(age) }) err = web.Run(":8080") if err != nil { log.Error(err) } }
使用ReadJSON獲取參數(shù)
若POST請(qǐng)求中Body的數(shù)據(jù)的格式為JSON格式,可以直接使用WebContext的ReadJSON函數(shù)來(lái)讀?。?/p>
func main() { web, err := wego.NewWeb() if err != nil{ log.Error(err) return } web.POST("/user", func(c *WebContext) { var user2 User err := c.ReadJSON(&user2) if err != nil { t.Log(err) } t.Log(user2) }) err = web.Run(":8080") if err != nil { log.Error(err) } }
輸出JSON數(shù)據(jù)
wego對(duì)于JSON的支持非常好,可以讓我們非常方便的開(kāi)發(fā)一個(gè)基于JSON的API。若要返回JSON請(qǐng)求結(jié)果,您可以使用WriteJSON函數(shù):
func writeJson(c *wego.WebContext) { var user User user.ID = 1 user.Name = "demo" user.Age = 12 c.WriteJSON(200, user) }
輸出HTML數(shù)據(jù)
wego框架的html結(jié)果的輸出是基于html/template實(shí)現(xiàn)的。以下是一個(gè)輸出html頁(yè)面的例子:
func writeHtml(c *wego.WebContext) { var user User user.ID = 1 user.Name = "demo" user.Age = 12 c.WriteHTML(200, "./views/index.html", user) }
使用模板函數(shù)
如果您的模板文件中使用了模板函數(shù),需要預(yù)先將所需的模板函數(shù)進(jìn)行登記:
func GetUserID(id int64) string { return fmt.Sprintf("ID_%d", id) } func main() { web, err := wego.NewWeb() if err != nil{ log.Error(err) return } wego.AddTemplFunc("GetUserID", GetUserID) web.GET("/templfunc", (c *wego.WebContext) { var user User user.ID = 1 user.Name = "lisi" user.Age = 12 c.WriteHTML(200, "./views/index.html", user) }) err = web.Run(":8080") if err != nil { log.Error(err) } }
設(shè)置cookie
func setCookie(c *wego.WebContext) { val, err := c.Input.Cookie("demo") if err != nil { log.Error(err) } cookie := &http.Cookie{ Name: "demo", Value: "test", Path: "/", HttpOnly: true, } c.SetCookie(cookie) }
重定向
func main() { web, err := wego.NewWeb() if err != nil{ log.Error(err) return } web.GET("/redirect", func(c *wego.WebContext) { c.Redirect(302, "/index") }) err = web.Run(":8080") if err != nil { log.Error(err) } }
錯(cuò)誤處理
func main() { web, err := wego.NewWeb() if err != nil{ log.Error(err) return } web.GET("/abort", func(c *wego.WebContext) { name := c.Param.GetString("name") if name.Error != nil { c.AbortWithError(500, name.Error) return } c.WriteText(200, "hello " + name.Value) }) err = web.Run(":8080") if err != nil { log.Error(err) } }
使用配置文件
- 首先定義一個(gè)簡(jiǎn)單的配置文件
#應(yīng)用名稱 app_name = demo #mysql數(shù)據(jù)庫(kù)的配置參數(shù) mysql = root:rootpwd@tcp(127.0.0.1:3306)/demp?charset=utf8 [server] #http監(jiān)聽(tīng)端口 http_port = 8080
- 使用InitWeb()函數(shù)初始化Web服務(wù)器
func main() { web, err := wego.InitWeb() if err != nil{ log.Error(err) return } err = web.Run() if err != nil { log.Error(err) } }
說(shuō)明:調(diào)用InitWeb()函數(shù)時(shí)可以指定一個(gè)配置文件,若沒(méi)有指定配置文件,則使用缺省的配置文件:./app.conf。
獲取業(yè)務(wù)參數(shù)
調(diào)用InitWeb()后wego會(huì)自動(dòng)將系統(tǒng)參數(shù)解析到WebEngine.Config中,業(yè)務(wù)參數(shù)則需要用戶自己調(diào)用配置數(shù)據(jù)的GetXXX函數(shù)來(lái)獲取。例如:
func main() { web, err := wego.InitWeb() if err != nil{ log.Error(err) return } mysql_cnn := web.Config.GetString("mysql") if mysql_cnn.Error != nil { log.Error(mysql_cnn.Error) return } log.Info(mysql_cnn.Value) err = web.Run() if err != nil { log.Error(err) } }
使用Session
- 首選定義配置文件:
#應(yīng)用名稱 app_name = demo [server] #http監(jiān)聽(tīng)端口 http_port = 8080 [session] #session 是否開(kāi)啟 session_on = true #session類型:cookie、cache session_store=cookie #客戶端的cookie的名稱 cookie_name = "wego" #session 過(guò)期時(shí)間, 單位秒 life_time = 3600 #session數(shù)據(jù)的hash字符串 hash_key = demohash
- 然后在入口函數(shù)中加載配置文件
func main() { web, err := wego.NewWeb() if err != nil{ log.Error(err) return } web.GET("/login", login) web.GET("/index", index) err = web.Run(":8080") if err != nil { log.Error(err) } }
- 然后再login處理器函數(shù)中保存session數(shù)據(jù):
func login(c *wego.WebContext) { c.Session.Set("uid", 1) c.Session.Save() c.Redirect(302, "/index") }
- 然后index處理器函數(shù)中就可以訪問(wèn)session數(shù)據(jù)了:
func index(c *wego.WebContext) { id , _ := c.Session.GetInt("uid") c.WriteTextF(200, "uid=%d", id) }
輸出日志
package main import log "wego/dlog" func main() { log.Debug("This is a Debug Message") log.Info("This is a Info Message") } //執(zhí)行后的輸出結(jié)果為: //2021/11/30 07:20:06 [D] main.go:31 This is a Debug Message //2021/11/30 07:20:06 [I] main.go:32 This is a Debug Info
