Beego:簡約 & 強大並存的 Go 應用框架

EAWorld發表於2020-04-06

Beego:簡約 & 強大並存的 Go 應用框架

轉載本文需註明出處:微信公眾號EAWorld,違者必究。

引言:

Beego 是一個快速開發 Go 應用的 HTTP 框架,他可以用來快速開發 API、Web 及後端服務等各種應用,是一個 RESTful 的框架,主要設計靈感來源於 tornado、sinatra 和 flask 這三個框架,但是結合了 Go 本身的一些特性(interface、struct 嵌入等)而設計的一個框架。

目錄:

1. Beego框架架構介紹

2. Beego框架專案結構

3. Beego框架優勢

1.  Beego框架架構介紹

介紹beego框架之前先來了解下Go語言吧。
Go 是一個開源的程式語言,它能讓構造簡單、可靠且高效的軟體變得容易。
Go是從2007年末由Robert Griesemer, Rob Pike, Ken Thompson主持開發,後來還加入了Ian Lance Taylor, Russ Cox等人,並最終於2009年11月開源,在2012年早些時候釋出了Go 1穩定版本。現在Go的開發已經是完全開放的,並且擁有一個活躍的社群。
Go 語言被設計成一門應用於搭載 Web 伺服器,儲存叢集或類似用途的巨型中央伺服器的系統程式語言。
對於高效能分散式系統領域而言,Go 語言無疑比大多數其它語言有著更高的開發效率。它提供了海量並行的支援,這對於遊戲服務端的開發而言是再好不過了。
Golang安裝和使用請參考https://golang.google.cn/doc/
什麼是Beego?
Beego 是一個快速開發 Go 應用的 HTTP 框架,他可以用來快速開發 API、Web 及後端服務等各種應用,是一個 RESTful 的框架,主要設計靈感來源於 tornado、sinatra 和 flask 這三個框架,但是結合了 Go 本身的一些特性(interface、struct 嵌入等)而設計的一個框架。
Beego:簡約 & 強大並存的 Go 應用框架
Beego是基於八大獨立的模組之上構建的,是一個高度解耦的框架。當初設計Beego的時候就是考慮功能模組化,使用者即使不使用Beego的http邏輯,也是可以使用其他獨立模組,例如你可以使用cache模組來做你的快取邏輯,使用logs模組來記錄你的操作資訊,使用config模組來解析你各種格式的檔案,使用orm運算元據庫等。各個模組就類似積木,堆積起來就是功能強大的Beego框架。




Beego:簡約 & 強大並存的 Go 應用框架

執行邏輯可以拆分以下幾段:

1. main檔案監聽啟動埠接收請求。

2. 請求經過路由和引數過濾功能轉發給繫結url的controller處理。
3. Controller可呼叫輔助工具包、model、session管理、日誌處理、快取處理模組進行相應的業務處理。其中model(orm)直接運算元據庫。
4. 業務處理完成,返回響應或檢視給請求方。

2. Beego框架專案結構

最小的Beego專案
package main
 
import (
    "github.com/astaxie/beego"  //匯入beego依賴
)
 
type MainController struct {
    beego.Controller    //匿名包含beego.Controller
}
 
func (this *MainController) Get() {
    this.Ctx.WriteString("hello world")  //實現get響應
}
 
func main() {
    beego.Router("/", &MainController{})  //設定路由
    beego.Run()   //啟動Beego       
}

把上面的程式碼儲存為main.go,然後通過命令列進行編譯並執行:

