beego

beego 是一个快速开发 Go 运用的 HTTP 结构,他能够用来快速开发 API、Web 及后端服务等各种运用,是一个 RESTful 的结构,主要设计创意来源于 tornado、sinatra 和 flask 这三个结构,但是结合了 Go 本身的一些特性(interface、struct 嵌入等)而设计的一个结构。

为什么运用结构

上帝不行能让每一个人都满足,相同的,并不是一切人都喜欢结构,大概便是有三点吧,结构重,结构不灵敏,结构有坑。其实假如写一个hello world,肯定是用不到结构的。结构并不是有人对自己的一堆代码起了个姓名就叫结构了。如其说咱们运用结构,不如说咱们运用了一种标准,然后一切的开发人员一同遵守,另外一点便是开箱即用,解放开发人员,提高开发功率,还有结构提前弥补一些你可能疏忽的或者没想到的漏洞,比方安全问题,日志格局等等。

为什么选择beego

beego作为go言语的结构,其实是很适合phper入门学习的。听说beego的作者也是从PHP跨入go言语行列的,并且参阅了PHP的laravel结构的设计思维和目录设计。 相同的,和laravel有一样的通病,结构很重,都是追求大而全的思维,既然追求大而全,必定就舍弃了卓越的功能。咱们不如先看一下结构目录

拆箱phper最适合入门的go框架beego
很典型的MVC架构,最为phper一看就感到亲热而了解。有人说,PHP转go,只需要一周,3天看go语法,3天看beego结构,周末休息一天,周一就能够飞速的crud了。

东西模块

就像laravel的artisan,beego也供给了东西,便是bee,先来看一下bee有哪些指令吧

USAGE
    bee command [arguments]
AVAILABLE COMMANDS
    version     Prints the current Bee version 检查版别号
    migrate     Runs database migrations 数据库搬迁
    api         Creates a Beego API application 生成api结构
    bale        Transforms non-Go files to Go source files
    fix         Fixes your application by making it compatible with newer versions of Beego
    pro         Source code generator
    dev         Commands which used to help to develop beego and bee
    dlv         Start a debugging session using Delve
    dockerize   Generates a Dockerfile for your Beego application 经过生成Dockerfile文件完结运用docker化
    generate    Source code generator 主动化生成代码
    hprose      Creates an RPC application based on Hprose and Beego frameworks
    new         Creates a Beego application 创立一个项目
    pack        Compresses a Beego application into a single file 用来发布运用的时候打包,会把项目打包成 zip 包 mac上面打包linux 留意bee pack -be GOOS=linux
    rs          Run customized scripts
    run         Run the application by starting a local development server 在项目目录下履行编译项目
    server      serving static content over HTTP on port
    update      Update Bee 升级版别
Use bee help [command] for more information about a command.这就话很重要

快速入门

  • 安装go,下载地址点击下载
  • 设置GOROOT,GOPATH,PATH
 export GOROOT=/usr/local/go
 export GOPATH=/Users/goRoot:/Users/go
 export PATH=/usr/local/go/bin:/Users/goRoot/bin:$PATH
  • 安装好了,看一下版别
 $  go version
go version go1.17.8 darwin/amd64
  • 安装beego
go get -u github.com/astaxie/beego
go get -u github.com/beego/bee
  • 将GOPATH/bin参加$PATH中
$ echo 'export GOPATH="$HOME/go"' >> ~/.profile # 或者 ~/.zshrc, ~/.cshrc, 您所运用的sh对应的装备文件
# 假如您已经增加了 $GOPATH 变量
$ echo 'export PATH="$GOPATH/bin:$PATH"' >> ~/.profile # 或者 ~/.zshrc, ~/.cshrc, 您所运用的sh对应的装备文件
$ exec $SHELL
  • 上面操作结束,就能够运用bee了,快速创立一个bee-demo的项目
 bee new bee-demo

拆箱phper最适合入门的go框架beego

着手部分

  • 这儿为了更好的让我们了解,我不适用结构默许的,而是创立新的文件
  • 方才说过,bee generate 是主动生成代码,咱们来看看怎么运用吧
  • 先生成一个控制器
$  bee generate controller user
______
| ___ \
| |_/ /  ___   ___
| ___ \ / _ \ / _ \
| |_/ /|  __/|  __/
\____/  \___| \___| v2.0.2
2022/12/08 14:43:23 INFO     ▶ 0001 Using 'User' as controller name
2022/12/08 14:43:23 INFO     ▶ 0002 Using 'controllers' as package name
        create   /Users/zhangguofu/website/bee-demo/controllers/user.go
