beego入門筆記

Beego Learn Note

示例環境在Deepin系統下。javascript

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下:css

sudo mv go /usr/local/

而後配置環境變量:html

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

而後執行java

source /etc/profile

控制檯輸出go version有版本號輸出即配置完成。node


安裝beego:mysql

GOPATH目錄下,執行:jquery

go get github.com/astaxie/beego
go get github.com/beego/bee

執行bee version看到版本號即安裝成功。linux


執行bee new demo,便可新建一個項目:git

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項目。

sequenceDiagram Browser->>Server: http:localhost:8080 Server->>Server: Main.go Server->>Server: router.Init() Server->>Server: Controller.Get() Server->>Server: View Server-->>Browser: index.tpl

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)

改造項目:

  1. 爲了方便先後端分離,首先咱們須要配置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()
}
  1. 爲了方便查看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 文檔。

  1. 按照MVC代碼設計,首先咱們在models/user.goUser新增一個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>

這裏只是我的入門過程,更多內容參閱beego官方文檔 源碼地址參見Github

相關文章
相關標籤/搜索