$ go build main.go
$ ./hello
啟動之後開啟http://127.0.0.1:8080瀏覽器顯示“hello world”
程式碼詳解:
1、首先引入了包github.com/astaxie/beego, beego包中會初始化一個BeeAPP的應用,初始化一些引數。
2、定義Controller,這裡定義了一個struct為MainController,充分利用了Go語言的組合的概念,匿名包含了beego.Controller,這樣MainController就擁有了beego.Controller的所有方法。
3、定義RESTFul方法,通過匿名組合之後,MainController已經擁有了Get、Post、Delete、Put等方法,這些方法是分別用來對應使用者請求的Method函式,如果使用者發起的是POST請求,那麼就執行Post函式。所以這裡我們定義了MainController的Get方法用來重寫繼承的Get函式,這樣當使用者GET請求的時候就會執行該函式。
4、定義main函式,所有的Go應用程式和C語言一樣都是Main函式作為入口,所以這裡定義應用的入口。
5、Router註冊路由,路由就是告訴beego,當使用者來請求的時候,該如何去呼叫相應的Controller,這裡註冊了請求/的時候,請求到MainController。需注意,Router函式的兩個引數函式,第一個是路徑,第二個是Controller的指標。
6、Run應用,內部監聽了8080埠:Go預設情況會監聽你本機所有的IP上面的8080埠。
安裝beego
go get github.com/astaxie/beego
bee 工具是一個為了協助快速開發 beego 專案而建立的專案,通過 bee 您可以很容易的進行 beego 專案的建立、熱編譯、開發、測試、和部署。go get github.com/beego/bee
當我們安裝好bee之後,bee命令預設是放在GOPATH/bin裡面,所以需要把GOPATH/bin裡面,所以需要把GOPATH/bin 新增到您的環境變數中。
bee常用的命令:
bee new <專案名> :建立一個專案,這樣的專案一般是web專案
需要注意的是這個命令須在 $GOPATH/src 下執行。
Beego目錄結構
├── conf           //配置檔案
│   └── app.conf
├── controllers    //控制器
│   ├── admin
│   └── default.go
├── main.go        //專案入口
├── models         //模型   
│   └── models.go
├── routers       //路由
│   └──router.go
├── static         //靜態檔案
│   ├── css
│   ├── ico
│   ├── img
│   └── js
└── views          //介面模板
    ├── admin
    └── index.tpl
Beego框架是一個典型的mvc框架。M(models 目錄)、V(views 目錄)和 C(controllers 目錄)的結構。

路由設定

Beego:簡約 & 強大並存的 Go 應用框架

路由的主要功能是實現從請求地址到實現的方法,beego中封裝了Controller,所以路由是從路徑到ControllerInterface的過程,ControllerInterface的方法有如下:

type ControllerInterface interface {
Init(ct *Context, cn string)
Prepare()
Get()
Post()
Delete()
Put()
Head()
Patch()
Options()
Finish()
Render() error
}
這些方法beego.Controller都已經實現了,所以只要使用者定義struct的時候匿名包含就可以了。當然更靈活的方法就是使用者可以去自定義類似的方法,然後實現自己的邏輯。

使用者可以通過如下的方式進行路由設定:

beego.Router("/user", &controllers.UserController{})
beego.Router("/bill", &controllers.BillController{})
beego.Router("/log", &controllers.LogController{})

為了使用者更加方便的路由設定,beego參考了sinatra的路由實現,支援多種方式的路由:

beego.Router("/api/:id([0-9]+)", &controllers.RController{})
自定義正則匹配 //匹配 /api/123 :id= 123
beego.Router("/news/:all", &controllers.RController{})
全匹配方式 //匹配 /news/path/to/123.html :all= path/to/123.html
beego.Router("/user/:username([\w]+)", &controllers.RController{})
正則字串匹配 //匹配 /user/astaxie :username = astaxie
beego.Router("/download/*.*", &controllers.RController{})
*匹配方式 //匹配 /download/file/api.xml :path= file/api :ext=xml
beego.Router("/download/ceshi/*", &controllers.RController{})
*全匹配方式 //匹配 /download/ceshi/file/api.json :splat=file/api.json
beego.Router("/int", &controllers.RController{})
int型別設定方式 //匹配 :id為int型別,框架幫你實現了正則([0-9]+)
beego.Router("/:hi:string", &controllers.RController{})
string型別設定方式 //匹配 :hi為string型別。框架幫你實現了正則([\w]+)

Controller設定

