介绍

beego 是免费、开源的软件,这意味着任何人都可以为其开发和进步贡献力量。beego 源代码目前托管在 Github 上,Github 提供非常容易的途径 fork 项目和合并你的贡献。
Github地址:https://github.com/beego/beego

[!NOTE]

建议看下README.md,还是有很大的帮助的

安装升级

安装

和常规的包安装一样,go get即可

  1. go get -v github.com/beego/beego/v2@latest

或者手动下载源码go install,反正原理都是一样的

  1. git clone https://github.com/beego/beego.git
  2. cd beego
  3. go install

升级

beego 升级分为 go 方式升级和源码下载升级:

  • Go升级:通过该方式用户可以升级 beego 框架(推荐)
  1. go get -v -u github.com/beego/beego/v2@latest
  • 源码下载升级:手动下载源码,然后覆盖到 $GOPATH/src/github.com/beego/beego 目录,然后通过本地执行安装就可以升级了:
  1. go install github.com/beego/beego

bee工具使用

bee 工具是一个为了协助快速开发 beego 项目而创建的项目,通过 bee 您可以很容易的进行 beego 项目的创建、热编译、开发、测试、和部署

安装

  1. go get github.com/beego/bee/v2

下载完成后,会自动编译成可执行二进制文件bee,放到$GOPATH/bin目录下
image-20220107133803833

基础使用

  1. bee help
  2. Bee is a Fast and Flexible tool for managing your Beego Web Application.
  3. You are using bee for beego v2.x. If you are working on beego v1.x, please downgrade version to bee v1.12.0
  4. USAGE
  5. bee command [arguments]
  6. AVAILABLE COMMANDS
  7. version Prints the current Bee version
  8. migrate Runs database migrations
  9. api Creates a Beego API application
  10. bale Transforms non-Go files to Go source files
  11. fix Fixes your application by making it compatible with newer versions of Beego
  12. pro Source code generator
  13. dev Commands which used to help to develop beego and bee
  14. dlv Start a debugging session using Delve
  15. dockerize Generates a Dockerfile for your Beego application
  16. generate Source code generator
  17. hprose Creates an RPC application based on Hprose and Beego frameworks
  18. new Creates a Beego application
  19. pack Compresses a Beego application into a single file
  20. rs Run customized scripts
  21. run Run the application by starting a local development server
  22. server serving static content over HTTP on port
  23. update Update Bee
  24. Use bee help [command] for more information about a command.
  25. ADDITIONAL HELP TOPICS
  26. Use bee help [topic] for more information about that topic.
  27. bee: Too many arguments.
  28. Use bee help for more information.

new

新建一个web项目,用法:

  1. bee new <项目名>

image-20220107134634083
执行后会在当前目录创建文件夹,所以建议在src/目录下创建,创建后的目录结构:

  1. .
  2. ├── conf
  3. └── app.conf
  4. ├── controllers
  5. └── default.go
  6. ├── go.mod
  7. ├── main.go
  8. ├── models
  9. ├── routers
  10. └── router.go
  11. ├── static
  12. ├── css
  13. ├── img
  14. └── js
  15. └── reload.min.js
  16. ├── tests
  17. └── default_test.go
  18. └── views
  19. └── index.tpl
  20. 10 directories, 8 files

api

上面的 new 命令是用来新建 Web 项目,不过很多用户使用 beego 来开发 API 应用。所以这个 api 命令就是用来创建 API 应用的

  1. bee api <项目名>
  1. bee api beegoAPI
  2. create /Users/d4m1ts/go/src/github.com/damit5/beegoAPI/go.mod
  3. create /Users/d4m1ts/go/src/github.com/damit5/beegoAPI
  4. create /Users/d4m1ts/go/src/github.com/damit5/beegoAPI/conf
  5. create /Users/d4m1ts/go/src/github.com/damit5/beegoAPI/controllers
  6. create /Users/d4m1ts/go/src/github.com/damit5/beegoAPI/tests
  7. create /Users/d4m1ts/go/src/github.com/damit5/beegoAPI/conf/app.conf
  8. create /Users/d4m1ts/go/src/github.com/damit5/beegoAPI/models
  9. create /Users/d4m1ts/go/src/github.com/damit5/beegoAPI/routers/
  10. create /Users/d4m1ts/go/src/github.com/damit5/beegoAPI/controllers/object.go
  11. create /Users/d4m1ts/go/src/github.com/damit5/beegoAPI/controllers/user.go
  12. create /Users/d4m1ts/go/src/github.com/damit5/beegoAPI/tests/default_test.go
  13. create /Users/d4m1ts/go/src/github.com/damit5/beegoAPI/routers/router.go
  14. create /Users/d4m1ts/go/src/github.com/damit5/beegoAPI/models/object.go
  15. create /Users/d4m1ts/go/src/github.com/damit5/beegoAPI/models/user.go
  16. create /Users/d4m1ts/go/src/github.com/damit5/beegoAPI/main.go