2022/12/08 14:43:23 SUCCESS  ▶ 0003 Controller successfully generated!

履行指令之后,咱们就会发现生成了一个RESTful的controller

拆箱phper最适合入门的go框架beego
那么咱们怎么让恳求路由到这个文件呢,咱们看一下main入口文件,发现有一行 _ "bee-demo/routers"说明 项目发动的时候会先初始化routers这个包,经过控制器和路由之间的映射关系,在项目发动时完结注册

  • 咱们新起一个路由文件,姓名叫web.go,并映射到方才生成的user控制器,假如不指定方法,默许走Get方法
    拆箱phper最适合入门的go框架beego

项目下运用bee run发动项目,默许是8080端口,咱们拜访/web/index看看


GET http://localhost:8080/web/index
HTTP/1.1 200 OK
Server: beegoServer:2.0.0
Date: Thu, 08 Dec 2022 08:06:50 GMT
Content-Length: 11
Content-Type: text/plain; charset=utf-8
hello world
Response code: 200 (OK); Time: 25ms; Content length: 11 bytes
  • 路由的第二种方法 咱们方才看到,在web.go路由文件里,有一行beego.Include(&controllers.UserController{}),那么咱们能否在控制器中声明路由呢,因为include方法里边也有一个addWithMethodParams操作,实际上也是注册了路由,比方在控制器中声明Hello方法,运用路由/web/hello拜访
// Hello @router /web/hello [get]
func (c *UserController) Hello() {
	c.Ctx.WriteString("i am Hello")
}

模板

假如是一个web运用,咱们怎么在模板赋值呢

  • 首要新建一个view
 $ bee generate view /user
create   /Users/zhangguofu/website/bee-demo/views/user/index.tpl
        create   /Users/zhangguofu/website/bee-demo/views/user/show.tpl
        create   /Users/zhangguofu/website/bee-demo/views/user/create.tpl
        create   /Users/zhangguofu/website/bee-demo/views/user/edit.tpl
  • 修改原来的Get方法
    拆箱phper最适合入门的go框架beego
  • 拜访
GET http://localhost:8080/web/index
HTTP/1.1 200 OK
Content-Length: 4
Content-Type: text/html; charset=utf-8
Server: beegoServer:2.0.0
Date: Thu, 08 Dec 2022 08:28:15 GMT
jack

操作数据库

相关装备文件

在操作数据库之前,咱们要知道数据库装备在哪里,这儿咱们就看一下beego的装备文件,在项目目录的conf文件夹下有一个app.conf,经过beego.AppConfig.String("defaultdb")获取相关的装备

$ cat conf/app.conf
#项目姓名
appname = bee-demo
#项目运行端口
httpport = 8080
#指定运行环境 是dev还是prod
runmode = dev
#经过Ctx.Input.RequestBody获取数据
copyrequestbody = true
#开发环境装备文件
[dev]
    defaultdb = root:guofuBlog@tcp(127.0.0.1:3306)/youku?charset=utf8
#生成环境装备文件
[prod]
    defaultdb = root:guofuBlog@tcp(127.0.0.1:3306)/youku?charset=utf8

运用orm操作数据库

  • 咱们先来创立一个user表bee generate migration user,或者手写SQL也能够,我这儿运用bee指令创立,履行指令之后,生成文件bee-demo/database/migrations/20221209_105701_user.go
  • 接下来咱们依据自己的需求补全这个文件的内容
package main
import (
	"github.com/beego/beego/v2/client/orm/migration"
)
// DO NOT MODIFY
type User_20221209_105701 struct {
	migration.Migration
}
// DO NOT MODIFY
func init() {
	m := &User_20221209_105701{}
	m.Created = "20221209_105701"
	migration.Register("User_20221209_105701", m)
}
// Run the migrations
func (m *User_20221209_105701) Up() {
	// use m.SQL("CREATE TABLE ...") to make schema update
	m.CreateTable("user", "innodb", "utf8mb4")
	m.PriCol("id").SetAuto(true).SetDataType("int").SetUnsigned(true)
	m.NewCol("username").SetDataType("varchar(255)")
	m.NewCol("password").SetDataType("varchar(255)")
	m.NewCol("created_at").SetDataType("datetime").SetDefault("NOW()")
	m.NewCol("updated_at").SetDataType("datetime").SetDefault("NOW()")
	m.SQL(m.GetSQL())
}
// Reverse the migrations
func (m *User_20221209_105701) Down() {
	// use m.SQL("DROP TABLE ...") to reverse schema update
	m.SQL("DROP TABLE IF EXISTS user")
}
  • 履行指令生成数据表bee migrate -driver=mysql -conn="root:guofuBlog@tcp(127.0.0.1:3306)/bee_db"

