beego 是一个用于Go编程语言的开源、高性能的 web 框架
beego 被用于在Go语言中企业应用程序的快速开发,包括RESTful API、web应用程序和后端服务。它的灵感来源于Tornado, Sinatra 和 Flask
beego 官网:http://beego.gocn.vip/
上面的 beego 官网如果访问不到,看这篇文章《beego 官网文档本地环境搭建》
注意:本文的 beego 文档使用的就是本地环境搭建的文档,因为官网文档已经不可用了
beego 官方 github 仓库:https://github.com/beego/beego
上一讲,讲了 beego 过滤器部分内容,需要的朋友可以查看《Beego 使用教程 4:过滤器》
这一讲,讲解 页面视图
代码使用上一讲的代码
目录
1、返回页面
2、模板数据
2.1、返回字符串
2.2、返回结构体
2.3、返回 map
2.4、返回切片
3、模板函数
3.1、格式化时间函数
3.2、html 和字符串转换函数
3.3、自定义模板函数
3.4、其他模板函数
4、静态文件
5、Layout 设计
1、返回页面
在 controller 目录下新建 page.go,在 page.go 中添加下面代码
package controller
import (
	"github.com/beego/beego/v2/server/web"
)
type PageController struct {
	web.Controller
}
func (p *PageController) Index() {
	//返回页面
	p.TplName = "index.html"
}
 
Beego 默认情况下支持 tpl 和 html 后缀名的模板文件,如果你的后缀名不是这两种,请进行如下设置
web.AddTemplateExt("你文件的后缀名") 
在项目根目录下新建 views 目录,Beego 中默认的模板目录是 views,可以通过配置 web.BConfig.WebConfig.ViewsPath = "pages" 修改默认的模版目录名称,笔者使用默认的模版目录
在 views 目录下新建 index.html,index.html 内容如下
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>灵种传闻出越裳,何人提挈上蛮航。他年我若修花史,列作人间第一香</h1>
</body>
</html> 

修改 main.go 为下面代码
package main
import (
	"beego-demo/controller"
	"beego-demo/filter"
	"fmt"
	"github.com/beego/beego/v2/core/config"
	"github.com/beego/beego/v2/server/web"
)
func main() {
	//通过config获取自定义配置
	workername, _ := config.String("workername")
	fmt.Println(workername)
	//执行定时任务
	//go job.DemoTask()
	//注册自动路由
	//web.AutoPrefix("api", &controller.UserController{})
	web.CtrlGet("/name", (*controller.UserController).Name)
	web.CtrlGet("/get/:id", (*controller.UserController).GetUserById)
	web.CtrlGet("/get/:id/:num", (*controller.UserController).GetUserByIdAndNum)
	//返回页面
	web.CtrlGet("/page/index", (*controller.PageController).Index)
	//注册函数式路由
	controller.RegisterFunctionalRoutes()
	//web命名空间
	controller.RegisterNamespaceRoutes()
	//过滤器
	filter.RegisterFilters()
	//开启 Admin 管理后台
	web.BConfig.Listen.EnableAdmin = true
	web.BConfig.Listen.AdminAddr = "localhost"
	web.BConfig.Listen.AdminPort = 8088
	//查看已注册路由
	tree := web.PrintTree()
	methods := tree["Data"].(web.M)
	for k, v := range methods {
		fmt.Printf("%s => %v\n", k, v)
	}
	web.Run()
}
 
运行效果
浏览器请求:http://localhost:9090/page/index

修改 页面模版文件位置,在main.go 中添加下面代码
web.BConfig.WebConfig.ViewsPath = "pages" 
在项目根目录下新建 pages 目录,在pages 目录下新建 index.tpl 文件
index.tpl 内容如下
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>灵种传闻出越裳,何人提挈上蛮航。他年我若修花史,列作人间第一香</h1>
</body>
</html> 
修改 page.go 为下面代码
package controller
import (
	"github.com/beego/beego/v2/server/web"
)
type PageController struct {
	web.Controller
}
func (p *PageController) Index() {
	//返回页面
	//p.TplName = "index.html"
	p.TplName = "index.tpl"
}
 
