Beego是一个Go开发的,开源的、高性能的web框架,常用于Web和Restfull API开发。
介绍
beego 是基于MVC的框架
什么是MVC
MVC基于分层原则实现:
- M(Model) 模型,DB
- V(View) 视图,Template
- C(Controller) 控制器,Controller
处理过程:
- Client发起请求: HTTP Protocol -> url/method/params
- Server: url -router-> handler -> params -> db -> template -> html
- 根据 URL 找到对应的 handler
- 处理/解析数据(如参数等)
- 调用数据库进行增、删、改、查
- 渲染页面
- 响应客户端
beego 使用
工具安装
go get -u github.com/beego/bee/v2
创建项目
bee new demo
目录结构
demo
├── 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
配置
启动时指定:
web.Run(":8888")
配置文件指定 conf/app.conf(ini格式)
:
HTTPPort=8888
HTTPAddr=127.0.0.1
# 注释
# 项目名 html 模板中获取方式 {{ config "String" "AppName" "Name" }}
AppName=<name>
# dev(自动加载页面模板) or prod(default,缓存页面模板到内存)
#RunMode=prod
# 从环境变量获取配置,若获取不到,采用默认模式
#RunMode=${BEEGO_RUNMODE}
# 指定默认值
RunMode=${BEEGO_RUNMODE||dev}
# 拷贝body数据
CopyRequestBody=true
# 文件上传的缓冲内存大小,默认 64M
Maxmemory=1*1024*1024
# 服务名称,Response Server header
ServerName=xianbin
# Web 配置,自动寻找 tpl 渲染文件
AutoRender=true
ViewsPath=views
StaticDir=static
# 指定不同环境的配置
[dev]
HTTPPort=8080
[prod]
HTTPPort=80
# 自定义配置
# 获取 db section, err := web.AppConfig.GetSection("db")
# web.AppConfig.Int("StaticDir")
# web.AppConfig.Int("db::MySQLPort")
# 默认值:web.AppConfig.DefaultInt("MySQLPort", 3306)
[db]
MySQLHost=127.0.0.1
MySQLPort=3306
- 配置拆分,创建
mysql.conf
,并在 app.conf
中添加 include mysql.conf
代码自动生成
bee help generate
USAGE
bee generate [command]
OPTIONS
-conn
Connection string used by the SQLDriver to connect to a database instance.
-ddl
Generate DDL Migration
-driver
Database SQLDriver. Either mysql, postgres or sqlite.
-fields
List of table Fields.
-level
Either 1, 2 or 3. i.e. 1=models; 2=models and controllers; 3=models, controllers and routers.
-tables
List of table names separated by a comma.
DESCRIPTION
▶ To scaffold out your entire application:
$ bee generate scaffold [scaffoldname] [-fields="title:string,body:text"] [-driver=mysql] [-conn="root:@tcp(127.0.0.1:3306)/test"]
▶ To generate a Model based on fields:
$ bee generate model [modelname] [-fields="name:type"]
▶ To generate a controller:
$ bee generate controller [controllerfile]
▶ To generate a CRUD view:
$ bee generate view [viewpath]
▶ To generate a migration file for making database schema updates:
$ bee generate migration [migrationfile] [-fields="name:type"]
▶ To generate swagger doc file:
$ bee generate docs
▶ To generate a test case:
$ bee generate test [routerfile]
▶ To generate appcode based on an existing database:
$ bee generate appcode [-tables=""] [-driver=mysql] [-conn="root:@tcp(127.0.0.1:3306)/test"] [-level=3]
代码生成示例
# User
$ bee generate scaffold user -fields="uuid:string,username:string,email:string,display_name:string,status:string,role:string,email_verified:bool,email_verified_at:string,phone:string,phone_verified:bool,phone_verified_at:string,age:int,avatar_url:string,gender:string,location:string,address:string,blog:string,bio:string,company:string,created_at:string,updated_at:string" -driver=sqlite
# Application
$ bee generate scaffold application -fields="uuid:string,owner:string,name:string,display_name:string,organization:string,logo_url:string,default_avatar_url:string,website_url:string,description:string,enable_password:bool,password_type:string,password_salt:string,enable_signup:bool,enable_signin:bool,client_id:string,client_secret:string,redirect_uris:string,created_at:string,updated_at:string" -driver=sqlite
# Organization
$ bee generate scaffold organization -fields="uuid:string,owner:string,name:string,display_name:string,site_url:string,default_avatar_url:string,created_at:string,updated_at:string" -driver=sqlite
# Provider
$ bee generate scaffold provider -fields="uuid:string,owner:string,name:string,display_name:string,application:string,type:string,client_id:string,client_secret:string,logo_url:string,description:string,redirect_uris:string,created_at:string,updated_at:string" -driver=sqlite
$ bee generate controller news
func init() {
beego.Include(&controllers.ApplicationController{}) // 注意此行必须加
beego.Include(&controllers.OrganizationController{})
beego.Include(&controllers.ProviderController{})
beego.Include(&controllers.UserController{})
}
路由
Beego 支持多种路由方式
简单路由示例
package main
import (
"fmt"
"github.com/beego/beego/v2/server/web"
"github.com/beego/beego/v2/server/web/context"
)
func main() {
// 静态路由
// 绑定函数,以 GET 方式请求 / 时,通过该匿名函数处理
web.Get("/", func(ctx *context.Context) {
// 用户数据获取
name := ctx.Input.Query("name")
ctx.Output.Context.WriteString(fmt.Sprint("get your name is ", name))
})
// Post 请求
web.Post("/", func(ctx *context.Context) {
name := ctx.Input.Query("name")
ctx.Output.Context.WriteString(fmt.Sprint("post your name is ", name))
})
// 任意请求,相同方式时,是否生效与代码的顺序有关
web.Any("/any/", func(ctx *context.Context) {
ctx.Output.Context.WriteString(fmt.Sprintf("you actions is %s", ctx.Request.Method))
})
// 正则路由,URL中定义正则字符串匹配,示例匹配 /number/ 格式路由,并放入 :id 参数中
//web.Get("/:id(^\\d+$)/", func(ctx *context.Context) {
// ? 表示没有 id 也匹配
web.Get("/?:id(^\\d+$)/", func(ctx *context.Context) {
// 用户数据获取
//id := ctx.Input.Query(":id")
id := ctx.Input.Param(":id")
ctx.Output.Context.WriteString(fmt.Sprint("number url id is ", id))
})
// 不区分类型
web.Get("/any/:any/", func(ctx *context.Context) {
// 用户数据获取
any := ctx.Input.Query(":any")
ctx.Output.Context.WriteString(fmt.Sprint("any url id is ", any))
})
// 类型获取 /file/abc /file/a/b/c
web.Get("/file/*", func(ctx *context.Context) {
// 通过 splat 获取没有名字的参数
splat := ctx.Input.Param(":splat")
ctx.Output.Context.WriteString(fmt.Sprintf("file %s", splat))
})
// /ext/a.txt
web.Get("/ext/*.*", func(ctx *context.Context) {
path := ctx.Input.Param(":path") // a
ext := ctx.Input.Param(":ext") // txt
ctx.Output.Context.WriteString(fmt.Sprintf("file path %s, ext %s", path, ext))
})
web.Run()
}
控制器
控制器路由示例
package main
import (
"fmt"
"github.com/beego/beego/v2/server/web"
)
// 定义 Controller
type CityController struct {
web.Controller
}
// Restfull API
func (c *CityController) Get() {
c.Ctx.WriteString(`{"data": 123}`)
}
func (c *CityController) Create() {
c.Ctx.WriteString(c.Ctx.Request.Method)
}
func (c *CityController) Put() {
}
func (c *CityController) Delete() {
}
type RegexpController struct {
web.Controller
}
func (c *RegexpController) Get() {
c.Ctx.WriteString(c.Ctx.Input.Param(":id"))
}
type AutoController struct {
web.Controller
}
func (c *AutoController) Test() {
c.Ctx.WriteString(fmt.Sprintf("%s method: %s", "test", c.Ctx.Request.Method))
}
func main() {
// url 和控制器绑定,默认匹配Get/Post/Put等方法
//web.Router("/city/", &CityController{})
// 自定义路由和函数Map
web.Router("/city/", &CityController{}, "GET:Get;post:Create")
// 正则路由
web.Router("/regexp/?:id/", &RegexpController{})
// 自动路由,自动将路由绑定到 "/auto/",/auto/test 自动将所有请求类型绑定到 Test 方法上
web.AutoRouter(&AutoController{})
web.Run()
}
控制器内置方法
package main
import (
"github.com/beego/beego/v2/core/logs"
"github.com/beego/beego/v2/server/web"
"github.com/beego/beego/v2/server/web/context"
)
type CityController struct {
web.Controller
}
func (c *CityController) Init(ctx *context.Context, controllerName, actionName string, app interface{}) {
c.Controller.Init(ctx, controllerName, actionName, app)
logs.Info("run Init func, controllerName: %s, actionName: %s", controllerName, actionName)
}
func (c *CityController) Prepare() {
logs.Info("run Prepare func")
}
func (c *CityController) Get() {
logs.Info("Get method")
c.Ctx.WriteString(c.Ctx.Request.Method)
}
func (c *CityController) Render() error {
logs.Info("run Render func")
return c.Controller.Render()
}
func (c *CityController) Finish() {
logs.Info("run Finish func")
}
func main() {
web.Router("/city/", &CityController{})
web.Run()
}
日志:
run Init func, controllerName: CityController, actionName: GET
run Prepare func
Get method
run Finish func
说明:
Prepare()
函数可以做认证拦截和信息注入
Render()
函数只有配置 c.TplName
时才执行
Render()
函数也可以执行其他批量的动作,如 c.ServeJSON()
过滤器
https://beego.vip/docs/mvc/controller/filter.md
请求数据
url 和 body 数据
package main
import (
"encoding/json"
"fmt"
"strconv"
"github.com/beego/beego/v2/core/logs"
"github.com/beego/beego/v2/server/web"
)
// 定义 Controller
type CityController struct {
web.Controller
}
type CityForm struct {
X int `form:"x"`
Y int // URL 必须是大写的 Y 才能匹配到
}
// Get 获取URL参数和Form(application/x-www-form-urlencoded)中数据示例
func (c *CityController) Get() {
// http://127.0.0.1:8080/city/?x=1&y=2
// 方法一
c.Ctx.WriteString(c.Ctx.Input.Query("x"))
c.Ctx.WriteString(c.Ctx.Input.Query("y"))
c.Ctx.WriteString("\n")
// 方法二
var x string
c.Ctx.Input.Bind(&x, "x")
c.Ctx.WriteString(x)
c.Ctx.WriteString("\n")
// 方式三
c.Ctx.WriteString(c.GetString("x"))
xi, _ := c.GetInt("x")
c.Ctx.WriteString(strconv.Itoa(xi))
c.Ctx.WriteString("\n")
// 方式四
c.Ctx.Request.ParseForm()
c.Ctx.WriteString(c.Ctx.Request.Form.Encode())
c.Ctx.WriteString("\n")
// 方式五
var form CityForm
c.ParseForm(&form)
c.Ctx.WriteString(fmt.Sprintf("%#v", form))
c.Ctx.WriteString("\n")
// 获取 url router 参数
c.Ctx.WriteString(fmt.Sprintf("%#v", c.Ctx.Input.Params()))
c.Ctx.WriteString(c.Ctx.Input.Param("x"))
c.Ctx.WriteString(c.Ctx.Input.Param("y"))
c.Ctx.WriteString("\n")
}
// Post request body 参数获取示例
func (c *CityController) Post() {
// 获取 form 数据
//c.Ctx.Request.ParseForm()
c.Ctx.WriteString(c.Ctx.Request.Method)
c.Ctx.WriteString(c.Ctx.Request.Form.Encode())
c.Ctx.WriteString("\n")
// 方式二:仅获取 Post Form 数据
c.Ctx.WriteString(c.Ctx.Request.PostForm.Encode())
c.Ctx.WriteString("\n")
//方式三,使用较多
c.Ctx.WriteString(c.GetString("name"))
c.Ctx.WriteString("\n")
// 方式四,使用较多
var form CityForm
c.ParseForm(&form)
c.Ctx.WriteString(fmt.Sprintf("%#v", form))
c.Ctx.WriteString("\n")
}
type FileController struct {
web.Controller
}
// Post 处理 form-data 文件上传
func (c *FileController) Post() {
// 方式一
//c.Ctx.Request.FormFile("abc")
files := c.Ctx.Request.MultipartForm.File
logs.Info("%#v", files)
// 方式二
//file := c.GetFile("abc")
//defer file.Close()
// 方式三
c.SaveToFile("abc", "abc.json")
//c.SaveToFileWithBuffer(fromFile string, toFile string, buf []byte) error {
c.Ctx.WriteString(fmt.Sprintf("%#v", files))
}
type JsonController struct {
web.Controller
}
// Post 处理 application/json 文件上传
func (c *JsonController) Post() {
c.Ctx.Input.CopyBody(1 * 1024 * 1024) // 1Mb,必须加该行,或app.conf中配置,否则拿不到数据
m := make(map[string]interface{})
err := json.Unmarshal(c.Ctx.Input.RequestBody, &m)
if err != nil {
c.Ctx.WriteString(err.Error())
} else {
c.Ctx.WriteString(fmt.Sprintf("%#v\n", m))
}
}
func main() {
web.Router("/city/", &CityController{})
web.Router("/file/", &FileController{})
web.Router("/json/", &JsonController{})
web.Run()
}
package main
import (
"github.com/beego/beego/v2/core/logs"
"github.com/beego/beego/v2/server/web"
)
type HeaderController struct {
web.Controller
}
func (c *HeaderController) Get() {
// 获取 header
logs.Info("c.Ctx.Request.Header", c.Ctx.Request.Header)
logs.Info("c.Ctx.Input.Header", c.Ctx.Input.Header("Path"))
// 设置 header
c.Ctx.ResponseWriter.Header().Add("h1", "v1")
c.Ctx.Output.Header("h2", "v2")
c.Ctx.WriteString("ok")
}
func main() {
web.Router("/header/", &HeaderController{})
web.Run()
}
Cookie 数据
读取和设置 Cookie 数据示例
package main
import (
"net/http"
"github.com/beego/beego/v2/core/logs"
"github.com/beego/beego/v2/server/web"
)
// 定义 Controller
type CookieController struct {
web.Controller
}
// Get curl -H "Cookie:name=value; name2=value2; name3=value3"
func (c *CookieController) Get() {
// 获取 cookies
// 方法一
//c.Ctx.Request.Cookie(name)
for _, cookie := range c.Ctx.Request.Cookies() {
logs.Info("cookie: %s", cookie)
}
// 方法二
c.Ctx.WriteString(c.Ctx.Input.Cookie("name"))
c.Ctx.WriteString("\n")
// 方式三
c.Ctx.WriteString(c.Ctx.GetCookie("name"))
cookie := http.Cookie{
Name: "namebeego1",
Value: "value1",
}
http.SetCookie(c.Ctx.ResponseWriter, &cookie)
c.Ctx.SetCookie("namebeego2", "valuebeego") // Get 方法没有生效?
c.Ctx.WriteString("")
}
func (c *CookieController) Post() {
// 设置 cookie
// 方式一:
cookie := http.Cookie{
Name: "namebeego1",
Value: "v1",
}
http.SetCookie(c.Ctx.ResponseWriter, &cookie)
c.Ctx.SetCookie("namebeego2", "v2")
// SecureCookie 加密 cookie
//c.SetSecureCookie()
secret := "abcd"
v3, result := c.GetSecureCookie(secret, "namebeego3")
logs.Info("sc", v3, result)
c.Ctx.SetSecureCookie(secret, "namebeego3", "v3")
c.Ctx.WriteString("")
}
func main() {
web.Router("/cookie/", &CookieController{})
web.Run()
}
响应数据
模板
模板的基本使用
# 根据 Controller 查找 url
<form action="{{ urlfor `AuthController.Login` }}">
...
</form>
# form 定义
$ cat forms/auth.go
package auth
type LoginForm struct {
Name string `form:"name"`
Password string `form:"password"`
}
# 解析 form
c.ParseForm(&authForm)
# 数据库定义,ID 一般全大写
# 数据库初始化
$ cat models/db.go
package models
import (
"database/sql"
)
var db *sql.DB
func init() {
dns := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&local=PRC&parseTime=true",
"user", "password", "host", "port", "db")
db, err = sql.Open("mysql", dns)
if err != nil {
log.Fatal(err)
}
if err != db.Ping(); err != nil {
log.Fatal(err)
}
}
$ cat modules/user.go
package models
type User struct {
Name string
Password string
CreateAd *time.Time // 时间一般使用指针
}
func GetUserByName(name string) *User {
}
$ cat utils/sql.go
package utils
import (
"fmt"
"strings"
)
func Like(q string) string {
q = strings.TrimSpace(q)
if q == "" {
return q
}
// select ... where name like ? ESCAPE '/'
strings.Replace(q, "/", "//", -1)
strings.Replace(q, "%", "/%", -1)
strings.Replace(q, "_", "/_", -1)
return fmt.Sprintf("%%%s%%", q)
}
$ cat views/home.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>home</title>
</head>
<body>
Name:
{{ .Name }}<br><br>
判断:<br>
{{ if eq .show true }}
show<br>
{{ else }}
not show
{{ end }}
<br>
遍历切片:
{{ range .city }}
{{ . }}<br>
{{ end }}
<br>
{{ range $index, $c := .city }}
{{ $index }}-{{ $c }}<br>
{{ end }}
<br>
遍历map:<br>
{{ range .region }}
{{ . }}<br>
{{ end }}
<br>
{{ range $key, $value := .region }}
{{ $key}} : {{ $value }}<br>
{{ end }}
<br>
自定义函数:{{ lower .UpperInfo }} - {{ .UpperInfo | lower }}<br>
<br>
模板定义:实现代码的复用<br>
{{ define "toLower" }}
{{ . }} : {{ . | lower }}
{{ end }}
{{ template "toLower" .UpperInfo }}
{{ template "toLower" .UpperInfo }}
{{ template "toLower" .UpperInfo }}
{{ template "toLower" .UpperInfo }}
<br><br>
{{ template "tpla.html" .UpperInfo }} {{ template "tpla.html" .UpperInfo }} <br>
</body>
</html>
$ cat views/tpla.html
{{ . | lower }}%
package main
import (
"strings"
"github.com/beego/beego/v2/server/web"
)
type HomeController struct {
web.Controller
}
func (c *HomeController) Get() {
// 后缀只支持 *.html/*.tpl
// 需要放到 path:views/
// 默认加载控制器名称/action名.tpl模板文件
// 传数据
c.Data["Name"] = "xianbin"
c.Data["show"] = true
c.Data["city"] = []string{"shanghai", "shangqiu", "zhengzhou"}
c.Data["region"] = map[string]string{"shanghai": "021", "shangqiu": "0370"}
c.Data["UpperInfo"] = "XIEXIANBIN"
// 指定模板
c.TplName = "home.html"
}
func main() {
// 自定义函数
web.AddFuncMap("lower", func(str string) string {
return strings.ToLower(str)
})
web.Router("/home/", &HomeController{})
web.Run()
}
json/xml/yaml等格式
包括raw/json/xml/yaml等
package main
import (
"encoding/xml"
"github.com/beego/beego/v2/server/web"
)
// 定义 Controller
type RespController struct {
web.Controller
}
func (c *RespController) Get() {
c.Ctx.WriteString("c.Ctx.WriteString")
c.Ctx.WriteString("\n")
c.Ctx.Output.Body([]byte("c.Ctx.Output.Body"))
c.Ctx.WriteString("\n")
// 返回 json 数据
// 方式一
m := map[string]interface{}{"a": 1, "b": 2}
c.Ctx.Output.JSON(m, true, true)
c.Ctx.WriteString("\n")
// 方式二
c.Data["json"] = m
c.ServeJSON()
// 返回 yaml 数据
c.Ctx.Output.YAML(m)
c.Data["yaml"] = m
c.ServeYAML()
// 返回 xml 数据
//x := struct {
// XMLName xml.Name
// Name string `xml:"name"`
// Age int `xml:"age"`
//}{XMLName: xml.Name{Space: "xiexianbin.cn", Local: "root"}, Name: "xianbin", Age: 18}
x := struct {
XMLName xml.Name `xml:"root"`
Name string `xml:"name"`
Age int `xml:"age"`
}{Name: "xianbin", Age: 18}
c.Ctx.Output.XML(x, true)
c.Data["xml"] = x
c.ServeXML()
// 返回 html 模板
//c.TplName = "xxx.html" // 在 views 目录下
// 重定向
//c.Redirect("https://www.xiexianbin.cn", 302)
// 停止执行
//c.StopRun()
// 抛出错误
//c.Abort("404")
}
func (c *RespController) Post() {
c.Ctx.WriteString("")
}
func main() {
web.Router("/response/", &RespController{})
web.Run()
}
Session
参考:
Session 的存储介质:
- 内存,重启消失
- 文件,单机部署使用
- 数据库,如redis、memcache
配置信息
Session 在 beego 的配置文件中指定
# 是否开启
SessionOn=[truefalse]
# 存储位置
SessionProvider=[memory|file|mysql|redis]
# 存储的地址
SessionProviderConfig=[file文件路径|mysql datasourcename|redis host:port password]
# cookie 中 sessionid 的名字,用来屏蔽服务器信息
SessionName=sid
# 生命周期
SessionGCMaxLifetime = 3600s
Session 的操作
- 存储
func (c *Controller) SetSession(name interface{}, value interface{}) error {}
- key/value 可以是任意类型
- 持久化编码方式 gob
- 获取
func (c *Controller) GetSession(name interface{}) interface{} {}
- 销毁
func (c *Controller) DelSession(name interface{}) error {}
- c.DestorySession()
package main
import (
"github.com/beego/beego/v2/core/logs"
"github.com/beego/beego/v2/server/web"
)
type CityController struct {
web.Controller
}
func (c *CityController) Get() {
city := c.GetSession("city")
if city == nil {
logs.Info("get session city is nil")
//c.Redirect("login", 302)
err := c.SetSession("city", "shanghai")
if err != nil {
logs.Error(err)
}
} else {
logs.Info("get session city is", city)
}
// 销毁session
//c.DelSession(name)
//c.DestroySession()
c.Ctx.WriteString(`{"data": 123}`)
}
func main() {
web.BConfig.RunMode = "dev"
web.BConfig.WebConfig.Session.SessionOn = true
web.BConfig.WebConfig.Session.SessionName = "sid"
web.BConfig.WebConfig.Session.SessionProvider = "file"
web.BConfig.WebConfig.Session.SessionProviderConfig = "./session"
web.Router("/city/", &CityController{})
web.Run()
}
Session 拦截一般使用 filter 过滤
认证拦截
用户认证拦截可以放置的位置:
controller.Prepare()
,可以使用 c.StopRun() 终止继续执行,缺点:所有的控制器均需写重复的代码
- 定义一个认证controller,在
Prepare()
中实现权限认证,如通过 c.GetControllerAndAction()
和用户的菜单权限对比等
- xxxController
- AuthorizationController | UnAuthController like LoginController
- BaseController
- web.Controller
type AuthorizationController struct {
web.Controller
SigInUser *models.User
}
type (c *AuthorizationController) Prepare() {
// auth: 通过从Session中获取登录信息
// 1. nil,跳转登录
// 2. 获取成功时,将User信息添加到 c.Data["user"] 中,断言获取值信息
// id := sessionValue.(string)
// c.SigInUser = user
// 针对该controller关闭xsrf认证
// c.EnableXSRF = false
}
Flash
使用 cookie 存储消息,并可以在页面获取对应的值后删除
使用场景:
- 使用后端页面模板
- 从当前Controller跳转到另一个URL
f := web.NewFlash
f.Set("key1", "val1)
f.Store(&c.Controller)
// 另一个Controller获取
f:= web.ReadFromRequest(&c.Controller)
f.Data["key1]
// 页面获取
{{ .flash.key1 }}
CSRF
CSRF 跨站请求伪造,是常见的攻击手段。配置 conf/app.conf
EnableXSRF=true
XSRFKey=abcd..
XSRFExpire=3600
使用:
c.Data["xsrf_token"] = c.XSRFtoken()
<input type="hidden" name="_xfst" value="{{ .xsrf_token }}" />
Layout
$ cat layout.html
<html>
.LayoutContent
...
.scriptStyle
$ cat base/controllers/layout.go
func (c *LayoutController) Prepare() {
c.Controller.Prepare()
c.Layout = "layouts/layout.html"
c.Data["title"] = web.AppConf...
c.LayoutSections=make(map[string]string)
c.LayoutSection["scriptStyle"] = "...html"
c.LayoutSection["css"] = "...css"
}
Cache 缓存
package main
import (
"encoding/gob"
"os"
"time"
"github.com/beego/beego/v2/client/cache"
"github.com/beego/beego/v2/core/logs"
)
type City struct {
Name string
}
func main() {
//cache, _ := cache.NewCache("memory", `{"interval": 60}`)
cache, err := cache.NewCache("file", `{"CachePath": "cache", "FileSuffix": ".cache", "EmbedExpiry": "60", "DirectoryLevel": "5"}`)
if err != nil {
logs.Error(err)
os.Exit(-1)
}
logs.Info(cache.Get(nil, "name"))
timeout := 5 * time.Second
cache.Put(nil, "name", "xianbin", timeout)
logs.Info(cache.Get(nil, "name"))
time.Sleep(6 * time.Second)
logs.Info(cache.Get(nil, "name"))
cache.Delete(nil, "name")
logs.Info(cache.IsExist(nil, "name"))
gob.Register(new(City))
c := &City{
Name: "shanghai",
}
cache.Put(nil, "city", c, 5*time.Second)
logs.Info(cache.Get(nil, "city"))
}
Filter
部署
使用linux service打包部署
https
EnableHTTP=true
EnableHTTPs=true
HTTPSCertFile=
HTTPSKeyFile=
项目架构
- controller
- services Server
type userService struct{}
func (s *userService) GetByPk (){
}
var UserService = new(userService)
FaQ
beego2.0打包文件执行错误:
$ ./main
panic: err: go command required, not found: exec: "go": executable file not found in $PATH: stderr:
goroutine 1 [running]:
github.com/beego/beego/v2/server/web.initBeforeHTTPRun.func1()
/go/pkg/mod/github.com/beego/beego/v2@v2.0.1/server/web/beego.go:83 +0x225
sync.(*Once).Do(0x16ef2e0, 0xdcc288)
/usr/local/go/src/sync/once.go:44 +0xb3
github.com/beego/beego/v2/server/web.initBeforeHTTPRun()
/go/pkg/mod/github.com/beego/beego/v2@v2.0.1/server/web/beego.go:69 +0x39
github.com/beego/beego/v2/server/web.(*HttpServer).Run(0xc000185a40, 0x0, 0x0, 0x0, 0x0, 0x0)
/go/pkg/mod/github.com/beego/beego/v2@v2.0.1/server/web/server.go:85 +0x34
github.com/beego/beego/v2/server/web.Run(0x0, 0x0, 0x0)
/go/pkg/mod/github.com/beego/beego/v2@v2.0.1/server/web/beego.go:57 +0x62
main.main()
/tmp/code/main.go:21 +0x32
- 解决方式,将
app.conf
中设置为生产环境:
runmode = prod