beego框架使用

一,beego簡介

1,beego是一個go語言框架,可以用來快速開發(fā)API、Web、后端服務(wù)等各種應(yīng)用。
2,beego的安裝,包地址即源碼github地址,go get命令借助代碼管理工具如git通過遠(yuǎn)程拉取或更新代碼包及其依賴包,并自動完成編譯和安裝。
go get github.com/astaxie/beego
go get github.com/beego/bee
3,文件結(jié)構(gòu)及邏輯
beego在執(zhí)行邏輯上是一個典型的 MVC 架構(gòu):

image.png

二,beego流程及使用

通過使用bee工具的命令可以分別生成web和api兩種項(xiàng)目結(jié)構(gòu)

bee new myproject
bee api myapi

入口文件

  • 文件名可以隨意命名
  • 初始化路由配置,監(jiān)聽http請求

路由配置

  • 固定式路由 參數(shù):路徑,controller地址,函數(shù)方法名
package routers

import (
    "myapi/controllers"
    "github.com/astaxie/beego"
)

func init() {
    beego.Router("/", &controllers.MainController{})
    beego.Router("/v1/area/getArea", &controllers.AreaController{}, "post:GetArea")
}
  • 正則路由 正則匹配路徑及參數(shù)
beego.Router(“/api/:id([0-9]+)“, &controllers.RController{})

beego.Router(“/user/:username([\\w]+)“, &controllers.RController{})

  • 自動匹配路由

beego.AutoRouter(&controllers.ObjectController{})

/object/login   調(diào)用 ObjectController 中的 Login 方法
/object/logout  調(diào)用 ObjectController 中的 Logout 方法
  • 注解式路由 路由里使用namespace引入文件,函數(shù)方法的上方加上router注釋
    beego.Include(&CMSController{})
// CMS API
type CMSController struct {
    beego.Controller
}

// @router /staticblock [post]
func (this *CMSController) StaticBlock() {

}

控制器

  • 通過type struct結(jié)構(gòu)體引入實(shí)現(xiàn)了類似繼承的功能
type xxxController struct {
    beego.Controller
}
  • beego.Controller 實(shí)現(xiàn)了接口 beego.ControllerInterface 定義了如下函數(shù):
Init(ct *context.Context, childName string, app interface{})

這個函數(shù)主要初始化了 Context、相應(yīng)的 Controller 名稱,模板名,初始化模板參數(shù)的容器 Data 

Prepare() 這個函數(shù)主要是為了用戶擴(kuò)展用的,用戶可以重寫這個函數(shù)實(shí)現(xiàn)類似用戶驗(yàn)證之類。

Get() 如果用戶請求的 HTTP Method 是 GET, 處理 Get 請求。

Post() 如果用戶請求的 HTTP Method 是 POST, 處理 Post 請求。

Delete() 如果用戶請求的 HTTP Method 是 DELETE, 處理 Delete 請求。

Put() 如果用戶請求的 HTTP Method 是 PUT,處理 Put 請求.

Head() 如果用戶請求的 HTTP Method 是 HEAD, 處理 Head 請求。

Patch() 如果用戶請求的 HTTP Method 是 PATCH, 處理 Patch 請求.

Options() 如果用戶請求的HTTP Method是OPTIONS, 處理 Options 請求。

Finish() 這個函數(shù)是在執(zhí)行完相應(yīng)的 HTTP Method 方法之后執(zhí)行的,默認(rèn)是空, 執(zhí)行例如數(shù)據(jù)庫關(guān)閉,清理數(shù)據(jù)之類的工作。

Render() error 這個函數(shù)主要用來實(shí)現(xiàn)渲染模板,如果 beego.AutoRender 為 true 的情況下才會執(zhí)行。

模型orm

  • 默認(rèn)支持MySQL、PostgreSQL和Sqlite3 三種數(shù)據(jù)庫
  • 數(shù)據(jù)庫連接及增刪改查示例
func init() {
    // set default database
    orm.RegisterDataBase("default", "mysql", "username:password@tcp(127.0.0.1:3306)/db_name?charset=utf8", 30)
    // register model
    orm.RegisterModel(new(User))
    // create table
    orm.RunSyncdb("default", false, true)
}

func main() {
    o := orm.NewOrm()
    user := User{Name: "slene"}
    // insert
    id, err := o.Insert(&user)
    fmt.Printf("ID: %d, ERR: %v\n", id, err)
    // update
    user.Name = "astaxie"
    num, err := o.Update(&user)
    fmt.Printf("NUM: %d, ERR: %v\n", num, err)
    // read one
    u := User{Id: user.Id}
    err = o.Read(&u)
    fmt.Printf("ERR: %v\n", err)
    // delete
    num, err = o.Delete(&u)
    fmt.Printf("NUM: %d, ERR: %v\n", num, err)
}
  • 關(guān)聯(lián)查詢,關(guān)聯(lián)方式大體有三種,均需在tag注解中說明:
    1, 一對一orm:"rel(one)" 反向:orm:"reverse(one)"
    2, 一對多orm:"rel(fk)" 反向:orm:"reverse(many)"
    4, 多對多orm:"rel(m2m)" 反向:orm:"reverse(many)"