beego.Controller實現了介面beego.ControllerInterface,beego.ControllerInterface定義瞭如下函式:

type ControllerInterface interface {
    Init(ct *Context, cn string)
    Prepare()
    Get()
    Post()
    Delete()
    Put()
    Head()
    Patch()
    Options()
    Finish()
    Render() error
}
Init(ct *Context, cn string)
這個函式主要初始化了Context、相應的Controller名稱,模板名,初始化模板引數的容器Data
Prepare()
這個函式主要是為了使用者擴充套件用的,這個函式會在下面定義的這些Method方法之前執行,使用者可以重寫這個函式實現類似使用者驗證之類。
Get()
如果使用者請求的HTTP Method是GET, 那麼就執行該函式,預設是403,使用者繼承的子struct中可以實現了該方法以處理Get請求.
Post()
如果使用者請求的HTTP Method是POST, 那麼就執行該函式,預設是403,使用者繼承的子struct中可以實現了該方法以處理Post請求.
Delete()
如果使用者請求的HTTP Method是DELETE, 那麼就執行該函式,預設是403,使用者繼承的子struct中可以實現了該方法以處理Delete請求.
Put()
如果使用者請求的HTTP Method是PUT, 那麼就執行該函式,預設是403,使用者繼承的子struct中可以實現了該方法以處理Put請求.
Head()
如果使用者請求的HTTP Method是HEAD, 那麼就執行該函式,預設是403,使用者繼承的子struct中可以實現了該方法以處理Head請求.
Patch()
如果使用者請求的HTTP Method是PATCH, 那麼就執行該函式,預設是403,使用者繼承的子struct中可以實現了該方法以處理Patch請求.
Options()
如果使用者請求的HTTP Method是OPTIONS, 那麼就執行該函式,預設是403,使用者繼承的子struct中可以實現了該方法以處理Options請求.
Finish()
這個函式實在執行完相應的http Method方法之後執行的,預設是空,使用者可以在子Strcut中重寫這個函式,執行例如資料庫關閉,清理資料之類的工作。
Render() error
這個函式主要用來實現渲染模板,如果beego.AutoRender為true的情況下才會執行。
Session模組
Beego內建了session模組,目前session模組支援的後端引擎包括memory、file、mysql、redis四中,使用者也可以根據相應的interface實現自己的引擎。
Beego中使用session相當方便,只要在main入口函式中設定如下:
beego.SessionOn = true

或者通過配置檔案配置如下:

sessionon = true

session有幾個方便的方法:

SetSession(name string, value interface{})
GetSession(name string) interface{}
DelSession(name string)

例子:

func (this *MainController) Get() {
    v := this.GetSession("asta")
    if v == nil {
        this.SetSession("asta", int(1))
        this.Data["num"] = 0
    } else {
        this.SetSession("asta", v.(int)+1)
        this.Data["num"] = v.(int)
    }
    this.TplNames = "index.tpl"
}
session操作主要有設定session、獲取session、刪除session。
當然你要可以通過下面的方式自己控制相應的邏輯這些邏輯:
sess:=this.StartSession()
defer sess.SessionRelease()

sess物件具有如下方法:

sess.Set()
sess.Get()
sess.Delete()
sess.SessionID()

但是我還是建議大家採用SetSession、GetSession、DelSession三個方法來操作,避免自己在操作的過程中資源沒釋放的問題。
關於Session模組使用中的一些引數設定:
SessionOn
設定是否開啟Session,預設是false,配置檔案對應的引數名:sessionon
SessionProvider
設定Session的引擎,預設是memory,目前支援還有file、mysql、redis等,配置檔案對應的引數名:sessionprovider
SessionName
設定cookies的名字,Session預設是儲存在使用者的瀏覽器cookies裡面的,預設名是beegosessionID,配置檔案對應的引數名是:sessionname
SessionGCMaxLifetime
設定Session過期的時間,預設值是3600秒,配置檔案對應的引數:sessiongcmaxlifetime
SessionSavePath
設定對應file、mysql、redis引擎的儲存路徑或者連結地址,預設值是空,配置檔案對應的引數:sessionsavepath