main.go
package main
import (
	"beego-demo/controller"
	"beego-demo/filter"
	"fmt"
	"github.com/beego/beego/v2/core/config"
	"github.com/beego/beego/v2/server/web"
)
func main() {
	//通过config获取自定义配置
	workername, _ := config.String("workername")
	fmt.Println(workername)
	//执行定时任务
	//go job.DemoTask()
	//注册自动路由
	//web.AutoPrefix("api", &controller.UserController{})
	web.CtrlGet("/name", (*controller.UserController).Name)
	web.CtrlGet("/get/:id", (*controller.UserController).GetUserById)
	web.CtrlGet("/get/:id/:num", (*controller.UserController).GetUserByIdAndNum)
	//返回页面
	web.CtrlGet("/page/index", (*controller.PageController).Index)
	//注册函数式路由
	controller.RegisterFunctionalRoutes()
	//web命名空间
	controller.RegisterNamespaceRoutes()
	//过滤器
	filter.RegisterFilters()
	//开启 Admin 管理后台
	web.BConfig.Listen.EnableAdmin = true
	web.BConfig.Listen.AdminAddr = "localhost"
	web.BConfig.Listen.AdminPort = 8088
	web.BConfig.WebConfig.ViewsPath = "pages"
	//查看已注册路由
	tree := web.PrintTree()
	methods := tree["Data"].(web.M)
	for k, v := range methods {
		fmt.Printf("%s => %v\n", k, v)
	}
	web.Run()
}
 
运行效果

2、模板数据
下面的代码笔者使用 views 下的模板文件
2.1、返回字符串
修改 page.go 为下面内容
package controller
import (
	"github.com/beego/beego/v2/server/web"
)
type PageController struct {
	web.Controller
}
func (p *PageController) Index() {
	p.Data["content"] = "如许闲宵似广寒,翠丛倒影浸冰团。梅花宜冷君宜热,一样香魂两样看"
	//返回页面
	p.TplName = "index.html"
	//p.TplName = "index.tpl"
}
 
修改 index.html 为下面内容
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>灵种传闻出越裳,何人提挈上蛮航。他年我若修花史,列作人间第一香</h1>
    <p>{{.content}}</p>
</body>
</html> 
运行效果

2.2、返回结构体
修改 page.go 为下面内容
package controller
import (
	"github.com/beego/beego/v2/server/web"
)
type PageController struct {
	web.Controller
}
type Poetry struct {
	Name    string
	Author  string
	Content string
}
func (p *PageController) Index() {
	//p.Data["content"] = "如许闲宵似广寒,翠丛倒影浸冰团。梅花宜冷君宜热,一样香魂两样看"
	poetry := Poetry{
		Name:    "茉莉花",
		Author:  "许景迂",
		Content: "自是天上冰雪种,占尽人间富贵香。不烦鼻观偷馥郁,解使心俱清凉。南船卖客俱到岸,东道主人容寄廊",
	}
	p.Data["poetry"] = &poetry
	//返回页面
	p.TplName = "index.html"
	//p.TplName = "index.tpl"
}
 
修改 index.html 为下面内容
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>灵种传闻出越裳,何人提挈上蛮航。他年我若修花史,列作人间第一香</h1>
    <p>{{.poetry.Name}}</p>
    <p>{{.poetry.Author}}</p>
    <p>{{.poetry.Content}}</p>
</body>
</html> 
重启后运行效果