那么运用migrate有什么好处呢?

  • 咱们看一下库,会发现有两个表,一个是咱们创立的user表,一个是migrations表,里边记录了咱们的建表语句,便利咱们快速完结数据搬迁

装备数据库

  • 咱们在app.conf中参加bee_db库的链接装备beedb = root:guofuBlog@tcp(127.0.0.1:3306)/bee_db
  • 在main函数中完结数据库的初始化
func init() {
	defaultdb, _ := beego.AppConfig.String("beedb")
	fmt.Println(defaultdb)
	orm.RegisterDriver("mysql", orm.DRMySQL)
	orm.RegisterDataBase("default", "mysql", defaultdb)
	orm.Debug = true
}

增删改查

  • 以下操作遵从RESTful风格
增加数据
  • 增加路由,这儿咱们经过form表单传参的方法
	//获取列表 增加用户
	beego.Router("/user", &controllers.UserController{})
	//get:GetOne 恳求方法:恳求方法  更新 删去  获取单个用户
	beego.Router("/user/:id", &controllers.UserController{},"get:GetOne")
  • 创立modelbee generate model user -fields="name:string"
  • 修改控制器
type ReturnApi struct {
	//tag:json 表示回来json格局的字段名
	Code int `json:"code"`
	Msg  string `json:"msg"`
	Data interface{} `json:"data"`
}
func SuccessApi() *ReturnApi {
	return &ReturnApi{Code: 200,Data:""}
}
func FailedApi() *ReturnApi {
	return &ReturnApi{Code: 9999,Data:""}
}
func (c *UserController) Post() {
	username := c.GetString("username")
	password := c.GetString("password")
	//界说一个json回来失利和成功的结构体
	if username == "" || password == "" {
		data := FailedApi()
		data.Msg = "参数不全"
		log.Println(data)
		c.Data["json"] = &data
		c.ServeJSON()
		return
	}
	m := models.User{
		Username: username,
		Password: password,
	}
	id, err := models.AddUser(&m)
	if err != nil {
		data := FailedApi()
		data.Msg = "刺进数据失利"
		data.Data = ""
		c.Data["json"] = data
		c.ServeJSON()
		return
	}
	data := SuccessApi()
	data.Msg = "刺进成功"
	data.Data = id
	c.Data["json"] = data
	c.ServeJSON()
	return
}

拆箱phper最适合入门的go框架beego

  • 这是咱们用bee model生成的model里边自带的方法,接下来咱们运用原生sql写一下,共享一下model的代码
func AddUserRaw(username string,password string) (id int64,err error) {
	o := orm.NewOrm()
	res,errRes:=o.Raw("insert into User set username=?,password=? ", username, password).Exec()
	if errRes != nil {
		err=errors.New("刺进失利")
		id=0
		return
	}
	err=nil
	id,_=res.LastInsertId()
	return
}
查询一条数据
func (c *UserController) GetOne() {
	id_str := c.Ctx.Input.Param(":id")
	id, _ := strconv.ParseInt(id_str, 10, 64)
	log.Println(id)
	if id < 1  {
		data := FailedApi()
		data.Msg = "该用户不存在"
		log.Println(data)
		c.Data["json"] = &data
		c.ServeJSON()
		return
	}
	data := SuccessApi()
	data.Msg = "获取成功"
	user, err := models.GetUserById(id)
	if err != nil {
		data := FailedApi()
		data.Msg = "该用未注册"
		log.Println(data)
		c.Data["json"] = &data
		c.ServeJSON()
		return
	}
	data.Data = user
	c.Data["json"] = &data
	c.ServeJSON()
	return
}
  • orm和原生写法
// GetUserById retrieves User by Id. Returns error if
// Id doesn't exist
func GetUserById(id int64) (v *User, err error) {
	o := orm.NewOrm()
	v = &User{Id: id}
	if err = o.QueryTable(new(User)).Filter("Id", id).RelatedSel().One(v); err == nil {
		return v, nil
	}
	return nil, err
}
func GetUserByIdRaw(id int64) (v *User, err error) {
	o := orm.NewOrm()
	v = &User{}
	err=o.Raw("select `id`,`username` from user where id=? limit 1",id).QueryRow(&v)
	if err != nil {
		return nil,err
	}
	return v, err
}

