Beego介绍与安装
Beego是一个使用Go语言来开发Web应用额GoWeb框架,诞生于2012年。可以快速开发API、Web、后端服务等各种应用。
主要特点:
- 简单化:使用MVC模型,支持RESTful;可以使用bee工具来提高开发效率,如果监控代码修改进行热编译、自动化测试代码、自动化打包部署。
-智能化:封装了路由、支持智能路由、智能监控、监控内存消耗、CPU使用以及Goroutine的运行状况。 - 模块化:对代码解耦封装、形成了session、cache、log、配置解析、性能监控、上下文操作、ORM等;
- 高性能: Beego采用原生的Go原生的HTTP请求,Goroutine的并发效率应付大流量Web应用和API应用。
Beego安装
- mkdir beego
- cd beego
- go mod init beego
- go install github.com/beego/bee/v2@latest //先安装bee工具
- 安装完之后,bee 可执行文件默认存放在 $GOPATH/bin 里面,所以你需要把 $GOPATH/bin 添加到你的环境变量中,才可以进行下一步。
如果你本机设置了 GOBIN,那么上面的bee命令就会安装到 GOBIN 目录下,所以我们需要在环境变量中添加相关的配置信息
#go语言安装主根目录
export GOROOT=/usr/local/go #替换你的目录
#GOPATH 是自己的go项目路径,自定义设置
export GOPATH=/Users/Lee/www/golang #替换你的目录
#GOBIN 当我们使用go install命令编译后并且安装的二进制程序目录
export GOBIN=$GOPATH/bin
# 启用 Go Modules 功能
export GO111MODULE=on
# 配置 GOPROXY 环境变量。你可以换成你喜欢的 proxy
export GOPROXY=https://goproxy.cn,direct
# 加入环境变量中
export PATH=$PATH:$GOROOT/bin:$GOBIN
安装完成之后 使用 bee version
______
| ___ \
| |_/ / ___ ___
| ___ \ / _ \ / _ \
| |_/ /| __/| __/
\____/ \___| \___| v2.1.0
出现如此字样即安装ok,执行命令 bee new beego 即创建一个 beego项目。如果只是用来做api项目,可以用bee api beego,这样就不会有静态资源和view文件夹,多一个test文件夹。
bee run 命令可以启动并监控项目(热更新)
bee pack 目录用来发布应用的时候打包,会把项目打包成 zip 包,这样我们部署的时候直接把打包之后的项目上传,解压就可以部署了。
开发的时候最喜欢的命令:generate
可以一个命令生成 bee generate controller、model、view等方便快捷。
管理SQL的命令 migrate:
bee migrate: run all outstanding migrations
bee migrate rollback:rollback the last migration operation
bee migrate reset :rollback all migrations
bee migrate refresh:rollback all migrations and run them all again
配置模块
Beego 目前支持 INI、XML、JSON、YAML 格式的配置文件解析,也支持以 etcd 作为远程配置中心。
在conf/app.conf
路由
查看已经注册的所有路由:
tree := web.PrintTree()
methods := tree["Data"].(web.M)
for k, v := range methods {
fmt.Printf("%s => %v\n", k, v)
}
控制器风格的路由:
web.CtrlGet("api/user/:id", UserController.GetUserById)
注册函数式风格路由注册:
该风格比较接近 Go 本身的语法特性,使用该风格,非常简单,可以直接采用函数式的写法:
func main() {
web.Get("/hello", func(ctx *context.Context) {
ctx.WriteString("hello, world")
})
web.Run()
}
增加前缀:
ctrl := &UserController{}
web.AutoPrefix("api", ctrl)
获取路由参数
/api/order/:id/detail
id := ctrl.Ctx.Input.Param(":splat")
如果是多段的,例如/api/*/name/*/detail,那么:splat只能获得最后一段的数据
/api/:username/profile
username := ctrl.Ctx.Input.Param(":username")
Get类 方法:
name := ctrl.GetString("name","jack") //默认值是jack
把输入转换为结构体:
type MainController struct {
web.Controller
}
func (ctrl *MainController) Post() {
user := User{}
err := ctrl.BindJSON(&user)
if err != nil {
ctrl.Ctx.WriteString(err.Error())
return
}
ctrl.Ctx.WriteString(fmt.Sprintf("%v", user))
}
type User struct {
Age int `json:"age"`
Name string `json:"name"`
}
web 上传和下载
文件上传之后一般是放在系统的内存里面,如果文件的 size 大于设置的缓存内存大小,那么就放在临时文件中,默认的缓存内存是 64M,你可以通过如下来调整这个缓存内存大小:
web.MaxMemory = 1<<22
或者在配置文件中通过如下设置:
maxmemory = 1<<22
与此同时,Beego 提供了另外一个参数,MaxUploadSize来限制最大上传文件大小——如果你一次长传多个文件,那么它限制的就是这些所有文件合并在一起的大小。
默认情况下,MaxMemory应该设置得比MaxUploadSize小,这种情况下两个参数合并在一起的效果则是:
如果文件大小小于MaxMemory,则直接在内存中处理;
如果文件大小介于MaxMemory和MaxUploadSize之间,那么比MaxMemory大的部分将会放在临时目录;
文件大小超出MaxUploadSize,直接拒绝请求,返回响应码 413
GetFile()该方法主要用于用户读取表单中的文件名 the_file,然后返回相应的信息,用户根据这些变量来处理文件上传、过滤、保存文件等。
SaveToFile(fromfile, tofile string) error:该方法是在 GetFile 的基础上实现了快速保存的功能。fromfile是提交时候表单中的name。
下载:
ctrl.Ctx.Output.Download("LICENSE", "license.txt")
Download方法的第一个参数文件路径,第二个参数是用户保存到本地时候的文件名。
如果第一个参数使用的是相对路径,那么它代表的是从当前工作目录开始计算的相对路径
XSRF跨站请求伪造
跨站请求伪造(Cross-site request forgery) (opens new window), 简称为 XSRF,是 Web 应用中常见的一个安全问题。
当前防范 XSRF 的一种通用的方法,是对每一个用户都记录一个无法预知的 cookie 数据,然后要求所有提交的请求(POST/PUT/DELETE)中都必须带有这个 cookie 数据。如果此数据不匹配 ,那么这个请求就可能是被伪造的。
直接在 main 入口处这样设置:
web.EnableXSRF = true
web.XSRFKEY = "61oETzKXQAGaYdkL5gEmGeJJFuYh7EQnp2XdTP1o"
web.XSRFExpire = 3600
这样就需要前端传递给你的时候每次都要传递xsrf
信息
两种方式:
在表单里面携带一个叫做 _xsrf 的字段,里面是 XSRF 的 Token;
在提交的请求的 HTTP HEADER 里面设置 X-Xsrftoken 或 X-Csrftoken,值就是 Token;
烦死了去跑步去。5km之后再来写。5.7km 跑完了接着写~
Orm的增删改查:
//单行插入
Insert(md interface{}) (int64, error)
InsertWithCtx(ctx context.Context, md interface{}) (int64, error)
InsertOrUpdate(md interface{}, colConflitAndArgs ...string) (int64, error)
InsertOrUpdateWithCtx(ctx context.Context, md interface{}, colConflitAndArgs ...string)
批量插入
InsertMulti(bulk int, mds interface{}) (int64, error)
InsertMultiWithCtx(ctx context.Context, bulk int, mds interface{}) (int64, error)
更新
Update(md interface{}, cols ...string) (int64, error) //会主动寻找主键
UpdateWithCtx(ctx context.Context, md interface{}, cols ...string) (int64, error)
使用主键来删除数据,定义:
Delete(md interface{}, cols ...string) (int64, error)
DeleteWithCtx(ctx context.Context, md interface{}, cols ...string) (int64, error)
读取
Read(md interface{}, cols ...string) error
ReadWithCtx(ctx context.Context, md interface{}, cols ...string) error
事务
// Beego will manage the transaction's lifecycle
// if the @param task return error, the transaction will be rollback
// or the transaction will be committed
err := o.DoTx(func(ctx context.Context, txOrm orm.TxOrmer) error {
// data
user := new(User)
user.Name = "test_transaction"
// insert data
// Using txOrm to execute SQL
_, e := txOrm.Insert(user)
// if e != nil the transaction will be rollback
// or it will be committed
return e
})
QuerySeter
// 获取 QuerySeter 对象,user 为表名
qs := o.QueryTable("user")
qs.Filter("profileage", 18) // WHERE profile.age = 18
qs.Filter("ProfileAge", 18) // 使用字段名和 Field 名都是允许的
qs.Filter("profileagegt", 18) // WHERE profile.age > 18
qs.Filter("name__iexact", "slene")
// WHERE name LIKE 'slene'
// 大小写不敏感,匹配任意 'Slene' 'sLENE'
qs.Filter("name__icontains", "slene")
// WHERE name LIKE '%slene%'
// 大小写不敏感, 匹配任意 'im Slene', 'im sLENE'
qs.Filter("name__istartswith", "slene")
// WHERE name LIKE 'slene%'
// 大小写不敏感, 匹配任意以 'slene', 'Slene' 起始的字符串
qs.Filter("name__iendswithi", "slene")
// WHERE name LIKE '%slene'
// 大小写不敏感, 匹配任意以 'slene', 'Slene' 结束的字符串
qs.Filter("profile_id__isnull", true)
// WHERE profile_id IS NULL
qs.Filter("profile__isnull", false)
// WHERE profile_id IS NOT NULL
缓存模式
Read Through
Read Through 缓存模式本质上就是帮助你在缓存没有的情况下去数据库加载数据,并且回写缓存
Random Expire
这个模式主要用于解决缓存雪崩问题,即大量的 key 在同一时间过期,那么就可以考虑在设置 key-value 的时候,给过期时间加上一个随机偏移量
Singleflight
在 key 不存在,或者查询缓存失败的情况下,会有多个 goroutine 尝试去加载数据,那么使用该模式可以确保,一个 key 在当前进程里面只有一个 goroutine 去加载数据
Bloom Filter
该模式用于高并发环境下快速判断 key 对应的数据是否存在,比较适合解决缓存穿透问题。
日志模块
log := logs.NewLogger()
logs.EnableFuncCallDepth(true) 日志默认不输出调用的文件名和文件行号,如果你期望输出调用的文件名和文件行号 设置为true
数据校验
go get github.com/beego/beego/v2/core/validation
u := User{"man", 40}
valid := validation.Validation{}
valid.Required(u.Name, "name")
valid.MaxSize(u.Name, 15, "nameMax")
valid.Range(u.Age, 0, 18, "age")
type user struct {
Id int
Name string valid:"Required;Match(/^Bee.*/)"
// Name 不能为空并且以 Bee 开头
Age int valid:"Range(1, 140)"
// 1 <= Age <= 140,超出此范围即为不合法
Email string valid:"Email; MaxSize(100)"
// Email 字段需要符合邮箱格式,并且最大长度不能大于 100 个字符
Mobile string valid:"Mobile"
// Mobile 必须为正确的手机号
IP string valid:"IP"
// IP 必须为一个正确的 IPv4 地址
}
定时任务
tk1 := task.NewTask("tk1", "0 12 ", func(ctx context.Context) error { fmt.Println("tk1"); return nil })
NewTask(tname string, spec string, f TaskFunc) *Task
tname: 任务名称
spec: 定时任务格式,请参考下面的详细介绍
f: 执行的函数