2.3、返回 map
修改 page.go 为下面内容
package controller
import (
	"github.com/beego/beego/v2/server/web"
)
type PageController struct {
	web.Controller
}
type Poetry struct {
	Name    string
	Author  string
	Content string
}
func (p *PageController) Index() {
	//p.Data["content"] = "如许闲宵似广寒,翠丛倒影浸冰团。梅花宜冷君宜热,一样香魂两样看"
	//poetry := Poetry{
	//	Name:    "茉莉花",
	//	Author:  "许景迂",
	//	Content: "自是天上冰雪种,占尽人间富贵香。不烦鼻观偷馥郁,解使心俱清凉。南船卖客俱到岸,东道主人容寄廊",
	//}
	//p.Data["poetry"] = &poetry
	mp := make(map[string]string)
	mp["name"] = "茉莉花"
	mp["author"] = "江奎"
	mp["content"] = "虽无艳态惊群目,幸有清香压九秋。应是仙娥宴归去,醉来掉下玉搔头"
	p.Data["mp"] = mp
	//返回页面
	p.TplName = "index.html"
	//p.TplName = "index.tpl"
}
 
修改 index.html 为下面内容
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>灵种传闻出越裳,何人提挈上蛮航。他年我若修花史,列作人间第一香</h1>
    <p>{{.mp.name}}</p>
    <p>{{.mp.author}}</p>
    <p>{{.mp.content}}</p>
</body>
</html> 
运行效果

2.4、返回切片
修改 page.go 为下面内容
package controller
import (
	"github.com/beego/beego/v2/server/web"
)
type PageController struct {
	web.Controller
}
type Poetry struct {
	Name    string
	Author  string
	Content string
}
func (p *PageController) Index() {
	//p.Data["content"] = "如许闲宵似广寒,翠丛倒影浸冰团。梅花宜冷君宜热,一样香魂两样看"
	//poetry := Poetry{
	//	Name:    "茉莉花",
	//	Author:  "许景迂",
	//	Content: "自是天上冰雪种,占尽人间富贵香。不烦鼻观偷馥郁,解使心俱清凉。南船卖客俱到岸,东道主人容寄廊",
	//}
	//p.Data["poetry"] = &poetry
	//mp := make(map[string]string)
	//mp["name"] = "茉莉花"
	//mp["author"] = "江奎"
	//mp["content"] = "虽无艳态惊群目,幸有清香压九秋。应是仙娥宴归去,醉来掉下玉搔头"
	//p.Data["mp"] = mp
	flowers := []string{"梅", "兰", "竹", "菊"}
	p.Data["flowers"] = flowers
	//返回页面
	p.TplName = "index.html"
	//p.TplName = "index.tpl"
}
 
修改 index.html 为下面内容
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>灵种传闻出越裳,何人提挈上蛮航。他年我若修花史,列作人间第一香</h1>
    {{range $key, $val := .flowers}} {{$key}} {{$val}} {{end}}
</body>
</html> 
运行效果

3、模板函数
3.1、格式化时间函数
在 page.go 中添加 F 函数
package controller
import (
	"github.com/beego/beego/v2/server/web"
	"time"
)
type PageController struct {
	web.Controller
}
type Poetry struct {
	Name    string
	Author  string
	Content string
}
func (p *PageController) Index() {
	//p.Data["content"] = "如许闲宵似广寒,翠丛倒影浸冰团。梅花宜冷君宜热,一样香魂两样看"
	//poetry := Poetry{
	//	Name:    "茉莉花",
	//	Author:  "许景迂",
	//	Content: "自是天上冰雪种,占尽人间富贵香。不烦鼻观偷馥郁,解使心俱清凉。南船卖客俱到岸,东道主人容寄廊",
	//}
	//p.Data["poetry"] = &poetry
	//mp := make(map[string]string)
	//mp["name"] = "茉莉花"
	//mp["author"] = "江奎"
	//mp["content"] = "虽无艳态惊群目,幸有清香压九秋。应是仙娥宴归去,醉来掉下玉搔头"
	//p.Data["mp"] = mp
	flowers := []string{"梅", "兰", "竹", "菊"}
	p.Data["flowers"] = flowers
	//返回页面
	p.TplName = "index.html"
	//p.TplName = "index.tpl"
}
func (p *PageController) F() {
	p.Data["date"] = time.Now()
	p.TplName = "f.html"
}
 