當SessionProvider為file時,SessionSavePath是隻儲存檔案的目錄,如下所示:

beego.SessionProvider = "file"
beego.SessionSavePath = "./tmp"

當SessionProvider為mysql時,SessionSavePath是連結地址,採用go-sql-driver,如下所示:

beego.SessionProvider = "mysql"
beego.SessionSavePath = "username:password@protocol(address)/dbname?param=value"

當SessionProvider為redis時,SessionSavePath是redis的連結地址,採用了redigo,如下所示:

beego.SessionProvider = "redis"
beego.SessionSavePath = "127.0.0.1:6379"
Cache模組
Beego內建了一個cache模組,實現了類似memcache的功能,快取資料在記憶體中。
通過beego.NewBeeCache初始化一個物件,然後設定過期時間,開啟過期檢測,在業務邏輯中就可以通過如下的介面進行增刪改的操作:
Get(name string) interface{}
Put(name string, value interface{}, expired int) error
Delete(name string) (ok bool, err error)
IsExist(name string) bool

例子:

var (
    urllist *beego.BeeCache
)
 
func init() {
    urllist = beego.NewBeeCache()
    urllist.Every = 0 //不過期
    urllist.Start()
}
 
func (this *ShortController) Post() {
    var result ShortResult
    longurl := this.Input().Get("longurl")
    beego.Info(longurl)
    result.UrlLong = longurl
    urlmd5 := models.GetMD5(longurl)
    beego.Info(urlmd5)
    if urllist.IsExist(urlmd5) {
        result.UrlShort = urllist.Get(urlmd5).(string)
    } else {
        result.UrlShort = models.Generate()
        err := urllist.Put(urlmd5, result.UrlShort, 0)
        if err != nil {
            beego.Info(err)
        }
        err = urllist.Put(result.UrlShort, longurl, 0)
        if err != nil {
            beego.Info(err)
        }
    }
    this.Data["json"] = result
    this.ServeJson()
}

日誌模組

Beego預設有一個初始化的BeeLogger物件輸出內容到stdout中,你可以通過如下的方式設定自己的輸出:
beego.SetLogger(*log.Logger)

可以通過下面的方式設定不同的日誌分級:
beego.SetLevel(beego.LevelError)

日誌等級的排序如下:LevelTrace、LevelDebug、LevelInfo、LevelWarning、 LevelError、LevelCritical

不同級別的log日誌函式:

Trace(v ...interface{})

Debug(v ...interface{})

Info(v ...interface{})

Warn(v ...interface{})

Error(v ...interface{})

Critical(v ...interface{})

例子:

fd,err := os.OpenFile("/var/log/beeapp/beeapp.log", os.O_RDWR|os.O_APPEND, 0644)
if err != nil {
    beego.Critical("openfile beeapp.log:", err)
    return
}
lg := log.New(fd, "", log.Ldate|log.Ltime)
beego.SetLogger(lg)
配置

beego支援解析ini檔案, beego預設會解析當前應用下的conf/app.conf檔案

通過這個檔案你可以初始化很多beego的預設引數:

appname = beepkg
httpaddr = "127.0.0.1"
httpport = 9090
runmode ="dev"
autorender = false
autorecover = false
viewspath = "myview"

你可以在配置檔案中配置應用需要用的一些配置資訊,例如下面所示的資料庫資訊:

mysqluser = "root"
mysqlpass = "rootpass"
mysqlurls = "127.0.0.1"
mysqldb = "beego"

那麼你就可以通過如下的方式獲取設定的配置資訊:

beego.AppConfig.String("mysqluser")
beego.AppConfig.String("mysqlpass")
beego.AppConfig.String("mysqlurls")
beego.AppConfig.String("mysqldb")

AppConfig支援如下方法:

Bool(key string) (bool, error)
Int(key string) (int, error)
Int64(key string) (int64, error)
Float(key string) (float64, error)
String(key string) string

