beego框架入门(2)
beego框架的mvc
beego框架是一款典型的MVC框架,执行逻辑如下:
本图来自beego官网,具体的说明可以点击 这里查看具体说明。
创建一个项目
为了更好的进行说明,下面将通过bee工具创建一个beego的项目,如无特殊说明,后续的内容都会以这个测试项目为基础。
将目录切换到$PATH/src
目录,然后执行如下的命令:
bee new mytest
执行结果如下:
项目创建好之后的目录结构如下:
其中,conf
目录主要作用是设置项目的配置信息。controllers
目录为控制器,models
目录为数据库相关内容,routers
目录主要用来设置项目的路由信息,static
目录主要用来存储静态的文件,tests
目录是用来写测试文件,views
目录里面存储的是项目的模板文件,而main.go
是项目的入口程序,
项目的运行
beego项目的运行,首先需要将目录切换到$GOPATH/src/mytest
这个目录下,执行下面的命令:
bee run
项目运行后,打开浏览器,输入地址为localhost:8080
,可以看到beego项目的欢迎页面。
router 路由
基础RESTful 路由
在入口文件main.go
中的代码如下:
package main
import (
_ "mytest/routers"
"github.com/astaxie/beego"
)
func main() {
beego.Run()
}
在代码当中的import
当中引入了routers
,而这个routers
表示的就是项目的路由,下面来具体的说一下路由。
在routers/router.go
文件的代码如下:
package routers
import (
"mytest/controllers"
"github.com/astaxie/beego"
)
func init() {
beego.Router("/", &controllers.MainController{})
}
在上面代码中的init函数中,路由的规则注册通过beego.Router
来进行,第一个参数为路由规则,而第二个参数为路由匹配后要执行的控制器。
首先,我们先来简单的做一个路由测试,如下:
routers/router.go
package routers
import (
"mytest/controllers"
"github.com/astaxie/beego"
)
func init() {
beego.Router("/", &controllers.MainController{})
beego.Router("/mytest", &controllers.MyTestController{})
}
controllers/default.go
package controllers
import (
"github.com/astaxie/beego"
)
type MainController struct {
beego.Controller
}
// 新创建一个controller
type MyTestController struct {
beego.Controller
}
func (c *MainController) Get() {
c.Data["Website"] = "beego.me"
c.Data["Email"] = "astaxie@gmail.com"
c.TplName = "index.tpl"
}
// 重写get方法
func (c *MyTestController) Get() {
c.Ctx.WriteString("hello,this is myTest")
}
在上面的代码中,我们新创建了一个路由规则:/mytest
,当我们访问localhost:8080/mytest
的时候,就会执行对应的控制器。
我们在controllers/default.go
文件中,新创建了一个controllerMyTestController
,用来和/mytest
路由进行匹配。
在beego中,内置支持的基础函数如下:
- beego.Get(router, beego.FilterFunc)
- beego.Post(router, beego.FilterFunc)
- beego.Put(router, beego.FilterFunc)
- beego.Patch(router, beego.FilterFunc)
- beego.Head(router, beego.FilterFunc)
- beego.Options(router, beego.FilterFunc)
- beego.Delete(router, beego.FilterFunc)
- beego.Any(router, beego.FilterFunc)
我们在使用的时候,可以根据需要进行函数的重写,例如,上面的代码中,我们基于MyTestController控制器上重写了GET方法。
我们可以在浏览器中运行localhost:8080/mytest
,运行结果如下:
正则路由
beego为了更加方便的进行路由设置,支持多种方式的路由写法,具体情况如下:
下面针对不同的路由写法逐一的进行说明。
beego.Router(“/api/?:id”, &controllers.RController{})
默认匹配 //例如对于URL”/api/123”可以匹配成功,此时变量”:id”值为”123”
例如:
routers/router.go
package routers
import (
"mytest/controllers"
"github.com/astaxie/beego"
)
func init() {
beego.Router("/", &controllers.MainController{})
beego.Router("/mytest", &controllers.MyTestController{})
beego.Router("/router/?:id", &controllers.MyRouterController{})
}
controllers/default.go
package controllers
import (
"github.com/astaxie/beego"
)
type MainController struct {
beego.Controller
}
// 新创建一个controller
type MyTestController struct {
beego.Controller
}
type MyRouterController struct {
beego.Controller
}
func (c *MainController) Get() {
c.Data["Website"] = "beego.me"
c.Data["Email"] = "astaxie@gmail.com"
c.TplName = "index.tpl"
}
// 重写get方法
func (c *MyTestController) Get() {
c.Ctx.WriteString("hello,this is myTest")
}
func (m *MyRouterController) Get() {
// 获取传递过来的数据
ids := m.Ctx.Input.Param(":id")
// 将传递过来的数据映射到网页当中
m.Ctx.WriteString(ids)
}
运行项目后,输入地址localhost:8080/router/123
,页面输出结果为:
如果我们将路由更改为如下内容,匹配的结果将会发生变化:
func init() {
beego.Router("/", &controllers.MainController{})
beego.Router("/mytest", &controllers.MyTestController{})
// beego.Router("/router/?:id", &controllers.MyRouterController{})
beego.Router("/router/:id", &controllers.MyRouterController{})
}
上面的路由当中,我们把?:id
中的?给去掉,然后在浏览器中输入地址localhost:8080/router/123
是仍然可以匹配的,但是我们一旦不去输入数字就没有办法顺利匹配到相应的内容。
原因在于在正则表达式当中,?
表示匹配零次到一次。
如果说希望匹配具体的数字,也可以通过正则进行修饰,如下:
beego.Router(“/api/:id([0-9]+)“, &controllers.RController{})
自定义正则匹配 //例如对于URL”/api/123”可以匹配成功,此时变量”:id”值为”123”。
如果需要匹配字符串,可以使用类似于下面的路由进行设置:
beego.Router(“/user/:username([\w]+)“, &controllers.RController{})
正则字符串匹配 //例如对于URL”/user/astaxie”可以匹配成功,此时变量”:username”值为”astaxie”.
如果需要匹配请求地址当中的文件名和文件后缀,路由可以进行类似如下的设置:
beego.Router(“/download/*.*”, &controllers.RController{})
例如:
routers/router.go
package routers
import (
"mytest/controllers"
"github.com/astaxie/beego"
)
func init() {
beego.Router("/", &controllers.MainController{})
beego.Router("/mytest", &controllers.MyTestController{})
// beego.Router("/router/?:id", &controllers.MyRouterController{})
beego.Router("/router/:id", &controllers.MyRouterController{})
beego.Router("/router/*.*", &controllers.MyRouterFileController{})
}
controllers/default.go
package controllers
import (
"github.com/astaxie/beego"
)
type MainController struct {
beego.Controller
}
// 新创建一个controller
type MyTestController struct {
beego.Controller
}
type MyRouterController struct {
beego.Controller
}
type MyRouterFileController struct {
beego.Controller
}
func (c *MainController) Get() {
c.Data["Website"] = "beego.me"
c.Data["Email"] = "astaxie@gmail.com"
c.TplName = "index.tpl"
}
// 重写get方法
func (c *MyTestController) Get() {
c.Ctx.WriteString("hello,this is myTest")
}
func (m *MyRouterController) Get() {
// 获取传递过来的数据
ids := m.Ctx.Input.Param(":id")
m.Ctx.WriteString(ids)
}
func (m *MyRouterFileController) Get() {
// 获取文件名 :path
paths := m.Ctx.Input.Param(":path")
// 获取文件名后缀 :ext
exts := m.Ctx.Input.Param(":ext")
m.Ctx.WriteString(paths)
m.Ctx.WriteString(exts)
}
项目运行后,在浏览器地址中输入localhost:8080/router/my.xml
,输出内容为:
如果需要一次性匹配完整的文件,可以如下:
beego.Router(“/download/ceshi/*“, &controllers.RController{})
例如,我们可以直接将上面的路由改为如下:
beego.Router("/router/*", &controllers.MyRouterFileController{})
控制器的Get方法改为如下:
func (m *MyRouterFileController) Get() {
// 获取文件名 :path
// paths := m.Ctx.Input.Param(":path")
// // 获取文件名后缀 :ext
// exts := m.Ctx.Input.Param(":ext")
// m.Ctx.WriteString(paths)
splats := m.Ctx.Input.Param(":splat")
m.Ctx.WriteString(splats)
}
在浏览器当中输入地址localhost:8080/router/my.json
,输出结果如下:
在beego中,如果需要匹配数字,可以直接通过:int
来实现。
例如:
beego.Router(“/:id:int”, &controllers.RController{})
如果需要匹配字符串,可以直接通过:string
来实现。
例如:
beego.Router(“/:hi:string”, &controllers.RController{})
可以在 Controller 中通过如下方式获取上面的变量:
this.Ctx.Input.Param(":id") this.Ctx.Input.Param(":username") this.Ctx.Input.Param(":splat") this.Ctx.Input.Param(":path") this.Ctx.Input.Param("::ext")
自定义方法
上面列举的是默认的请求方法名(请求的 method 和函数名一致,例如 GET
请求执行 Get
函数,POST
请求执行 Post
函数),如果用户期望自定义函数名,那么可以使用如下方式:
beego.Router("/",&IndexController{},"*:Index")
第一个参数为路由,第二个参数是控制器,第三个参数是用来设置路由请求对应的method,定义如下:
*
表示任意的 method 都执行该函数- 使用 httpmethod:funcname 格式来展示
- 多个不同的格式使用
;
分割 - 多个 method 对应同一个 funcname,method 之间通过
,
来分割
例如,
routers/router.go
beego.Router("/router/hello", &controllers.MyRouterHelloController{}, "get:HelloFunc")
通过第三个参数来重写get方法。
controllers/default.go
type MyRouterHelloController struct {
beego.Controller
}
func (m *MyRouterHelloController) HelloFunc() {
m.Ctx.WriteString("hello,world")
}
在浏览器当中输入localhost:8080/router/hello
,可以查看如下:
可用的http method:
- *: 包含以下所有的函数
- get: GET 请求
- post: POST 请求
- put: PUT 请求
- delete: DELETE 请求
- patch: PATCH 请求
- options: OPTIONS 请求
- head: HEAD 请求
如果同时存在 * 和对应的 HTTP Method,那么优先执行 HTTP Method 的方法,例如同时注册了如下所示的路由:
beego.Router("/simple",&SimpleController{},"*:AllFunc;post:PostFunc")
那么执行 POST
请求的时候,执行 PostFunc
而不执行 AllFunc
。
上面说明了beego框架中常用的路由写法,具体的内容可以参照官网文档进行学习。
操作数据库
在beego框架中,既可以通过sql语句来实现对数据库的操作,也可以通过orm来实现对数据库的操作。下面来进行具体的说明。
通过sql语句操作数据库
beego当中支持通过sql语句来操作数据库。但是在使用之前,需要先通过go get命令安装mysql的驱动。
go get -u github.com/go-sql-driver/mysql
具体的应用如下:
routers/router.go
package routers
import (
"mytest/controllers"
"github.com/astaxie/beego"
)
func init() {
beego.Router("/", &controllers.MainController{})
beego.Router("/mytest", &controllers.MyTestController{})
// beego.Router("/router/?:id", &controllers.MyRouterController{})
beego.Router("/router/:id", &controllers.MyRouterController{})
// beego.Router("/router/*.*", &controllers.MyRouterFileController{})
beego.Router("/router/*", &controllers.MyRouterFileController{})
beego.Router("/router/hello", &controllers.MyRouterHelloController{}, "get:HelloFunc")
// 设置sql操作的路由
beego.Router("/mysql/sql", &controllers.MySqlTestSqlController{}, "get:SqlFunc")
}
controllers/mysqltest.go
package controllers
import (
"database/sql"
"github.com/astaxie/beego"
_ "github.com/go-sql-driver/mysql"
)
type MySqlTestSqlController struct {
beego.Controller
}
const (
db = "mysql"
user = "root"
pass = "123456"
host = "127.0.0.1"
port = "3306"
char = "charset=utf8"
data = "learngo1"
)
func (this *MySqlTestSqlController) SqlFunc() {
//创建一个数据表
// 第一步,链接数据库
params := user + ":" + pass + "@tcp(" + host + ":" + port + ")/" + data + "?" + char
// 1. 打开数据库
conn, err := sql.Open(db, params)
if err != nil {
beego.Error("数据库链接错误:", err)
return
}
// 2. 通过defer关闭数据库
defer conn.Close()
// 第二步,操作数据库
// 1. 设置sql语句
create_sql := `CREATE TABLE mytest1 ( userid INT PRIMARY KEY AUTO_INCREMENT, username varchar(255) NOT NULL ) ENGINE = InnoDB CHARSET = utf8;`
// 2. 执行sql语句
_, err2 := conn.Exec(create_sql)
if err2 != nil {
beego.Error("执行sql错误:", err2)
return
}
this.Ctx.WriteString("创建数据表成功")
}
上面的代码当中,我们设置了创建数据表的sql语句,当我们访问localhost:8080/mysql/sql
地址后,就可以直接在数据库创建一个数据表。
上面代码完成的是执行操作,通过Exec
函数来完成。下面我们来实现sql语句的增删改查操作。
routers/router.go
package routers
import (
"mytest/controllers"
"github.com/astaxie/beego"
)
func init() {
beego.Router("/", &controllers.MainController{})
beego.Router("/mytest", &controllers.MyTestController{})
// beego.Router("/router/?:id", &controllers.MyRouterController{})
beego.Router("/router/:id", &controllers.MyRouterController{})
// beego.Router("/router/*.*", &controllers.MyRouterFileController{})
beego.Router("/router/*", &controllers.MyRouterFileController{})
beego.Router("/router/hello", &controllers.MyRouterHelloController{}, "get:HelloFunc")
// 设置sql操作的路由
beego.Router("/mysql/sql", &controllers.MySqlTestSqlController{}, "get:SqlFunc")
// 通过sql语句实现增删改操作
beego.Router("/mysql/insert", &controllers.MySqlTestSqlController{}, "get:InsertFunc")
beego.Router("/mysql/update", &controllers.MySqlTestSqlController{}, "get:UpdateFunc")
beego.Router("/mysql/del", &controllers.MySqlTestSqlController{}, "get:DelFunc")
beego.Router("/mysql/search", &controllers.MySqlTestSqlController{}, "get:SearchFunc")
}
controllers/mytestsql.go
package controllers
import (
"database/sql"
"github.com/astaxie/beego"
_ "github.com/go-sql-driver/mysql"
)
type MySqlTestSqlController struct {
beego.Controller
}
type users struct {
userid int
username string
}
const (
db = "mysql"
user = "root"
pass = "123456"
host = "127.0.0.1"
port = "3306"
char = "charset=utf8"
data = "learngo1"
)
func (this *MySqlTestSqlController) SqlFunc() {
//创建一个数据表
// 第一步,链接数据库
params := user + ":" + pass + "@tcp(" + host + ":" + port + ")/" + data + "?" + char
// 1. 打开数据库
conn, err := sql.Open(db, params)
if err != nil {
beego.Error("数据库链接错误:", err)
return
}
// 通过defer关闭数据库
defer conn.Close()
// 第二步,操作数据库
// 1. 设置sql语句
create_sql := `CREATE TABLE mytest1 ( userid INT PRIMARY KEY AUTO_INCREMENT, username varchar(255) NOT NULL ) ENGINE = InnoDB CHARSET = utf8;`
// 2. 执行sql语句
_, err2 := conn.Exec(create_sql)
if err2 != nil {
beego.Error("执行sql错误:", err2)
return
}
this.Ctx.WriteString("创建数据表成功")
}
func (this *MySqlTestSqlController) InsertFunc() {
params := user + ":" + pass + "@tcp(" + host + ":" + port + ")/" + data + "?" + char
conn, err := sql.Open(db, params)
if err != nil {
beego.Error("数据库链接错误:", err)
return
}
defer conn.Close()
// 设置sql语句
sql := `insert into mytest1(username) values("张三")`
// 执行sql语句
_, err = conn.Exec(sql)
if err != nil {
beego.Error("插入数据错误:", err)
return
}
this.Ctx.WriteString("插入数据成功")
}
func (this *MySqlTestSqlController) UpdateFunc() {
params := user + ":" + pass + "@tcp(" + host + ":" + port + ")/" + data + "?" + char
conn, err := sql.Open(db, params)
if err != nil {
beego.Error("数据库链接错误:", err)
return
}
defer conn.Close()
// 设置sql语句
sql := `update mytest1 set username = "晓晓" where userid = 1`
// 执行sql语句
_, err = conn.Exec(sql)
if err != nil {
beego.Error("更改数据错误:", err)
return
}
this.Ctx.WriteString("更改数据成功")
}
func (this *MySqlTestSqlController) DelFunc() {
params := user + ":" + pass + "@tcp(" + host + ":" + port + ")/" + data + "?" + char
conn, err := sql.Open(db, params)
if err != nil {
beego.Error("数据库链接错误:", err)
return
}
defer conn.Close()
// 设置sql语句
sql := `delete from mytest1 where userid = 1`
// 执行sql语句
_, err = conn.Exec(sql)
if err != nil {
beego.Error("删除数据错误:", err)
return
}
this.Ctx.WriteString("删除数据成功")
}
func (this *MySqlTestSqlController) SearchFunc() {
params := user + ":" + pass + "@tcp(" + host + ":" + port + ")/" + data + "?" + char
conn, err := sql.Open(db, params)
if err != nil {
beego.Error("数据库链接错误:", err)
return
}
defer conn.Close()
// 设置sql语句
sql := `select * from mytest1`
// 执行sql语句
//
res, errSearch := conn.Query(sql)
if errSearch != nil {
beego.Error("查询数据错误:", errSearch)
return
}
var u users
// 打印查询结果
for res.Next() {
res.Scan(&u.userid, &u.username)
beego.Info("id:", u.userid, ",name:", u.username)
}
this.Ctx.WriteString("查询数据成功")
}
在上面的代码中,我们在增删改的操作中使用了Exec()函数,在查询的过程中使用了Query函数,但是除了这些函数以外,还有其他的函数,可以点击 这里查看。
使用ORM操作数据库
首先,在使用orm之前还是需要通过go get命令下载orm。
go get github.com/astaxie/beego/orm
安装完成之后就可以使用orm来进行数据库的增删改查操作。
orm的使用需要通过创建一个结构体与数据表进行相对应。例如数据表的结构如下:
我们需要创建一个结构体与数据表对应,如下:
type Mytest1 struct {
Userid int
Username string
}
同时,想要使用orm,需要对数据库进行初始化的设置,我们可以把这些初始化设置放在models模块里面的model.go中的init函数中。
func init() {
// 链接数据库
orm.RegisterDataBase("default", "mysql", "root:123456@tcp(127.0.0.1:3306)/learngo1?charset=utf8")
// 注册表
orm.RegisterModel(new(Mytest1))
// 生成表 false 为禁止强制更新 true为强制更新 第三个参数是是否查看创建表的过程
orm.RunSyncdb("default", false, true)
}
这样方便在controller中通过orm操作数据库。
上面的步骤设置完成之后,可以在main.go的入口文件当中引入。
package main
import (
_ "mytest/models"
_ "mytest/routers"
"github.com/astaxie/beego"
)
func main() {
beego.Run()
}
当我们在将上面的基础代码写完之后,就可以通过orm进行操作数据库啦。
完整示例如下:
routers/router.go
package routers
import (
"mytest/controllers"
"github.com/astaxie/beego"
)
func init() {
beego.Router("/", &controllers.MainController{})
beego.Router("/mytest", &controllers.MyTestController{})
// beego.Router("/router/?:id", &controllers.MyRouterController{})
beego.Router("/router/:id", &controllers.MyRouterController{})
// beego.Router("/router/*.*", &controllers.MyRouterFileController{})
beego.Router("/router/*", &controllers.MyRouterFileController{})
beego.Router("/router/hello", &controllers.MyRouterHelloController{}, "get:HelloFunc")
// 设置sql操作的路由
beego.Router("/mysql/sql", &controllers.MySqlTestSqlController{}, "get:SqlFunc")
// 通过sql语句实现增删改操作
beego.Router("/mysql/insert", &controllers.MySqlTestSqlController{}, "get:InsertFunc")
beego.Router("/mysql/update", &controllers.MySqlTestSqlController{}, "get:UpdateFunc")
beego.Router("/mysql/del", &controllers.MySqlTestSqlController{}, "get:DelFunc")
beego.Router("/mysql/search", &controllers.MySqlTestSqlController{}, "get:SearchFunc")
// 设置orm操作的路由
beego.Router("/mysql/orm/insert", &controllers.MysqlTestOrmController{}, "get:OrmInsertFunc")
beego.Router("/mysql/orm/update", &controllers.MysqlTestOrmController{}, "get:OrmUpdateFunc")
beego.Router("/mysql/orm/del", &controllers.MysqlTestOrmController{}, "get:OrmDelFunc")
beego.Router("/mysql/orm/search", &controllers.MysqlTestOrmController{}, "get:OrmSearchFunc")
}
controllers/mytestorm.go
package controllers
import (
"mytest/models"
"github.com/astaxie/beego"
"github.com/astaxie/beego/orm"
_ "github.com/go-sql-driver/mysql"
)
type MysqlTestOrmController struct {
beego.Controller
}
func (this *MysqlTestOrmController) OrmInsertFunc() {
o := orm.NewOrm()
o.Using("default")
stu := models.Mytest1{}
stu.Username = "张三丰"
_, err := o.Insert(&stu)
if err != nil {
beego.Error("添加错误:", err)
return
}
this.Ctx.WriteString("添加成功")
}
func (this *MysqlTestOrmController) OrmUpdateFunc() {
// 获取orm对象
o := orm.NewOrm()
// 获取更新对象
stu := models.Mytest1{Userid: 2}
// 查询对象
err := o.Read(&stu)
if err != nil {
beego.Error("查询数据错误:", err)
return
}
// 给查询到的对象进行重新赋值
stu.Username = "hello先生"
// 进行更新操作
_, err = o.Update(&stu)
if err != nil {
beego.Error("更新失败:", err)
return
}
this.Ctx.WriteString("更新成功")
}
func (this *MysqlTestOrmController) OrmDelFunc() {
// 获取orm对象
o := orm.NewOrm()
// 获取删除对象
stu := models.Mytest1{Userid: 2}
// 通过方法进行删除
_, err := o.Delete(&stu)
if err != nil {
beego.Error("删除失败:", err)
return
}
this.Ctx.WriteString("删除成功")
}
func (this *MysqlTestOrmController) OrmSearchFunc() {
x := orm.NewOrm()
x.Using("default")
stu := models.Mytest1{Userid: 3}
err := x.Read(&stu)
if err != nil {
beego.Error("查询失败:", err)
return
}
beego.Info(stu.Username)
this.Ctx.WriteString("查询成功")
}