目录结构如下:

  1. .
  2. ├── conf
  3. └── app.conf
  4. ├── controllers
  5. ├── object.go
  6. └── user.go
  7. ├── go.mod
  8. ├── main.go
  9. ├── models
  10. ├── object.go
  11. └── user.go
  12. ├── routers
  13. └── router.go
  14. └── tests
  15. └── default_test.go

从上面的目录我们可以看到和 Web 项目相比,少了 staticviews 目录,多了一个 test 模块,用来做单元测试的
同时,该命令还支持一些自定义参数自动连接数据库创建相关 model 和 controller:

  1. bee api [appname] [-tables=""] [-driver=mysql] [-conn="root:<password>@tcp(127.0.0.1:3306)/test"]

如果 conn 参数为空则创建一个示例项目,否则将基于链接信息链接数据库创建项目

run

我们在开发 Go 项目的时候最大的问题是经常需要自己手动去编译再运行,bee run 命令是监控 beego 的项目,通过fsnotify监控文件系统。但是注意该命令必须在 $GOPATH/src/ 下执行。 这样我们在开发过程中就可以实时的看到项目修改之后的效果

[!NOTE]

第一次运行bee run可能会存在很多小问题,根据提示依次解决即可

  1. bee run

image-20220107135811617
打开http://127.0.0.1:8080/即可看到Web页面
image-20220107135846128
修改内容后会实时更新(类似于flask的debug模式)
image-20220107140422085

pack

pack 命令用来发布应用的时候打包,会把项目打包成 zip 包,这样我们部署的时候直接把打包之后的项目上传,解压就可以部署了

  1. bee pack

image-20220107140603916

bale

给所有的静态文件压缩为单个二进制文件

  1. bee bale

image-20220107140836620
GO狂热者需要,平时感觉也没必要,略过

version

看各种版本等信息的

  1. bee version
  2. ______
  3. | ___ \
  4. | |_/ / ___ ___
  5. | ___ \ / _ \ / _ \
  6. | |_/ /| __/| __/
  7. \____/ \___| \___| v2.0.2
  8. ├── 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.
  9. ├── GoVersion : go1.16.7
  10. ├── GOOS : darwin
  11. ├── GOARCH : amd64
  12. ├── NumCPU : 16
  13. ├── GOPATH : /Users/d4m1ts/go
  14. ├── GOROOT : /usr/local/go
  15. ├── Compiler : gc
  16. └── Date : Friday, 7 Jan 2022

generate

自动生成代码,包含了从数据库一键生成 model,还包含了 scaffold 的
自己看帮助吧
image-20220107141204439

migrate

这个命令是应用的数据库迁移命令,主要是用来每次应用升级,降级的SQL管理
image-20220107141247422

dockerize

这个命令可以通过生成Dockerfile文件来实现docker化你的应用
感觉还可以,就是不知道实际效果咋样,后面可以再研究下
image-20220107141353837

修改端口

beego启动后默认监听8080端口,修改的话,直接修改conf/app.conf即可
image-20220107141852607

快速入门

项目创建

创建项目,还是利用bee去进行创建,主要分两个:

  1. bee new <项目名> # MVC架构
  2. bee api <项目名> # RESTful风格后端

创建后都可以使用bee run进行热编译,然后访问对应的端口即可

后面暂时以MVC架构为主吧

启动过程

查看main.go,明显看到启动其实是

  1. beego.Run()

我们看到的效果好像只是监听服务端口这个过程,但是它内部做了很多事情
image-20220107145347571
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解释器执行过程:
img
直接看看代码吧

  1. package main
  2. import (
  3. _ "beegoStudy/routers"
  4. beego "github.com/beego/beego/v2/server/web"
  5. )
  6. func main() {
  7. beego.Run()
  8. }