ORM模組

目前beego-orm支援的資料有:

-MySQL:https://github.com/go-sql-driver/mysql

-PostgreSQL:https://github.com/lib/pq

-Sqlite3:https://github.com/mattn/go-sqlite

beego-orm的相關特性:

- 支援 Go 的所有型別儲存

- 輕鬆上手,採用簡單的 CRUD 風格

- 自動 Join 關聯表

- 跨資料庫相容查詢

- 允許直接使用 SQL 查詢/對映

- 嚴格完整的測試保證 ORM 的穩定與健壯

示例請參考beego官方:https://beego.me/docs/mvc/model/orm.md

3.Beego框架優勢


Beego:簡約 & 強大並存的 Go 應用框架

優點:

1)使用簡單:通過命令列建立beego專案;監控程式碼修改進行熱編譯;自動化測試程式碼以及自動化打包部署。

2)模組化:配置解析,快取操作,日誌記錄,效能監測,ORM模組,請求模擬,上下文操作,session。

3)智慧化:智慧監控,智慧router。可監控cpu、memory、goroutine,QPS

缺點:依賴庫多,不利於掌握

使用場景
Beego:簡約 & 強大並存的 Go 應用框架

1. 適合用作伺服器端開發,快速開發web服務,支援restful api。

2. 開發的後端服務可作為微服務的一部分,提供高併發的效能。

3. 可作為雲平臺的開發框架,目前國內很多雲平臺採用beego開發。

4. 開發的服務也可以用來進行分散式部署。

5. 可以開發高效能閘道器,提供高效路由功能。

6. 開發的服務支援生成docker映象,使用docker容器部署。

【小結】通過上述介紹,可以看出Beego框架使用簡單,快速開發非常方便,提供多個模組工具,智慧監控,智慧路由。依託於golang語言有著高效的效能,Beego可用於微服務、分散式、閘道器接入等場景開發,完全可以替代springboot進行專案快速開發。

【備註】本文參考自beego官網,地址:https://beego.me/docs/intro/

精選提問:

1:能列出下常用的框架和庫嗎?

答:go web框架:Beego Buffalo  Echo Gin Iris Revel;golang:常用庫請參考golang中文網:https://studygolang.com/articles/14828?fr=sidebar

問2:請問beego後續有計劃增加哪些新的特性麼?

答:目前來看,beego沒有新的特性推出,旨在bug維護和框架穩定性。

問3:這種框架和gin區別是什麼?優勢是什麼?beego本身整合了很多,有種大而全,卻不精,每個功能點cover住的場景有限,還不如藉助第三方來的高效,簡單。

答:(1)Beego支援完整的mvc,Gin不支援完整的mvc。

(2) 路由:Beego支援完整正則路由,Gin不支援。

(3) Beego在業務方面較Gin支援更多(Beego有多模組封裝,且支援單獨模組獨立使用,構建專案更加方便)

(4) Gin在效能方面較Beego更好(遇到效能瓶頸適合使用Gin)

誠然Beego在效能方面確實不能和Gin比,但是在複雜業務轉化為專案時更加方便,而Gin實現業務邏輯需要更多的程式碼和庫引用。根據具體業務和效能選擇適合自己的框架或庫。

問4能比較一下beego 和 go-restful 嗎?

答:go-resful功能單一旨在提供高效的路由分發和restful訪問,而此功能只是beego一個模組的功能,如果只是想單純的路由轉發和高的訪問效能,建議使用go-restful,如果專案有複雜的業務且符合mvc模型,建議使用beego。Beego:簡約 & 強大並存的 Go 應用框架

關於作者:十月,現任普元西安研發中心資深開發工程師,擅長Java、golang、大資料、雲端計算等領域技術;對公有云、混合雲、微服務架構有著濃厚的興趣。

關於EAWorld:微服務,DevOps,資料治理,移動架構原創技術分享

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31562043/viewspace-2665016/,如需轉載,請註明出處,否則將追究法律責任。

相關文章