beego框架入门(2)

beego框架的mvc

beego框架是一款典型的MVC框架,执行逻辑如下:

本图来自beego官网,具体的说明可以点击 这里查看具体说明。

创建一个项目

为了更好的进行说明,下面将通过bee工具创建一个beego的项目,如无特殊说明,后续的内容都会以这个测试项目为基础。

$PATH/src
bee new mytest

执行结果如下:

项目创建好之后的目录结构如下:

confcontrollersmodelsroutersstatictestsviewsmain.go

项目的运行

$GOPATH/src/mytest
bee run

localhost:8080

router 路由

基础RESTful 路由

main.go
package main

import (
	_ "mytest/routers"
	"github.com/astaxie/beego"
)

func main() {
	beego.Run()
}
importroutersrouters
routers/router.go
package routers

import (
	"mytest/controllers"
	"github.com/astaxie/beego"
)

func init() {
    beego.Router("/", &controllers.MainController{})
}
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")
}
/mytestlocalhost:8080/mytest
controllers/default.goMyTestController/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{})
}
?:idlocalhost: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

:int

例如:

beego.Router(“/:id:int”, &controllers.RController{})
:string

例如:

beego.Router(“/:hi:string”, &controllers.RController{})
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")

自定义方法

GETGetPOSTPost
beego.Router("/",&IndexController{},"*:Index")

第一个参数为路由,第二个参数是控制器,第三个参数是用来设置路由请求对应的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")
POSTPostFuncAllFunc

上面说明了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("创建数据表成功")

}
localhost:8080/mysql/sql

Exec

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("查询成功")
}