介绍
beego 是免费、开源的软件,这意味着任何人都可以为其开发和进步贡献力量。beego 源代码目前托管在 Github 上,Github 提供非常容易的途径 fork 项目和合并你的贡献。
Github地址:https://github.com/beego/beego
[!NOTE]
建议看下README.md,还是有很大的帮助的,GO高版本不能直接
go get
,需要先创建项目go mod init
后才能go get
安装升级
安装
和常规的包安装一样,go get
即可
mkdir hello
cd hello
go mod init
go get -v github.com/beego/beego/v2@latest
或者手动下载源码go install
,反正原理都是一样的
git clone https://github.com/beego/beego.git
cd beego
go install
升级
beego 升级分为 go 方式升级和源码下载升级:
Go升级:通过该方式用户可以升级 beego 框架(推荐)
go get -v -u github.com/beego/beego/v2@latest
源码下载升级:手动下载源码,然后覆盖到
$GOPATH/src/github.com/beego/beego
目录,然后通过本地执行安装就可以升级了:go install github.com/beego/beego
bee工具使用
bee 工具是一个为了协助快速开发 beego 项目而创建的项目,通过 bee 您可以很容易的进行 beego 项目的创建、热编译、开发、测试、和部署。
安装
go get -u github.com/beego/bee/v2@master
下载完成后,会自动编译成可执行二进制文件bee
,放到$GOPATH/bin
目录下
基础使用
▶ bee help
Bee is a Fast and Flexible tool for managing your Beego Web Application.
You are using bee for beego v2.x. If you are working on beego v1.x, please downgrade version to bee v1.12.0
USAGE
bee command [arguments]
AVAILABLE COMMANDS
version Prints the current Bee version
migrate Runs database migrations
api Creates a Beego API application
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
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
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.
ADDITIONAL HELP TOPICS
Use bee help [topic] for more information about that topic.
bee: Too many arguments.
Use bee help for more information.
new
新建一个web项目,用法:
bee new <项目名>
执行后会在当前目录创建文件夹,所以建议在src/
目录下创建,创建后的目录结构:
.
├── conf
│ └── app.conf
├── controllers
│ └── default.go
├── go.mod
├── main.go
├── models
├── routers
│ └── router.go
├── static
│ ├── css
│ ├── img
│ └── js
│ └── reload.min.js
├── tests
│ └── default_test.go
└── views
└── index.tpl
10 directories, 8 files
api
上面的 new
命令是用来新建 Web 项目,不过很多用户使用 beego 来开发 API 应用。所以这个 api
命令就是用来创建 API 应用的
bee api <项目名>
▶ bee api beegoAPI
create /Users/d4m1ts/go/src/github.com/damit5/beegoAPI/go.mod
create /Users/d4m1ts/go/src/github.com/damit5/beegoAPI
create /Users/d4m1ts/go/src/github.com/damit5/beegoAPI/conf
create /Users/d4m1ts/go/src/github.com/damit5/beegoAPI/controllers
create /Users/d4m1ts/go/src/github.com/damit5/beegoAPI/tests
create /Users/d4m1ts/go/src/github.com/damit5/beegoAPI/conf/app.conf
create /Users/d4m1ts/go/src/github.com/damit5/beegoAPI/models
create /Users/d4m1ts/go/src/github.com/damit5/beegoAPI/routers/
create /Users/d4m1ts/go/src/github.com/damit5/beegoAPI/controllers/object.go
create /Users/d4m1ts/go/src/github.com/damit5/beegoAPI/controllers/user.go
create /Users/d4m1ts/go/src/github.com/damit5/beegoAPI/tests/default_test.go
create /Users/d4m1ts/go/src/github.com/damit5/beegoAPI/routers/router.go
create /Users/d4m1ts/go/src/github.com/damit5/beegoAPI/models/object.go
create /Users/d4m1ts/go/src/github.com/damit5/beegoAPI/models/user.go
create /Users/d4m1ts/go/src/github.com/damit5/beegoAPI/main.go
目录结构如下:
.
├── conf
│ └── app.conf
├── controllers
│ ├── object.go
│ └── user.go
├── go.mod
├── main.go
├── models
│ ├── object.go
│ └── user.go
├── routers
│ └── router.go
└── tests
└── default_test.go
从上面的目录我们可以看到和 Web 项目相比,少了 static
和 views
目录,多了一个 test 模块,用来做单元测试的
同时,该命令还支持一些自定义参数自动连接数据库创建相关 model 和 controller:
bee api [appname] [-tables=""] [-driver=mysql] [-conn="root:<password>@tcp(127.0.0.1:3306)/test"]
如果 conn
参数为空则创建一个示例项目,否则将基于链接信息链接数据库创建项目
创建后需要执行下列命令来补全依赖
go mod tidy
run
我们在开发 Go 项目的时候最大的问题是经常需要自己手动去编译再运行,bee run
命令是监控 beego 的项目,通过fsnotify监控文件系统。但是注意该命令必须在 $GOPATH/src/
下执行。 这样我们在开发过程中就可以实时的看到项目修改之后的效果
[!NOTE]
第一次运行
bee run
可能会存在很多小问题,根据提示依次解决即可
▶ bee run
打开http://127.0.0.1:8080/
即可看到Web页面
修改内容后会实时更新(类似于flask的debug模式)
pack
pack
命令用来发布应用的时候打包,会把项目打包成 zip 包,这样我们部署的时候直接把打包之后的项目上传,解压就可以部署了
▶ bee pack
bale
给所有的静态文件压缩为单个二进制文件
bee bale
GO狂热者需要,平时感觉也没必要,略过
version
看各种版本等信息的
bee version
______
| ___ \
| |_/ / ___ ___
| ___ \ / _ \ / _ \
| |_/ /| __/| __/
\____/ \___| \___| v2.0.2
├── Beego : Beego is not installed. Please do consider installing it first: https://github.com/beego/beego/v2. If you are using go mod, and you don't install the beego under $GOPATH/src/github.com/astaxie, just ignore this.
├── GoVersion : go1.16.7
├── GOOS : darwin
├── GOARCH : amd64
├── NumCPU : 16
├── GOPATH : /Users/d4m1ts/go
├── GOROOT : /usr/local/go
├── Compiler : gc
└── Date : Friday, 7 Jan 2022
generate
自动生成代码,包含了从数据库一键生成 model,还包含了 scaffold 的
自己看帮助吧
migrate
这个命令是应用的数据库迁移命令,主要是用来每次应用升级,降级的SQL管理
dockerize
这个命令可以通过生成Dockerfile文件来实现docker化你的应用
感觉还可以,就是不知道实际效果咋样,后面可以再研究下
修改端口
beego启动后默认监听8080端口,修改的话,直接修改conf/app.conf
即可
快速入门
项目创建
创建项目,还是利用bee
去进行创建,主要分两个:
bee new <项目名> # MVC架构
bee api <项目名> # RESTful风格后端
创建后都可以使用bee run
进行热编译,然后访问对应的端口即可
后面暂时以MVC架构为主吧
启动过程
查看main.go
,明显看到启动其实是
beego.Run()
我们看到的效果好像只是监听服务端口这个过程,但是它内部做了很多事情
1、解析配置文件
beego 会自动解析在 conf 目录下面的配置文件 app.conf
,通过修改配置文件相关的属性,我们可以定义:开启的端口,是否开启 session,应用名称等信息。
2、执行用户的 hookfunc
beego 会执行用户注册的 hookfunc,默认的已经存在了注册 mime,用户可以通过函数 AddAPPStartHook
注册自己的启动函数。
3、是否开启 session
会根据上面配置文件的分析之后判断是否开启 session,如果开启的话就初始化全局的 session。
4、是否编译模板
beego 会在启动的时候根据配置把 views 目录下的所有模板进行预编译,然后存在 map 里面,这样可以有效的提高模板运行的效率,无需进行多次编译。
5、是否开启文档功能
根据 EnableDocs 配置判断是否开启内置的文档路由功能
6、是否启动管理模块
beego 目前做了一个很酷的模块,应用内监控模块,会在 8088 端口做一个内部监听,我们可以通过这个端口查询到 QPS、CPU、内存、GC、goroutine、thread 等统计信息。
7、监听服务端口
这是最后一步也就是我们看到的访问 8080 看到的网页端口,内部其实调用了 ListenAndServe
,充分利用了 goroutine 的优势
一旦 run 起来之后,我们的服务就监听在两个端口了,一个服务端口 8080 作为对外服务,另一个 8088 端口实行对内监控。
自定义路由
前面已经能访问了,说明肯定有一个基础的路由,GO解释器执行过程:
直接看看代码吧
package main
import (
_ "beegoStudy/routers"
beego "github.com/beego/beego/v2/server/web"
)
func main() {
beego.Run()
}
第四行很明显,引入了我当前项目下的routers
包,也就是路由,再去看一下这个目录下的文件router.go
package routers
import (
"beegoStudy/controllers"
beego "github.com/beego/beego/v2/server/web"
)
func init() {
beego.Router("/", &controllers.MainController{})
}
它会先引入controllers
(逻辑处理),再执行init()
函数,所以路由注册代码:
beego.Router("/", &controllers.MainController{})
// beego.Router(路由, 逻辑)
比如我们再创建一个路由:
编辑router.go
文件,添加一行
package routers
import (
"beegoStudy/controllers"
beego "github.com/beego/beego/v2/server/web"
)
func init() {
beego.Router("/", &controllers.MainController{})
beego.Router("/test", &controllers.MainController{}) // 新加路由
}
查看效果
Controller逻辑
路由有了,那么接下来就应该是逻辑部分了
还是看示例代码吧,感觉有点基础通过看示例代码就基本上能入门了哈哈
注册路由的时候,第二个参数就是逻辑部分
看一下Router
这个函数,逻辑部分应该是需要实现ControllerInterface
这个接口
跟进ControllerInterface
,可以看到他的方法列表
来看下默认生成的逻辑代码,很明显的实现了Get()
方法
所以我们get调用的时候会返回渲染后的内容。
[!NOTE]
上面只是根据实例代码分析出来的,实际还是需要多找找资料文档研究
package controllers
import (
beego "github.com/beego/beego/v2/server/web"
)
type MainController struct {
beego.Controller
}
func (c *MainController) Get() {
c.Data["Website"] = "beego.me"
c.Data["Email"] = "[email protected]"
c.TplName = "index.tpl"
}
上面的代码显示首先我们声明了一个控制器 MainController
,这个控制器里面内嵌了 beego.Controller
,这就是 Go 的嵌入方式,也就是 MainController
自动拥有了所有 beego.Controller
的方法。
而 beego.Controller
拥有很多方法,其中包括 Init
、Prepare
、Post
、Get
、Delete
、Head
等方法。我们可以通过重写的方式来实现这些方法,而我们上面的代码就是重写了 Get
方法。
[!NOTE]
beego 是一个 RESTful 的框架,所以我们的请求默认是执行对应
req.Method
的方法。例如浏览器的是GET
请求,那么默认就会执行MainController
下的Get
方法。这样我们上面的 Get 方法就会被执行到,这样就进入了我们的逻辑处理。
c.Data
是一个用来存储输出数据的 map,可以赋值任意类型的值,会在最后一步把里面的内容渲染到tpl模板对应的位置,用户设置了模板之后系统会自动的调用 Render
函数(这个函数是在 beego.Controller
中实现的),所以无需用户自己来调用渲染。
最后一步是渲染的模板,c.TplName
就是需要渲染的模板,这里指定了 index.tpl
,如果用户不设置该参数,那么默认会去到模板目录的 Controller/<方法名>.tpl
查找,例如上面的方法会去 maincontroller/get.tpl
(文件、文件夹必须小写)。
不使用模版,可以直接用 c.Ctx.WriteString
调用上下文来输出字符串
c.Ctx.WriteString("test")
Model模型
我们知道 Web 应用中我们用的最多的就是数据库操作,而 model 层一般用来做这些操作,我们的 bee new
例子不存在 Model 的演示,但是 bee api
应用中存在 model 的应用。说的简单一点,如果您的应用足够简单,那么 Controller 可以处理一切的逻辑,如果您的逻辑里面存在着可以复用的东西,那么就抽取出来变成一个模块。因此 Model 就是逐步抽象的过程,一般我们会在 Model 里面处理一些数据读取
View视图
在前面编写 Controller 的时候,我们在 Get() 方法里面写过这样的语句 c.TplName = "index.tpl"
,设置显示的模板文件,默认支持 tpl
和 html
的后缀名,如果想设置其他后缀你可以调用 beego.AddTemplateExt
接口设置
很多动态语言里面都是通过在静态 HTML 中插入动态语言生成的数据,例如 JSP 中通过插入 <%=....=%>
,PHP 中通过插入 <?php.....?>
来实现的,beego 采用了 Go 语言默认的模板引擎,所以和 Go 的模板语法一样
字段操作
Go 语言的模板通过 {{}}
来包含需要在渲染时被替换的字段,{{.}}
表示当前的对象,这和 Java 或者 C++ 中的 this 类似,如果要访问当前对象的字段通过 {{.FieldName}}
,但是需要注意一点:这个字段必须是导出的 (字段首字母必须是大写的),否则在渲染的时候就会报错
c.Data["Website"] = "beego.me"
c.Data["Email"] = "[email protected]"
输出嵌套字段内容
如果字段里面还有对象,可以使用 {{with …}}…{{end}}
和 {{range …}}{{end}}
来进行数据的循环输出
`function(start, stop, step) {
if(typeof stop === 'undefined') { stop = start; start = 0; step = 1; } else if(!step) { step = 1; } var arr = []; var i; if (step > 0) { for (i=start; i<stop; i+=step) { arr.push(i); } } else { for (i=start; i>stop; i+=step) { arr.push(i); } } return arr; }` 这个和 Go 语法里面的 range 类似,循环操作数据
- `` 操作是指当前对象的值,类似上下文的概念
Emails := []string {
"[email protected]",
"[email protected]",
}
c.Data["Emails"] = Emails
{{range .Emails}}
{{.}}
{{end}}
{{with .Emails}}
{{range .}}
{{.}}
{{end}}
{{end}}
条件输出
在 Go 模板里面如果需要进行条件判断,那么我们可以使用和 Go 语言的 if-else
语法类似的方式来处理,如果 pipeline
为空,那么 if 就认为是 false
1、{{if bool}} ... {{end}}
2、{{if bool}} ... {{else}} ... {{end}}
[!WARNING]
注意:if 里面无法使用条件判断,例如 .Mail=="[email protected]",这样的判断是不正确的,if 里面只能是 bool 值
c.Data["Res1"] = true
c.Data["Res2"] = false
{{if .Res1}}
True
{{end}}
{{if .Res2}}
True
{{else}}
False
{{end}}
HTML实体化编码
[!NOTE]
pipelines
,和Unix下的管道符 | 一样,给前面的结果传递给后面
Go 语言模板最强大的一点就是支持 pipe 数据,在 Go 语言里面任何 {{}}
里面的都是 pipelines
数据,例如我们上面输出的 email 里面如果还有一些可能引起 XSS 注入的,就可以使用如下语法来防止,把输出全部转化 html 的实体
{{. | html}}
举例:
{{.Email | html}}
模板变量
有时候,我们在模板使用过程中需要定义一些局部变量,我们可以在一些操作中申明局部变量
{{with $x := "output" | printf "%q"}}{{$x}}{{end}}
{{with $x := "output"}}{{printf "%q" $x}}{{end}}
{{with $x := "output"}}{{$x | printf "%q"}}{{end}}
嵌套模板
我们平常开发 Web 应用的时候,经常会遇到一些模板有些部分是固定不变的,然后可以抽取出来作为一个独立的部分,例如一个博客的头部和尾部是不变的,而唯一改变的是中间的内容部分。所以我们可以定义成 header
、content
、footer
三个部分。Go 语言中通过如下的语法来声明
{{define "子模板名称"}}内容{{end}}
通过如下方式来调用
{{template "子模板名称"}}
举例:
//header.tpl
{{define "header"}}
演示信息
{{end}}
//content.tpl
{{define "content"}}
{{template "header"}}
演示嵌套
- 嵌套使用define定义子模板
- 调用使用template
{{template "footer"}}
{{end}}
//footer.tpl
{{define "footer"}}
{{end}}
静态文件
前面我们介绍了如何输出静态页面,但是我们的网页往往包含了很多的静态文件,包括图片、JS、CSS 等,刚才创建的应用里面就创建了如下目录
├── static
│ ├── css
│ ├── img
│ └── js
│ └── reload.min.js
beego 默认注册了 static 目录为静态处理的目录,注册样式:URL 前缀和映射的目录(在/main.go文件中beego.Run()
之前加入)
StaticDir["/static"] = "static"
所以默认情况下可以这样访问
<script src="/static/js/reload.min.js"></script>
用户可以设置多个静态文件处理目录,例如你有多个文件下载目录 download1、download2,你可以这样映射(在 /main.go 文件中 beego.Run()
之前加入)
beego.SetStaticPath("/down1", "download1")
beego.SetStaticPath("/down2", "download2")