Beego Learn Note
示例環境在Deepin系統下。
deepin 15.9.3
├── Beego : 1.11.2
├── GoVersion : go1.12.4
├── GOOS : linux
├── GOARCH : amd64
├── NumCPU : 1
├── GOPATH : /home/jehorn/workspace/go
├── GOROOT : /usr/local/go
├── Compiler : gc
└── Date : Saturday, 27 Apr 2019
Linux下配置Go開發環境
首先從Go官網下載對應的壓縮包。
下載完畢后解壓,然后移動至/usr/local
下:
sudo mv go /usr/local/
然后配置環境變量:
sudo vim /etc/profile
在結尾添加(其中GOPATH
請替換自己的路徑):
export GOROOT=/usr/local/go
export GOARCH=amd64
export GOOS=linux
export GOPATH=/home/jehorn/workspace/go
export GOBIN=$GOROOT/bin
export PATH=$GOPATH/bin:$GOROOT/bin:$PATH
export PATH=$GOPATH/bin:$PATH
然后執行
source /etc/profile
控制台輸出go version
有版本號輸出即配置完成。
安裝beego:
到GOPATH
目錄下,執行:
go get github.com/astaxie/beego
go get github.com/beego/bee
執行bee version
看到版本號即安裝成功。
執行bee new demo
,即可新建一個項目:
jehorn@jehorn-PC:~/workspace/go/src/demo$ tree
.
├── conf
│ └── app.conf
├── controllers
│ └── default.go
├── main.go
├── models
├── routers
│ └── router.go
├── static
│ ├── css
│ ├── img
│ └── js
│ └── reload.min.js
├── tests
│ └── default_test.go
└── views
└── index.tpl
10 directories, 7 files
Linux下IDE配置
安裝VSCode。
然后安裝go
插件。
然后打開File
-preferences
-settings
,在右上角點開擴展菜單,選擇Open settings.json
,然后在右側的USER SETTINGS
中輸入:
"go.buildOnSave": "workspace",
"go.lintOnSave": "package",
"go.vetOnSave": "package",
"go.buildTags": "",
"go.buildFlags": [],
"go.lintFlags": [],
"go.vetFlags": [],
"go.coverOnSave": false,
"go.useCodeSnippetsOnFunctionSuggest": false,
"go.formatOnSave": true,
"go.formatTool": "goreturns",
"go.goroot": "/usr/local/go",
"go.gopath": "/home/jehorn/workspace/go"
保存,然后就可以打開項目。
項目打開以后,可能會有一些包提示你安裝,直接點擊install
即可。
beego項目運行原理
在$GOPATH/src/demo/
目錄下,命令行運行bee run
,然后打開瀏覽器localhost:8080
可以看到運行的beego項目。
ORM
ORM創建
Object Relation Mapping(對象關系映射)。
通過結構體對象來操作對應的數據庫表。
可以生成結構體相對應的數據庫表。
安裝:
go get github.com/astaxie/beego/orm
安裝完成之后,在models文件夾新建一個實體 user.go
:
package models
import (
"github.com/astaxie/beego/orm"
_ "github.com/go-sql-driver/mysql"
)
type User struct {
Id int
Name string
Pwd string
}
func init() {
// 鏈接數據庫
orm.RegisterDataBase("default", "mysql", "root:123456@tcp(127.0.0.1:3306)/demo?charset=utf8")
// 映射model數據(new(Type)...)
orm.RegisterModel(new(User))
// 生成表(別名, 是否強制更新, 是否可見)
orm.RunSyncdb("default", false, true)
}
然后在main.go
中調用init()
方法:
package main
import (
_ "demo/models"
...
)
...
最后在執行bee run
之前,先在mysql中創建一個數據庫:
create database demo;
-- Query OK, 1 row affected (0.02 sec)
執行bee run
:
C:\Users\Jehorn\Work\projects\Go\src\demo>bee run
______
| ___ \
| |_/ / ___ ___
| ___ \ / _ \ / _ \
| |_/ /| __/| __/
\____/ \___| \___| v1.10.0
2019/05/05 15:49:24 INFO ▶ 0001 Using 'demo' as 'appname'
2019/05/05 15:49:24 INFO ▶ 0002 Initializing watcher...
2019/05/05 15:49:27 SUCCESS ▶ 0003 Built Successfully!
2019/05/05 15:49:27 INFO ▶ 0004 Restarting 'demo.exe'...
2019/05/05 15:49:27 SUCCESS ▶ 0005 './demo.exe' is running...
create table `user`
-- --------------------------------------------------
-- Table Structure for `demo/models.User`
-- --------------------------------------------------
CREATE TABLE IF NOT EXISTS `user` (
`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
`name` varchar(255) NOT NULL DEFAULT '' ,
`pwd` varchar(255) NOT NULL DEFAULT ''
) ENGINE=InnoDB;
2019/05/05 15:49:28.353 [I] [asm_amd64.s:1333] http server Running on http://:8080
到數據庫中查看創建結果:
use demo;
desc user;
注:“civ”為數據庫名稱。
ORM增
核心代碼:
o := orm.NewOrm()
u := User{}
_, err := o.Insert(&u)
改造項目:
- 為了方便前后端分離,首先我們需要配置CORS來實現跨域:
在main.go
中引入github.com/astaxie/beego/plugins/cors
包:
package main
import (
_ "civ/models"
_ "civ/routers"
"github.com/astaxie/beego"
"github.com/astaxie/beego/plugins/cors"
)
func main() {
beego.InsertFilter("*", beego.BeforeRouter, cors.Allow(&cors.Options{
//允許訪問所有源
AllowAllOrigins: true,
//可選參數"GET", "POST", "PUT", "DELETE", "OPTIONS" (*為所有)
//其中Options跨域復雜請求預檢
AllowMethods: []string{"*"},
//指的是允許的Header的種類
AllowHeaders: []string{"*"},
//公開的HTTP標頭列表
ExposeHeaders: []string{"Content-Length"},
}))
beego.Run()
}
- 為了方便查看API,我們使用API自動化文檔:
首先在routers/router.go
文件最頂端添加注釋:
// @APIVersion 1.0.0
// @Title DEMO API
// @Description Demo APIs.
// @Contact xxx@gmail.com
package routers
...
然后在controllers/user.go
中,給UserController
增加注釋:
package controllers
import ...
// User APIs
type UserController struct {
beego.Controller
}
然后修改conf/app.conf
文件,添加:
EnableDocs = true
然后在具體的接口上填寫注釋。到時見下一步的具體的接口實現。
最后,運行bee run
的時候添加幾個參數:
bee run -gendoc=true -downdoc=true
編譯完成后會在當前項目文件夾下生成swagger
目錄,部署這個目錄,然后在瀏覽器打開即可看到生成的swagger api 文檔。
- 按照MVC代碼設計,首先我們在
models/user.go
為User
新增一個Add
方法:
package models
import (
"errors"
"github.com/astaxie/beego/orm"
"strings"
)
type User struct {
Id int
Name string
Pwd string
}
func (u User) Add(item User) error {
u.Name = strings.Trim(item.Name, " ")
u.Pwd = strings.Trim(item.Pwd, " ")
if u.Name == "" {
return errors.New("請輸入姓名")
}
if u.Pwd == "" || len(u.Pwd) < 3 {
return errors.New("請輸入長度大於等於3的密碼")
}
o := orm.NewOrm()
_, err := o.Insert(&u)
return err
}
然后在models
新增一個公共返回結構result.go
:
package models
type Code int32
const (
SUCCESS Code = iota // value --> 0
ERR_BIZ // value --> 1
ERR_DATA // value --> 2
ERR_AUTH // value --> 3
ERR_LOST // value --> 4
ERR_UNKNOW // value --> 5
)
func (c Code) String() string {
switch c {
case SUCCESS:
return "操作成功"
case ERR_BIZ:
return "業務操作失敗"
case ERR_DATA:
return "數據操作失敗"
case ERR_AUTH:
return "權限操作失敗"
case ERR_LOST:
return "操作不存在"
case ERR_UNKNOW:
return "未知錯誤200"
default:
return "未知錯誤"
}
}
type Result struct {
Code Code
Msg string
Data interface{}
}
然后在controllers
新增一個user.go
,同時在這里添加api注釋,以生成api文檔:
package controllers
import (
"civ/models"
"encoding/json"
"github.com/astaxie/beego"
)
type UserController struct {
beego.Controller
}
// @Title AddUser
// @Description Add users
// @Param user formData models.UserAddObj "The user list for add"
// @router /add [post]
func (c *UserController) Post() {
r := models.Result{}
usr := models.User{}
var err error
var arr []models.User
var errs []error
if err = json.Unmarshal(c.Ctx.Input.RequestBody, &arr); err == nil {
for _, item := range arr {
err := usr.Add(item)
if err != nil {
errs = append(errs, err)
}
}
r.Data = nil
r.Msg = "新增用戶成功"
r.Code = models.SUCCESS
if len(errs) > 0 {
r.Data = nil
r.Msg = errs[0].Error()
r.Code = models.ERR_DATA
}
} else {
r.Data = nil
r.Msg = err.Error()
r.Code = models.ERR_BIZ
}
c.Data["json"] = r
c.ServeJSON()
}
然后在routers/router.go
中,添加/user
路由:
// @APIVersion 1.0.0
// @Title DEMO API
// @Description Demo APIs.
// @Contact xxx@gmail.com
package routers
import (
"civ/controllers"
"github.com/astaxie/beego"
)
func init() {
ns := beego.NewNamespace("/v1",
beego.NSNamespace("/",
beego.NSInclude(
&controllers.MainController{},
),
),
beego.NSNamespace("/user",
beego.NSInclude(
&controllers.UserController{},
),
),
)
beego.AddNamespace(ns)
}
由於我們要在UserController
中訪問Request Body
,需要在conf/app.conf
中添加:
copyrequestbody = true
至此服務端就算是完成,然后是前端提交表單代碼,這里使用ajax提交:
...
<body>
<div>
姓名:<input type="text" name="r2name">
密碼:<input type="password" name="r2pwd">
<button type="button" id="r2b">請求user接口並插入上面的數據</button>
</div>
<script src="./node_modules/jquery/dist/jquery.js"></script>
<script type="text/javascript">
$(document).ready(() => {
$('#r2b').on('click', function () {
new BeegoRequests().r2();
});
});
// ajax請求簡單封裝
class Request {
constructor() {
this.DEFAULT = {
host: 'http://localhost:8080/v1',
url: '/',
type: 'POST',
data: ''
};
}
DEFAULT;
r(option = {}) {
const opt = Object.assign(this.DEFAULT, option);
return new Promise((resolve, reject) => {
let data = opt.data;
if (opt.type.toUpperCase() === 'POST')
data = JSON.stringify(data);
$.ajax({
url: opt.host + opt.url,
type: opt.type,
data: data,
success(res) {
resolve(res);
},
error(err) {
reject(err);
}
});
});
}
}
class BeegoRequests extends Request {
constructor() {
super();
}
r2() {
const name = $('input[name="r2name"]').val();
const pwd = $('input[name="r2pwd"]').val();
const data = [{ name: name, pwd: pwd }];
this.r({
url: '/user/add',
data: data
}).then(res => {
console.log(res);
}).catch(err => {
});
}
}
</script>
</body>
ORM查
核心代碼:
o := orm.NewOrm()
qs := o.QueryTable("user")
_, err := qs.Filter("name__icontains", strings.Trim(name, " ")).All(&list)
實現過程:
簡單實現一個根據name模糊查詢的接口:
首先在models/user.go
中新增一個List
方法:
func (u User) List(name string) ([]User, error) {
var list []User
o := orm.NewOrm()
qs := o.QueryTable("user")
_, err := qs.Filter("name__icontains", strings.Trim(name, " ")).All(&list)
return list, err
}
然后在controllers/user.go
里新增一個List
方法:
// @Title GetUserList
// @Description Get user list
// @Param name query string "The filter key of Name"
// @router /list [get]
func (c *UserController) List() {
r := models.Result{}
usr := models.User{}
name := c.GetString("name")
userList, err := usr.List(name)
r.Data = userList
r.Code = models.SUCCESS
r.Msg = "查詢成功"
if err != nil {
r.Data = nil
r.Code = models.ERR_DATA
r.Msg = "查詢用戶不存在"
}
c.Data["json"] = r
c.ServeJSON()
}
至此服務端完成,然后前端:
<html>
...
<body>
<div>
查詢姓名:<input type="text" name="r3name">
<button type="button" id="r3b">根據姓名獲取用戶列表</button>
</div>
<script src="./node_modules/jquery/dist/jquery.js"></script>
<script type="text/javascript">
$(document).ready(() => {
$('#r3b').on('click', function () {
new BeegoRequests().r3();
});
});
class Request {
...
}
class BeegoRequests extends Request {
...
r3() {
const name = $('input[name="r3name"]').val();
this.r({
type: 'GET',
url: '/user/list',
data: {
name: name
}
}).then(res => {
console.log(res);
}).catch(err => {
});
}
}
</script>
</body>
</html>