在 views 下新建 f.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <p>{{ dateformat .date "2006-01-02 15:04:05" }}</p>
    <p>{{date .date "Y-m-d H:i:s"}}</p>
</body>
</html> 
修改 main.go 为下面内容
package main
import (
	"beego-demo/controller"
	"beego-demo/filter"
	"fmt"
	"github.com/beego/beego/v2/core/config"
	"github.com/beego/beego/v2/server/web"
)
func main() {
	//通过config获取自定义配置
	workername, _ := config.String("workername")
	fmt.Println(workername)
	//执行定时任务
	//go job.DemoTask()
	//注册自动路由
	//web.AutoPrefix("api", &controller.UserController{})
	web.CtrlGet("/name", (*controller.UserController).Name)
	web.CtrlGet("/get/:id", (*controller.UserController).GetUserById)
	web.CtrlGet("/get/:id/:num", (*controller.UserController).GetUserByIdAndNum)
	//返回页面
	web.CtrlGet("/page/index", (*controller.PageController).Index)
	web.CtrlGet("/page/f", (*controller.PageController).F)
	//注册函数式路由
	controller.RegisterFunctionalRoutes()
	//web命名空间
	controller.RegisterNamespaceRoutes()
	//过滤器
	filter.RegisterFilters()
	//开启 Admin 管理后台
	web.BConfig.Listen.EnableAdmin = true
	web.BConfig.Listen.AdminAddr = "localhost"
	web.BConfig.Listen.AdminPort = 8088
	//web.BConfig.WebConfig.ViewsPath = "pages"
	//查看已注册路由
	tree := web.PrintTree()
	methods := tree["Data"].(web.M)
	for k, v := range methods {
		fmt.Printf("%s => %v\n", k, v)
	}
	web.Run()
}
 
运行效果

3.2、html 和字符串转换函数
html2str 函数,实现了把 html 转化为字符串,剔除一些 script、css 之类的元素,返回纯文本信息
str2html 函数,实现了把相应的字符串当作 HTML 来输出,不转义
修改 page.go 为下面内容
package controller
import (
	"github.com/beego/beego/v2/server/web"
)
type PageController struct {
	web.Controller
}
type Poetry struct {
	Name    string
	Author  string
	Content string
}
func (p *PageController) Index() {
	//p.Data["content"] = "如许闲宵似广寒,翠丛倒影浸冰团。梅花宜冷君宜热,一样香魂两样看"
	//poetry := Poetry{
	//	Name:    "茉莉花",
	//	Author:  "许景迂",
	//	Content: "自是天上冰雪种,占尽人间富贵香。不烦鼻观偷馥郁,解使心俱清凉。南船卖客俱到岸,东道主人容寄廊",
	//}
	//p.Data["poetry"] = &poetry
	//mp := make(map[string]string)
	//mp["name"] = "茉莉花"
	//mp["author"] = "江奎"
	//mp["content"] = "虽无艳态惊群目,幸有清香压九秋。应是仙娥宴归去,醉来掉下玉搔头"
	//p.Data["mp"] = mp
	flowers := []string{"梅", "兰", "竹", "菊"}
	p.Data["flowers"] = flowers
	//返回页面
	p.TplName = "index.html"
	//p.TplName = "index.tpl"
}
func (p *PageController) F() {
	mp := make(map[string]string)
	mp["str"] = "<p style='color:red'>环佩青衣,盈盈素靥,临风无限清幽<p>"
	mp["html"] = "<p style='color:red'>出尘标格,和月最温柔。堪爱芳怀淡雅,纵离别,未肯衔愁<p>"
	p.Data["mp"] = mp
	p.TplName = "f.html"
}
 
修改 index.html 为下面内容
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    {{.mp.str}}
    <br>
    {{html2str .mp.str}}
    <br>
    {{.mp.html}}
    <br>
    {{str2html .mp.html}}