第四行很明显,引入了我当前项目下的routers包,也就是路由,再去看一下这个目录下的文件router.go

  1. package routers
  2. import (
  3. "beegoStudy/controllers"
  4. beego "github.com/beego/beego/v2/server/web"
  5. )
  6. func init() {
  7. beego.Router("/", &controllers.MainController{})
  8. }

它会先引入controllers(逻辑处理),再执行init()函数,所以路由注册代码:

  1. beego.Router("/", &controllers.MainController{})
  2. // beego.Router(路由, 逻辑)

比如我们再创建一个路由:
编辑router.go文件,添加一行

  1. package routers
  2. import (
  3. "beegoStudy/controllers"
  4. beego "github.com/beego/beego/v2/server/web"
  5. )
  6. func init() {
  7. beego.Router("/", &controllers.MainController{})
  8. beego.Router("/test", &controllers.MainController{}) // 新加路由
  9. }

查看效果
image-20220107144627355

Controller逻辑

路由有了,那么接下来就应该是逻辑部分了
还是看示例代码吧,感觉有点基础通过看示例代码就基本上能入门了哈哈
注册路由的时候,第二个参数就是逻辑部分
image-20220107150752471
看一下Router这个函数,逻辑部分应该是需要实现ControllerInterface这个接口
image-20220107150720637
跟进ControllerInterface,可以看到他的方法列表
image-20220107150943621


来看下默认生成的逻辑代码,很明显的实现了Get()方法
image-20220107151029649
所以我们get调用的时候会返回渲染后的内容。

[!NOTE]

上面只是根据实例代码分析出来的,实际还是需要多找找资料文档研究

  1. package controllers
  2. import (
  3. beego "github.com/beego/beego/v2/server/web"
  4. )
  5. type MainController struct {
  6. beego.Controller
  7. }
  8. func (c *MainController) Get() {
  9. c.Data["Website"] = "beego.me"
  10. c.Data["Email"] = "d4m1ts@qq.com"
  11. c.TplName = "index.tpl"
  12. }

上面的代码显示首先我们声明了一个控制器 MainController这个控制器里面内嵌了 beego.Controller,这就是 Go 的嵌入方式,也就是 MainController 自动拥有了所有 beego.Controller 的方法
beego.Controller 拥有很多方法,其中包括 InitPreparePostGetDeleteHead 等方法。我们可以通过重写的方式来实现这些方法,而我们上面的代码就是重写了 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 调用上下文来输出字符串

  1. c.Ctx.WriteString("test")

image-20220107152403767

Model模型

我们知道 Web 应用中我们用的最多的就是数据库操作,而 model 层一般用来做这些操作,我们的 bee new 例子不存在 Model 的演示,但是 bee api 应用中存在 model 的应用。说的简单一点,如果您的应用足够简单,那么 Controller 可以处理一切的逻辑,如果您的逻辑里面存在着可以复用的东西,那么就抽取出来变成一个模块。因此 Model 就是逐步抽象的过程,一般我们会在 Model 里面处理一些数据读取

View视图

在前面编写 Controller 的时候,我们在 Get() 方法里面写过这样的语句 c.TplName = "index.tpl",设置显示的模板文件,默认支持 tplhtml 的后缀名,如果想设置其他后缀你可以调用 beego.AddTemplateExt 接口设置
很多动态语言里面都是通过在静态 HTML 中插入动态语言生成的数据,例如 JSP 中通过插入 <%=....=%>,PHP 中通过插入 <?php.....?> 来实现的,beego 采用了 Go 语言默认的模板引擎,所以和 Go 的模板语法一样

Go Web 编程

字段操作

Go 语言的模板通过 {{}} 来包含需要在渲染时被替换的字段,{{.}} 表示当前的对象,这和 Java 或者 C++ 中的 this 类似,如果要访问当前对象的字段通过 {{.FieldName}},但是需要注意一点:这个字段必须是导出的 (字段首字母必须是大写的),否则在渲染的时候就会报错

  1. c.Data["Website"] = "beego.me"
  2. c.Data["Email"] = "d4m1ts@qq.com"

image-20220107154018934

输出嵌套字段内容

