beego是一個快速開發GO應用的http框架,做者是go語言方向的大牛,astaxie。beego能夠用來快速開發API、web、後端服務等應用,是一個RESTFul風格的框架,主要的設計靈感來自於Python web開發框架tornado、flask、sinstra,很好的結合了Go語言自己的一些特性(interface,struct繼承等)。html
beego是基於八大獨立模塊來實現的,很好的實現了模塊間的解耦,即便用戶不使用http的邏輯,也能夠很好的使用其中的各個模塊。做者本身說,他的這種思想來自於樂高積木,設計beego的時候,這些模塊就是積木,而最終搭建好的機器人就是beego。mysql
這篇博文經過使用beego來構建API,講解實現過程當中的細節以及遇到的一些坑,讓咱們立刻開始beego的API構建之旅吧!git
進入到你的$GOPATH/src 安裝beego開發包本身快速開發工具bee
github
go get github.com/astaxie/beego
go get github.com/astaxie/beego/orm
go get github.com/beego/bee
複製代碼
使用快速開發工具bee,建立咱們的API項目web
bee new firstAPI
複製代碼
咱們獲得的項目結構以下圖所示:sql
能夠看出這是一個典型的MVC架構的應用,beego把咱們項目所須要的一些都準備好了,例如配置文件conf,測試文件tests等,咱們只須要專一於API代碼的編寫便可。shell
運行項目並得到API自動化文檔數據庫
bee run -gendoc=true -downdoc=true
複製代碼
運行上述代碼輸出以下圖所示:json
咱們在瀏覽器中訪問:本機IP:8080/swagger
,就會看到swagger的API文檔,咱們代碼更新後,該文檔就會自動更新,很是方便。flask
對 數據庫object 操做有四個方法Read / Insert / Update / Delete
示例代碼:
o := orm.NewOrm()
user := new(User)
user.Name = "slene"
fmt.Println(o.Insert(user))
user.Name = "Your"
fmt.Println(o.Update(user))
fmt.Println(o.Read(user))
fmt.Println(o.Delete(user))
複製代碼
還有其餘的方法能夠參閱beego官方文檔,裏面對orm操做有着詳細的介紹。
建立一個數據庫並設計一張數據庫表
CREATE TABLE IF NOT EXISTS `student` (
`Id` int(11),
`Name` varchar(255),
`Birthdate` varchar(255),
`Gender` bool,
`Score` int(11)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
複製代碼
在models文件夾下新建一個文件Student.go,並實現如下代碼,代碼中關鍵點都有註釋 package models
import (
"fmt"
"github.com/astaxie/beego/orm"
)
複製代碼
//在models模塊中建立一個struct,目的是使用beego的orm框架,使struct與數據庫中的字段產生對應關係
type Student struct {
Id int`orm:"column(Id)"` //column()括號中的字段就是在定義數據庫時的相應字段,這一段必須嚴格填寫,否則在API讀寫數據時就會出現讀不到或者寫不進去的問題
Name string `orm:"column(Name)"`
BirthDate string `orm:"column(Birthdate)"`
Gender bool `orm:"column(Gender)"`
Score int `orm:"column(Score)"`
}
//該函數得到數據庫中全部student的信息,返回值是一個結構體數組指針
func GetAllStudents() []*Student {
o := orm.NewOrm() //產生一個orm對象
o.Using("default") //這句話的意思是使用定義的默認數據庫,與main.go中的orm.RegisterDataBase()對應
var students []*Student //定義指向結構體數組的指針
q := o.QueryTable("student")//得到一個數據庫表的請求
q.All(&students)//取到這個表中的全部數據
return students
}
//該函數根據student中的Id,返回該學生的信息
func GetStudentById(id int) Student {
u := Student{Id:id}//根據所傳入的Id獲得對應student的對象
o := orm.NewOrm()//new 一個orm對象
o.Using("default")//使用最開始定義的default數據庫
err := o.Read(&u)//讀取Id=id的student的信息
if err == orm.ErrNoRows {
fmt.Println("查詢不到")//對應操做,不必定是print
} else if err == orm.ErrMissPK {
fmt.Println("沒有主鍵")
}
return u
}
//添加一個學生的信息到數據庫中,參數是指向student結構題的指針
func AddStudent(student *Student) Student {
o := orm.NewOrm()
o.Using("default")
o.Insert(student)//插入數據庫
return *student
}
func UpdateStudent(student *Student) {
o := orm.NewOrm()
o.Using("default")
o.Update(student)//更新該student的信息
}
func DeleteStudent(id int) {
o := orm.NewOrm()
o.Using("default")
o.Delete(&Student{Id:id})//刪除對應id的student的信息
}
func init() {
orm.RegisterModel(new(Student))//將數據庫註冊到orm
}
複製代碼
model這一層主要是定義struct,併爲上層編寫讀寫數據庫。處理數據的代碼。
基於 beego 的 Controller 設計,只須要匿名組合 beego.Controller
就能夠了,以下所示:
type xxxController struct {
beego.Controller
}
beego.Controller 實現了接口 beego.ControllerInterface,beego.ControllerInterface 定義了以下函數:
Init(ct *context.Context, childName string, app interface{})
複製代碼
這個函數主要初始化了 Context、相應的 Controller 名稱,模板名,初始化模板參數的容器 Data,app 即爲當前執行的 Controller 的 reflecttype,這個 app 能夠用來執行子類的方法。
Prepare()
這個函數主要是爲了用戶擴展用的,這個函數會在下面定義的這些 Method 方法以前執行,用戶能夠重寫這個函數實現相似用戶驗證之類。
Get()
若是用戶請求的 HTTP Method 是 GET,那麼就執行該函數,默認是 405,用戶繼承的子 struct 中能夠實現了該方法以處理 Get 請求。
Post()
若是用戶請求的 HTTP Method 是 POST,那麼就執行該函數,默認是 405,用戶繼承的子 struct 中能夠實現了該方法以處理 Post 請求。
Delete()
若是用戶請求的 HTTP Method 是 DELETE,那麼就執行該函數,默認是 405,用戶繼承的子 struct 中能夠實現了該方法以處理 Delete 請求。
Put()
若是用戶請求的 HTTP Method 是 PUT,那麼就執行該函數,默認是 405,用戶繼承的子 struct 中能夠實現了該方法以處理 Put 請求.
Head()
若是用戶請求的 HTTP Method 是 HEAD,那麼就執行該函數,默認是 405,用戶繼承的子 struct 中能夠實現了該方法以處理 Head 請求。
Patch()
若是用戶請求的 HTTP Method 是 PATCH,那麼就執行該函數,默認是 405,用戶繼承的子 struct 中能夠實現了該方法以處理 Patch 請求.
Options()
若是用戶請求的HTTP Method是OPTIONS,那麼就執行該函數,默認是 405,用戶繼承的子 struct 中能夠實現了該方法以處理 Options 請求。
Finish()
這個函數是在執行完相應的 HTTP Method 方法以後執行的,默認是空,用戶能夠在子 struct 中重寫這個函數,執行例如數據庫關閉,清理數據之類的工做。
Render() error
這個函數主要用來實現渲染模板,若是 beego.AutoRender 爲 true 的狀況下才會執行。
因此經過子 struct 的方法重寫,用戶就能夠實現本身的邏輯。
routers層實現 什麼是路由設置呢?前面介紹的 MVC 結構執行時,介紹過 beego 存在三種方式的路由:固定路由、正則路由、自動路由,與RESTFul API相關的就是固定路由和正則路由。
下面就是固定路由的例子
beego.Router("/", &controllers.MainController{})
beego.Router("/admin", &admin.UserController{})
beego.Router("/admin/index", &admin.ArticleController{})
beego.Router("/admin/addpkg", &admin.AddController{})
複製代碼
下面是正則路由的例子:
beego.Router(「/api/?:id」, &controllers.RController{})
複製代碼
默認匹配 //例如對於URL」/api/123」能夠匹配成功,此時變量」:id」值爲」123」
beego.Router(「/api/:id」, &controllers.RController{})
複製代碼
默認匹配 //例如對於URL」/api/123」能夠匹配成功,此時變量」:id」值爲」123」,但URL」/api/「匹配失敗
beego.Router(「/api/:id([0-9]+)「, &controllers.RController{})
複製代碼
自定義正則匹配 //例如對於URL」/api/123」能夠匹配成功,此時變量」:id」值爲」123」
beego.Router(「/user/:username([\w]+)「, &controllers.RController{})
正則字符串匹配 //例如對於URL」/user/astaxie」能夠匹配成功,此時變量」:username」值爲」astaxie」
複製代碼
beego.Router(「/download/.」, &controllers.RController{})
*匹配方式 //例如對於URL」/download/file/api.xml」能夠匹配成功,此時變量」:path」值爲」file/api」, 「:ext」值爲」xml」
beego.Router(「/download/ceshi/*「, &controllers.RController{})
複製代碼
*全匹配方式 //例如對於URL」/download/ceshi/file/api.json」能夠匹配成功,此時變量」:splat」值爲」file/api.json」
beego.Router(「/:id:int」, &controllers.RController{})
複製代碼
int 類型設置方式,匹配 :id爲int 類型,框架幫你實現了正則 ([0-9]+)
beego.Router(「/:hi:string」, &controllers.RController{})
複製代碼
string 類型設置方式,匹配 :hi 爲 string 類型。框架幫你實現了正則 ([\w]+)
beego.Router(「/cms_:id([0-9]+).html」, &controllers.CmsController{})
複製代碼
帶有前綴的自定義正則 //匹配 :id 爲正則類型。匹配 cms_123.html 這樣的 url :id = 123
我的以爲,最方便的仍是相似於Python框架flask的註解路由,也是在這個項目中使用的:
在routers/routers.go裏面添加你所但願的API
package routers
import (
"firstAPI/controllers"
"github.com/astaxie/beego"
)
func init() {
ns := beego.NewNamespace("/v1",
beego.NSNamespace("/object",
beego.NSInclude(
&controllers.ObjectController{},
),
),
beego.NSNamespace("/user",
beego.NSInclude(
&controllers.UserController{},
),
),
beego.NSNamespace("/student",
beego.NSInclude(
&controllers.StudentController{},
),
),
)
beego.AddNamespace(ns)
}
複製代碼
以上代碼實現了以下的API:
/v1/object
/v1/user
/v1/student
複製代碼
很是清晰明瞭。
main.go的數據庫配置
package main
import (
_ "firstAPI/routers"
"github.com/astaxie/beego"
"github.com/astaxie/beego/orm"
_ "github.com/go-sql-driver/mysql"
)
func init() {
orm.RegisterDriver("mysql", orm.DRMySQL)//註冊MySQL的driver
orm.RegisterDataBase("default", "mysql", "root:test@tcp(127.0.0.1:3306)/restapi_test?charset=utf8")//本地數據庫的帳號。密碼等
orm.RunSyncdb("default", false, true)
}
func main() {
if beego.BConfig.RunMode == "dev" {
beego.BConfig.WebConfig.DirectoryIndex = true
beego.BConfig.WebConfig.StaticDir["/swagger"] = "swagger"//靜態文檔
}
beego.Run()
}
複製代碼
關鍵點都在代碼中以註釋的形式展示。
bee run 運行代碼後,咱們使用postman測試一下咱們所構建的API效果如何。
這裏節省篇幅,只測試一個接口。
到此爲止,咱們基於beego就實現了簡單API接口的構建,是否是既清晰又簡單呢?趕快本身動手試試吧!
代碼已上傳到GitHub,能夠bee run
一下,Happy Coding!