</body>
</html> 
运行效果

3.3、自定义模板函数
Beego 支持用户定义模板函数,但是必须在 web.Run() 调用之前
修改 main.go 为下面代码
package main
import (
	"beego-demo/controller"
	"beego-demo/filter"
	"fmt"
	"github.com/beego/beego/v2/core/config"
	"github.com/beego/beego/v2/server/web"
)
func main() {
	//通过config获取自定义配置
	workername, _ := config.String("workername")
	fmt.Println(workername)
	//执行定时任务
	//go job.DemoTask()
	//注册自动路由
	//web.AutoPrefix("api", &controller.UserController{})
	web.CtrlGet("/name", (*controller.UserController).Name)
	web.CtrlGet("/get/:id", (*controller.UserController).GetUserById)
	web.CtrlGet("/get/:id/:num", (*controller.UserController).GetUserByIdAndNum)
	//返回页面
	web.CtrlGet("/page/index", (*controller.PageController).Index)
	web.CtrlGet("/page/f", (*controller.PageController).F)
	//注册函数式路由
	controller.RegisterFunctionalRoutes()
	//web命名空间
	controller.RegisterNamespaceRoutes()
	//过滤器
	filter.RegisterFilters()
	//开启 Admin 管理后台
	web.BConfig.Listen.EnableAdmin = true
	web.BConfig.Listen.AdminAddr = "localhost"
	web.BConfig.Listen.AdminPort = 8088
	//web.BConfig.WebConfig.ViewsPath = "pages"
	//查看已注册路由
	tree := web.PrintTree()
	methods := tree["Data"].(web.M)
	for k, v := range methods {
		fmt.Printf("%s => %v\n", k, v)
	}
	//自定义模板函数
	web.AddFuncMap("bookName", bookName)
	web.Run()
}
// 自定义模板函数添加书名号
func bookName(in string) (out string) {
	out = "《" + in + "》"
	return
}
 
添加一个生成书名号的模板函数
修改 index.html 为下面内容
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    {{.name | bookName}}
</body>
</html> 
运行效果

3.4、其他模板函数
更多的模版函数可以参考 Beego 文档
4、静态文件
Beego 默认会将项目根目录下的 static 目录作为静态资源的存目录,请求静态资源默认添加前缀 /static,这个官方文档没有说,可以通过查看 Beego 项目源代码中的注释知道

自定义静态资源目录可以通过 web.SetStaticPath 函数添加
如下代码将目录 public 作为静态目录,请求前缀是 staticfile
web.SetStaticPath("/staticfile", "public") 
在项目根目录下新建 static 目录,在statc 目录下新建 index.js 和 index.css 文件
index.css
.poetry {
    background: aqua;
} 
index.js
function test(){
    var content = "咏院中丛竹"
    alert(content)
} 
修改 index.html 为下面代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link href="/static/index.css" type="text/css" rel="stylesheet" />
    <script src="/static/index.js"></script>
</head>
<body>
    <h1>灵种传闻出越裳,何人提挈上蛮航。他年我若修花史,列作人间第一香</h1>
    <div class="poetry">
        <p>擢擢当轩竹,青青重岁寒。</p>
        <p>心贞徒见赏,箨小未成竿。</p>
    </div>
    <button onclick="test()">测试</button>
</body>
</html> 
重启项目运行测试

5、Layout 设计
Beego 支持 layout 设计,例如你在管理系统中,整个管理界面是固定的,只会变化中间的部分
在 views 目录下新建 main.html,内容如下
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>main</h1>
<div>{{.Header}}</div>
<div class="container">{{.LayoutContent}}</div>
</body>
</html> 
这里面,.Header 是可以随意定义的,笔者表示引入固定的header 部分,.LayoutContent 是Beego 规定的,用来表示页面中间变化的部分
在 views 目录下新建 header.html,代码看下面
<div>
  <h2>头部</h2>