type Post struct {
    Id    int    `orm:"auto"`
    Title string `orm:"size(100)"`
    User  *User  `orm:"rel(fk)"`
}

var posts []*Post
qs := o.QueryTable("post")
num, err := qs.Filter("User__Name", "slene").All(&posts)

  • 原生sql查詢
var maps []orm.Params
num, err := o.Raw("SELECT * FROM user").Values(&maps)
for _,term := range maps{
    fmt.Println(term["id"],":",term["name"])
}
  • 事務(wù)處理
o.Begin()
...
user := User{Name: "slene"}
id, err := o.Insert(&user)
if err == nil {
    o.Commit()
} else {
    o.Rollback()
}
  • 高級查詢操作符
exact / iexact 等于
contains / icontains 包含
gt / gte 大于 / 大于等于
lt / lte 小于 / 小于等于
startswith / istartswith 以…起始
endswith / iendswith 以…結(jié)束
in
isnull
后面以 i 開頭的表示:大小寫不敏感
  • 高級查詢操作符示例:
qs.Filter("name__exact", "slene") // WHERE name = 'slene'
qs.Filter("name__contains", "slene") // WHERE name LIKE BINARY '%slene%'
ids:=[]int{17,18,19,20};  qs.Filter("age__in", ids) // WHERE age IN (17, 18, 19, 20)
qs.Filter("profile__age__gt", 17) // WHERE profile.age > 17
qs.Filter("name__startswith", "slene") // WHERE name LIKE BINARY 'slene%'
qs.Filter("profile__id__isnull", true) // WHERE profile_id IS NULL

//select示例
 orm1.QueryTable(TableName("user")).Filter("username__contains", m.Username).Limit(10, 0).OrderBy("-id").All(&users,"id","username");

// User 包裝了下面的查詢結(jié)果
type User struct {
    Id  int
    Username string
    Age  int
}
var users []User

// 獲取 QueryBuilder 對象. 需要指定數(shù)據(jù)庫驅(qū)動參數(shù)。
// 第二個返回值是錯誤對象,在這里略過
qb, _ := orm.NewQueryBuilder("mysql")

// 構(gòu)建查詢對象
qb.Select("a.id","a.username","b.birthday").
     From(TableName("user") + " as a").
     InnerJoin(TableName("user_profile") + " as b").On("a.id = b.user_id").
     Where("a.username like '"+ m.Username +"%'").
     OrderBy("a.id").Desc().
     Limit(10).Offset(0)

// 導(dǎo)出 SQL 語句
sql := qb.String()

// 執(zhí)行 SQL 語句
o := orm.NewOrm()
o.Raw(sql, 20).QueryRows(&users)

beego 模板語法

  • go 統(tǒng)一使用了 {{}} 作為左右標(biāo)簽,沒有其他的標(biāo)簽符號。如果您想要修改為其它符號,可以參考 模板標(biāo)簽
  • 使用 . 來訪問當(dāng)前位置的上下文
  • 數(shù)據(jù)輸出
func (this *MainController) Get() {
        this.Data["Website"] = "beego.me"
        this.Data["Email"] = "astaxie@gmail.com"
        this.TplName = "index.tpl"
}
  • if … else … end
{{if .IsHome}}
{{else}}
    {{if .IsAbout}}{{end}}
{{end}}
  • range … end
{{range .Pages}}
    {{.Num}} of {{$.Total}}
{{end}}
  • beego 中支持直接載入文件模板
    {{template "path/to/head.html" .}}

beego 單元測試

  • 只有唯一的參數(shù),必須是 t *testing.T 類型
  • 必須以單詞 Test 開頭,再組合上首字母大寫的單詞或詞組(一般是被測試的方法名稱,如 TestValidateClient)
  • 調(diào)用 t.Error 或者 t.Fail 方法指明測試失?。ㄟ@里我使用了 t.Errorf 來提供更多的細(xì)節(jié))
    t.Log 可以用來提供一些失敗信息以外的調(diào)試信息
  • 測試代碼文件名必須是 _test 結(jié)尾的形式 something_test.go ,例如:addtion_test.go

1,功能測試
go test user_test.go -v -run="TestGetUser"