如果字段里面还有对象,可以使用 {{with …}}…{{end}}{{range …}}{{end}} 来进行数据的循环输出

  • {{range}} 这个和 Go 语法里面的 range 类似,循环操作数据
  • {{with}} 操作是指当前对象的值,类似上下文的概念 ``` Emails := []string {
    1. "d4m1ts@qq.com",
    2. "tset@qq.com",
    } c.Data[“Emails”] = Emails
  1. ```
  2. {{range .Emails}}
  3. <h1> {{.}} </h1><br/>
  4. {{end}}
  5. {{with .Emails}}
  6. {{range .}}
  7. <h2> {{.}} </h2><br/>
  8. {{end}}
  9. {{end}}

image-20220107155413011

条件输出

在 Go 模板里面如果需要进行条件判断,那么我们可以使用和 Go 语言的 if-else 语法类似的方式来处理,如果 pipeline 为空,那么 if 就认为是 false
1、{{if bool}} ... {{end}}
2、{{if bool}} ... {{else}} ... {{end}}

[!WARNING]

注意:if 里面无法使用条件判断,例如 .Mail==”astaxie@gmail.com“,这样的判断是不正确的,if 里面只能是 bool 值

  1. c.Data["Res1"] = true
  2. c.Data["Res2"] = false
  1. {{if .Res1}}
  2. <h1> True </h1><br/>
  3. {{end}}
  4. {{if .Res2}}
  5. <h1> True </h1><br/>
  6. {{else}}
  7. <h1> False </h1><br/>
  8. {{end}}

image-20220107155952631

HTML实体化编码

[!NOTE]

pipelines,和Unix下的管道符 | 一样,给前面的结果传递给后面

Go 语言模板最强大的一点就是支持 pipe 数据,在 Go 语言里面任何 {{}} 里面的都是 pipelines 数据,例如我们上面输出的 email 里面如果还有一些可能引起 XSS 注入的,就可以使用如下语法来防止,把输出全部转化 html 的实体

  1. {{. | html}}

举例:

  1. <a class="email" href="mailto:{{.Email | html}}">{{.Email | html}}</a>

image-20220107160404416

模板变量

有时候,我们在模板使用过程中需要定义一些局部变量,我们可以在一些操作中申明局部变量

  1. {{with $x := "output" | printf "%q"}}{{$x}}{{end}}
  2. {{with $x := "output"}}{{printf "%q" $x}}{{end}}
  3. {{with $x := "output"}}{{$x | printf "%q"}}{{end}}

image-20220107161028479

嵌套模板

我们平常开发 Web 应用的时候,经常会遇到一些模板有些部分是固定不变的,然后可以抽取出来作为一个独立的部分,例如一个博客的头部和尾部是不变的,而唯一改变的是中间的内容部分。所以我们可以定义成 headercontentfooter 三个部分。Go 语言中通过如下的语法来声明

  1. {{define "子模板名称"}}内容{{end}}

通过如下方式来调用

  1. {{template "子模板名称"}}

举例:

  1. //header.tpl
  2. {{define "header"}}
  3. <html>
  4. <head>
  5. <title>演示信息</title>
  6. </head>
  7. <body>
  8. {{end}}
  9. //content.tpl
  10. {{define "content"}}
  11. {{template "header"}}
  12. <h1>演示嵌套</h1>
  13. <ul>
  14. <li>嵌套使用define定义子模板</li>
  15. <li>调用使用template</li>
  16. </ul>
  17. {{template "footer"}}
  18. {{end}}
  19. //footer.tpl
  20. {{define "footer"}}
  21. </body>
  22. </html>
  23. {{end}}

静态文件

前面我们介绍了如何输出静态页面,但是我们的网页往往包含了很多的静态文件,包括图片、JS、CSS 等,刚才创建的应用里面就创建了如下目录

  1. ├── static
  2. ├── css
  3. ├── img
  4. └── js
  5. └── reload.min.js

beego 默认注册了 static 目录为静态处理的目录,注册样式:URL 前缀和映射的目录(在/main.go文件中beego.Run()之前加入)

  1. StaticDir["/static"] = "static"

所以默认情况下可以这样访问

  1. <script src="/static/js/reload.min.js"></script>

用户可以设置多个静态文件处理目录,例如你有多个文件下载目录 download1、download2,你可以这样映射(在 /main.go 文件中 beego.Run() 之前加入)

  1. beego.SetStaticPath("/down1", "download1")
  2. beego.SetStaticPath("/down2", "download2")