</div> 
在 views 目录下新建 login.html,表示页面中间的部分,代码看下面
<div>
    <h2>登录</h2>
</div> 
在 page.go 中修改为下面代码
package controller
import (
	"github.com/beego/beego/v2/server/web"
)
type PageController struct {
	web.Controller
}
type Poetry struct {
	Name    string
	Author  string
	Content string
}
func (p *PageController) Index() {
	//p.Data["content"] = "如许闲宵似广寒,翠丛倒影浸冰团。梅花宜冷君宜热,一样香魂两样看"
	//poetry := Poetry{
	//	Name:    "茉莉花",
	//	Author:  "许景迂",
	//	Content: "自是天上冰雪种,占尽人间富贵香。不烦鼻观偷馥郁,解使心俱清凉。南船卖客俱到岸,东道主人容寄廊",
	//}
	//p.Data["poetry"] = &poetry
	//mp := make(map[string]string)
	//mp["name"] = "茉莉花"
	//mp["author"] = "江奎"
	//mp["content"] = "虽无艳态惊群目,幸有清香压九秋。应是仙娥宴归去,醉来掉下玉搔头"
	//p.Data["mp"] = mp
	flowers := []string{"梅", "兰", "竹", "菊"}
	p.Data["flowers"] = flowers
	//返回页面
	p.TplName = "index.html"
	//p.TplName = "index.tpl"
}
func (p *PageController) F() {
	p.Data["name"] = "水浒传"
	p.TplName = "f.html"
}
func (p *PageController) Main() {
	p.LayoutSections = make(map[string]string)
	p.LayoutSections["Header"] = "header.html"
	//模版
	p.Layout = "main.html"
	p.TplName = "login.html"
}
 
其中 Main 方法,p.Layout = "main.html" 指定模版,p.TplName = "login.html" 指定模版中间的页面,p.LayoutSections["Header"] = "header.html" 指定页面固定的部分
在 main.go 中添加路由,修改 main.go 为下面代码
package main
import (
	"beego-demo/controller"
	"beego-demo/filter"
	"fmt"
	"github.com/beego/beego/v2/core/config"
	"github.com/beego/beego/v2/server/web"
)
func main() {
	//通过config获取自定义配置
	workername, _ := config.String("workername")
	fmt.Println(workername)
	//执行定时任务
	//go job.DemoTask()
	//注册自动路由
	//web.AutoPrefix("api", &controller.UserController{})
	web.CtrlGet("/name", (*controller.UserController).Name)
	web.CtrlGet("/get/:id", (*controller.UserController).GetUserById)
	web.CtrlGet("/get/:id/:num", (*controller.UserController).GetUserByIdAndNum)
	//返回页面
	web.CtrlGet("/page/index", (*controller.PageController).Index)
	web.CtrlGet("/page/f", (*controller.PageController).F)
	web.CtrlGet("/page/main", (*controller.PageController).Main)
	//注册函数式路由
	controller.RegisterFunctionalRoutes()
	//web命名空间
	controller.RegisterNamespaceRoutes()
	//过滤器
	filter.RegisterFilters()
	//开启 Admin 管理后台
	web.BConfig.Listen.EnableAdmin = true
	web.BConfig.Listen.AdminAddr = "localhost"
	web.BConfig.Listen.AdminPort = 8088
	//web.BConfig.WebConfig.ViewsPath = "pages"
	//查看已注册路由
	tree := web.PrintTree()
	methods := tree["Data"].(web.M)
	for k, v := range methods {
		fmt.Printf("%s => %v\n", k, v)
	}
	//自定义模板函数
	web.AddFuncMap("bookName", bookName)
	web.Run()
}
// 自定义模板函数添加书名号
func bookName(in string) (out string) {
	out = "《" + in + "》"
	return
}
 
运行效果,访问 http://localhost:9090/page/main

下一讲:《Beego 使用教程 6:Web 输入处理》
至此完



