查列表

  • 路由beego.Router("/user/list", &controllers.UserController{},"get:GetAll")
  • 控制器

func (c *UserController) GetAll() {
	list:=models.GetAllUser()
	data := SuccessApi()
	data.Msg = "获取成功"
	data.Data=list
	log.Println(data)
	c.Data["json"] = &data
	c.ServeJSON()
	return
}
  • model
func GetAllUser() ([]User) {
	var (
		users []User
	)
	o := orm.NewOrm()
	qs := o.QueryTable(new(User))
	qs = qs.Filter("id__gt", 7)
	qs = qs.Limit(2)
	qs = qs.OrderBy("-id")
	qs.All(&users, "id", "username")
	return users
}

删数据

  • 路由 beego.Router("/user/:id", &controllers.UserController{}, "Delete:Delete")
  • 控制器
func (c *UserController) Delete() {
	id_str := c.Ctx.Input.Param(":id")
	id, _ := strconv.ParseInt(id_str, 10, 64)
	err:=models.DelUserRaw(id)
	if err != nil {
		data := FailedApi()
		data.Msg = "删去失利"
		log.Println(data)
		c.Data["json"] = &data
		c.ServeJSON()
		return
	}
	data := SuccessApi()
	data.Msg = "删去成功"
	log.Println(data)
	c.Data["json"] = &data
	c.ServeJSON()
	return
}
  • model

func DeleteUser(id int64) (err error) {
	o := orm.NewOrm()
	v := User{Id: id}
	// ascertain id exists in the database
	if err = o.Read(&v); err == nil {
		var num int64
		if num, err = o.Delete(&User{Id: id}); err == nil {
			fmt.Println("Number of records deleted in database:", num)
		}
	}
	return
}
func DelUserRaw(id int64) (err error) {
	o := orm.NewOrm()
	res, errRes := o.Raw("delete from  User where id=?",id).Exec()
	if errRes != nil {
		err = errors.New("刺进失利")
		id = 0
		return
	}
	err = nil
	id, _ = res.LastInsertId()
	return
}

bee的其他指令

  • generate 指令 这个指令是用来主动化的生成代码的,包含了从数据库一键生成 model,还包含了 scaffold 的,经过这个指令,让我们开发代码不再慢
    bee generate scaffold [scaffoldname] [-fields=""] [-driver=mysql] [-conn="root:@tcp(127.0.0.1:3306)/test"]
    // 此处是一个批处理指令,生成model,controller、view、doc以及生成数据搬迁文件,并进行数据搬迁
    // The generate scaffold command will do a number of things for you.
    // -fields: a list of table fields. Format: field:type, ...
    // -driver: [mysql | postgres | sqlite], the default is mysql
    // -conn:   the connection string used by the driver, the default is root:@tcp(127.0.0.1:3306)/test
    例子: bee generate scaffold post -fields="title:string,body:text" -conn="root:root@tcp(127.0.0.1:3306)/beego_api"
    例子中的指令会 依据-fields="title:string,body:text" 来创立model,controller、view、以及生成数据搬迁文件,并进行数据搬迁(即在数据库中生成对应的数据表)。以上操作都会问询yes或者no
bee generate model [modelname] [-fields=""]     // 依据fields列表来生成model文件
    // generate RESTful model based on fields
    // -fields: a list of table fields. Format: field:type, ...
bee generate controller [controllerfile]       // 生成controller文件(依据对应的model文件)
    // generate RESTful controllers
bee generate view [viewpath]                   // 生成view文件,
    // generate CRUD view in viewpath
bee generate migration [migrationfile] [-fields=""]        // 生成数据搬迁文件
    // generate migration file for making database schema update
    // -fields: a list of table fields. Format: field:type, ...
bee generate docs                             // 生成文档
    // generate swagger doc file
bee generate test [routerfile]                // 依据路由生成测试用例(没试过)
    // generate testcase
bee generate appcode [-tables=""] [-driver=mysql] [-conn="root:@tcp(127.0.0.1:3306)/test"] [-level=3]    // 这儿便是文章介绍的,依据数据表生成model文件等
    // generate appcode based on an existing database
    // -tables: a list of table names separated by ',', default is empty, indicating all tables
    // -driver: [mysql | postgres | sqlite], the default is mysql
    // -conn:   the connection string used by the driver.
    //         default for mysql:    root:@tcp(127.0.0.1:3306)/test
    //         default for postgres: postgres://postgres:postgres@127.0.0.1:5432/postgres
    // -level:  [1 | 2 | 3], 1 = models; 2 = models,controllers; 3 = models,controllers,router