// TestGetUser is a sample to run an endpoint test
func TestGetUser(t *testing.T) {

    param := map[string]string{
        "username": "a",
    }

    marshaled, _ := json.Marshal(param)
    r, err := http.NewRequest("Post", "/v1/user/GetUser", bytes.NewBuffer(marshaled))
    if err != nil {
        t.Fatalf("should get user success, but fails to send request, error:%s\n", err)
    }
    w := httptest.NewRecorder()
    beego.BeeApp.Handlers.ServeHTTP(w, r)

    beego.Trace("testing", "TestGetUser", "Code[%d]\n%s", w.Code, w.Body.String())

}

2,性能測試
go test user_test.go -v -bench="BenchmarkGetUser"

// BenchmarkGetUser 
func BenchmarkGetUser(b *testing.B) {

    b.ResetTimer()
 
    for i := 0; i < b.N; i++ {
        param := map[string]string{
            "username": "a",
        }

        marshaled, _ := json.Marshal(param)
        r, err := http.NewRequest("Post", "/v1/user/GetUser", bytes.NewBuffer(marshaled))
        if err != nil {
            b.Fatalf("should get user success, but fails to send request, error:%s\n", err)
        }
        w := httptest.NewRecorder()
        beego.BeeApp.Handlers.ServeHTTP(w, r)

        beego.Trace("testing", "TestGetUser", "Code[%d]\n%s", w.Code, w.Body.String())
    }
}

其他

1,import 導(dǎo)入包時,初始化init函數(shù)里用到,但是主體各函數(shù)里沒用到,引入包名左側(cè)要有個下劃線別名,否則會報錯,例如數(shù)據(jù)庫連接初始化

2, Go語言要求public的變量必須以大寫字母開頭,private變量則以小寫字母開頭, 函數(shù)名命名也遵循這個規(guī)則,否則小寫開頭的變量和函數(shù)名不能被外部訪問

3,JSON輸出的時候必須注意,只有導(dǎo)出的字段(首字母是大寫)才會被輸出,如果修改字段名,那么就會發(fā)現(xiàn)什么都不會輸出,所以必須通過struct tag(結(jié)構(gòu)體注解)定義來實(shí)現(xiàn)。針對JSON的輸出,我們在定義struct tag的時候需要注意的幾點(diǎn)是:

  • 字段的tag是"-",那么這個字段不會輸出到JSON
  • tag中帶有自定義名稱,那么這個自定義名稱會出現(xiàn)在JSON的字段名中
  • tag中如果帶有"omitempty"選項(xiàng),那么如果該字段值為空,就不會輸出到JSON串中
  • 如果字段類型是bool, string, int, int64等,而tag中帶有",string"選項(xiàng),那么這個字段在輸出到JSON的時候會把該字段對應(yīng)的值轉(zhuǎn)換成JSON字符串

4,Beego框架orm在執(zhí)行o.Insert(*p)插入數(shù)據(jù)時候需要傳入指針變量作為參數(shù),原因是因?yàn)樵诓迦氤晒?,會返回id給user

5,當(dāng)字段是指針類型時,如果沒有用orm:"-"進(jìn)行orm忽略,必須要添加標(biāo)簽來進(jìn)行表關(guān)系設(shè)置。

6,多個接口返回字段不一樣時,如果公用結(jié)構(gòu)體指針查詢的值,對輸出的字段不好增減控制,建議接口方法內(nèi)每次對接口輸出的字段自定義結(jié)構(gòu)體

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • beego orm是一個基于Go進(jìn)行ORM操作的庫,它采用了Go style方式對數(shù)據(jù)庫進(jìn)行操作,實(shí)現(xiàn)了struc...
    副班長國偉閱讀 2,164評論 2 5
  • 在開始學(xué)習(xí)beego的過濾器之前,說一個項(xiàng)目開發(fā)中遇到的一個bug,這個bug是hybris自己的,導(dǎo)致項(xiàng)目上線后...
    非典型_程序員閱讀 6,614評論 0 1
  • 今天主要來簡單學(xué)習(xí)一下beego,一個比較流行的go框架。前段時間學(xué)習(xí)了go語言的基礎(chǔ),対go算是有了一個簡單了解...
    非典型_程序員閱讀 34,136評論 1 12
  • Beego官網(wǎng)本身已經(jīng)整理的非常詳細(xì)了,但是作為一個學(xué)習(xí)者,我還是決定自己好好整理一下,這樣在后面使用的時候自己對...
    上下求索zsh閱讀 819評論 0 0
  • GoLang-Beego.Godep 介紹你是一個從PHP,Python,Ruby等動態(tài)語言轉(zhuǎn)移到Go的web應(yīng)用...
    燕京博士閱讀 1,288評論 0 3

友情鏈接更多精彩內(nèi)容