Beego
框架介绍
- 快速开发
- MVC架构
- 文档齐全,社区活跃
架构及原理
- cache
- 文件
- 内存
- memcache
- redis
- config
- ini
- json
- xml
- yaml
- context
- request
- response
- httplibs
- 支持
GET
POST
PUT
DELETE
HEAD
- 支持 https
- 支持超时设置
- 支持文件上传
- 支持
- logs
- 多种输出引擎
- 异步输出
- orm
- session
- toolbox
Beego项目运行基本流程
-
bee new:新建项目结构
- 使用bee创建名为elastic的项目
MacintoshdeMacBook-Pro-139:beego elasticnotes$ bee new elastic 2023/02/22 18:12:00.346 [D] init global config instance failed. If you do not use this, just ignore it. open conf/app.conf: no such file or directory 2023/02/22 18:12:00 INFO ▶ 0001 Generate new project support go modules. 2023/02/22 18:12:00 INFO ▶ 0002 Creating application... create /Users/elasticnotes/Desktop/beego/elastic/go.mod create /Users/elasticnotes/Desktop/beego/elastic/ create /Users/elasticnotes/Desktop/beego/elastic/conf/ create /Users/elasticnotes/Desktop/beego/elastic/controllers/ create /Users/elasticnotes/Desktop/beego/elastic/models/ create /Users/elasticnotes/Desktop/beego/elastic/routers/ create /Users/elasticnotes/Desktop/beego/elastic/tests/ create /Users/elasticnotes/Desktop/beego/elastic/static/ create /Users/elasticnotes/Desktop/beego/elastic/static/js/ create /Users/elasticnotes/Desktop/beego/elastic/static/css/ create /Users/elasticnotes/Desktop/beego/elastic/static/img/ create /Users/elasticnotes/Desktop/beego/elastic/views/ create /Users/elasticnotes/Desktop/beego/elastic/conf/app.conf create /Users/elasticnotes/Desktop/beego/elastic/controllers/default.go create /Users/elasticnotes/Desktop/beego/elastic/views/index.tpl create /Users/elasticnotes/Desktop/beego/elastic/routers/router.go create /Users/elasticnotes/Desktop/beego/elastic/tests/default_test.go create /Users/elasticnotes/Desktop/beego/elastic/main.go 2023/02/22 18:12:00 SUCCESS ▶ 0003 New application successfully created! MacintoshdeMacBook-Pro-139:beego elasticnotes$ ls
- 使用bee创建名为elastic的项目
-
bee run:自动编译部署
-
启动elastic项目
MacintoshdeMacBook-Pro-139:elastic elasticnotes$ bee run ______ | ___ \ | |_/ / ___ ___ | ___ \ / _ \ / _ \ | |_/ /| __/| __/ \____/ \___| \___| v2.0.4 2023/02/22 18:14:22 WARN ▶ 0001 Running application outside of GOPATH 2023/02/22 18:14:22 INFO ▶ 0002 Using 'elastic' as 'appname' 2023/02/22 18:14:22 INFO ▶ 0003 Initializing watcher... github.com/beego/beego/v2 google.golang.org/protobuf/internal/flags google.golang.org/protobuf/internal/set google.golang.org/protobuf/internal/fieldnum google.golang.org/protobuf/internal/genname golang.org/x/sys/internal/unsafeheader golang.org/x/mod/semver golang.org/x/xerrors/internal github.com/shiena/ansicolor github.com/beorn7/perks/quantile github.com/cespare/xxhash/v2 google.golang.org/protobuf/internal/pragma github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg golang.org/x/sys/unix github.com/pkg/errors github.com/mitchellh/mapstructure github.com/beego/beego/v2/core/utils github.com/beego/beego/v2/core/logs github.com/beego/beego/v2/core/admin github.com/beego/beego/v2/server/web/session gopkg.in/yaml.v2 github.com/beego/beego/v2/core/config github.com/beego/beego/v2/server/web/grace github.com/hashicorp/golang-lru google.golang.org/protobuf/internal/detrand google.golang.org/protobuf/internal/version google.golang.org/protobuf/internal/errors github.com/prometheus/common/model google.golang.org/protobuf/encoding/protowire github.com/prometheus/procfs/internal/fs google.golang.org/protobuf/reflect/protoreflect github.com/prometheus/procfs/internal/util github.com/prometheus/procfs google.golang.org/protobuf/reflect/protoregistry google.golang.org/protobuf/internal/strs google.golang.org/protobuf/internal/encoding/text google.golang.org/protobuf/internal/encoding/messageset google.golang.org/protobuf/internal/mapsort google.golang.org/protobuf/internal/fieldsort google.golang.org/protobuf/runtime/protoiface google.golang.org/protobuf/proto google.golang.org/protobuf/internal/descfmt google.golang.org/protobuf/internal/descopts google.golang.org/protobuf/internal/encoding/defval golang.org/x/crypto/acme google.golang.org/protobuf/encoding/prototext github.com/beego/beego/v2/server/web/context google.golang.org/protobuf/internal/filedesc golang.org/x/text/transform golang.org/x/text/unicode/bidi golang.org/x/text/unicode/norm github.com/beego/beego/v2/server/web/context/param golang.org/x/tools/go/internal/gcimporter golang.org/x/text/secure/bidirule golang.org/x/tools/internal/event/label golang.org/x/tools/internal/event/keys golang.org/x/tools/internal/event/core golang.org/x/tools/internal/event golang.org/x/tools/internal/gocommand golang.org/x/tools/go/internal/packagesdriver golang.org/x/tools/internal/packagesinternal golang.org/x/tools/internal/typesinternal google.golang.org/protobuf/internal/encoding/tag golang.org/x/xerrors google.golang.org/protobuf/internal/impl golang.org/x/net/idna golang.org/x/tools/go/gcexportdata golang.org/x/tools/go/packages golang.org/x/crypto/acme/autocert google.golang.org/protobuf/internal/filetype google.golang.org/protobuf/runtime/protoimpl google.golang.org/protobuf/types/known/timestamppb google.golang.org/protobuf/types/known/durationpb google.golang.org/protobuf/types/known/anypb github.com/golang/protobuf/proto github.com/golang/protobuf/ptypes/any github.com/golang/protobuf/ptypes/duration github.com/golang/protobuf/ptypes/timestamp github.com/prometheus/client_model/go github.com/matttproud/golang_protobuf_extensions/pbutil github.com/golang/protobuf/ptypes github.com/prometheus/client_golang/prometheus/internal github.com/prometheus/common/expfmt github.com/prometheus/client_golang/prometheus github.com/prometheus/client_golang/prometheus/promhttp github.com/beego/beego/v2/server/web elastic/controllers elastic/routers elastic 2023/02/22 18:14:47 SUCCESS ▶ 0004 Built Successfully! 2023/02/22 18:14:47 INFO ▶ 0005 Restarting 'elastic'... 2023/02/22 18:14:47 SUCCESS ▶ 0006 './elastic' is running... 2023/02/22 18:14:49.236 [I] [parser.go:413] generate router from comments 2023/02/22 18:14:49.237 [I] [server.go:241] http server Running on http://:8080 2023/02/22 18:15:06.706 [D] [router.go:955] | ::1| 200 | 17.756882ms| match| GET / r:/ 2023/02/22 18:15:06.778 [D] [router.go:955] | ::1| 200 | 22.617361ms| match| GET /static/js/reload.min.js
-
浏览器访问
localhost
展示如下图片
-
-
bee generate:自动生成代码
- 连接数据库,自动创建model
MacintoshdeMacBook-Pro-139:elastic elasticnotes$ bee generate scaffold user -fields="id:int64,name:string,gender:int,age:int" -driver=mysql -conn="elastic:@tcp IP /elastic" ______ | ___ \ | |_/ / ___ ___ | ___ \ / _ \ / _ \ | |_/ /| __/| __/ \____/ \___| \___| v2.0.4 2023/02/22 19:03:37 INFO ▶ 0001 Do you want to create a 'user' model? [Yes|No] yes 2023/02/22 19:03:46 INFO ▶ 0002 Using 'User' as model name 2023/02/22 19:03:46 INFO ▶ 0003 Using 'models' as package name create /Users/elasticnotes/Desktop/beego/elastic/models/user.go 2023/02/22 19:03:46 INFO ▶ 0004 Do you want to create a 'user' controller? [Yes|No] yes 2023/02/22 19:03:50 INFO ▶ 0005 Using 'User' as controller name 2023/02/22 19:03:50 INFO ▶ 0006 Using 'controllers' as package name 2023/02/22 19:03:50 INFO ▶ 0007 Using matching model 'User' create /Users/elasticnotes/Desktop/beego/elastic/controllers/user.go 2023/02/22 19:03:50 INFO ▶ 0008 Do you want to create views for this 'user' resource? [Yes|No] yes 2023/02/22 19:03:52 INFO ▶ 0009 Generating view... create /Users/elasticnotes/Desktop/beego/elastic/views/user/index.tpl create /Users/elasticnotes/Desktop/beego/elastic/views/user/show.tpl create /Users/elasticnotes/Desktop/beego/elastic/views/user/create.tpl create /Users/elasticnotes/Desktop/beego/elastic/views/user/edit.tpl 2023/02/22 19:03:52 INFO ▶ 0010 Do you want to create a 'user' migration and schema for this resource? [Yes|No] yes create /Users/elasticnotes/Desktop/beego/elastic/database/migrations/20230222_190353_user.go 2023/02/22 19:03:53 INFO ▶ 0011 Do you want to migrate the database? [Yes|No] yes
- 当前目录结构(高亮的为自动生成的)
-
自动生成的代码 !!! 自动生成的代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
package controllers import ( "elastic/models" "encoding/json" "errors" beego "github.com/beego/beego/v2/server/web" "strconv" "strings" ) // UserController operations for User type UserController struct { beego.Controller } // URLMapping ... func (c *UserController) URLMapping() { c.Mapping("Post", c.Post) c.Mapping("GetOne", c.GetOne) c.Mapping("GetAll", c.GetAll) c.Mapping("Put", c.Put) c.Mapping("Delete", c.Delete) } // Post ... // @Title Post // @Description create User // @Param body body models.User true "body for User content" // @Success 201 {int} models.User // @Failure 403 body is empty // @router / [post] func (c *UserController) Post() { var v models.User json.Unmarshal(c.Ctx.Input.RequestBody, &v) if _, err := models.AddUser(&v); err == nil { c.Ctx.Output.SetStatus(201) c.Data["json"] = v } else { c.Data["json"] = err.Error() } c.ServeJSON() } // GetOne ... // @Title Get One // @Description get User by id // @Param id path string true "The key for staticblock" // @Success 200 {object} models.User // @Failure 403 :id is empty // @router /:id [get] func (c *UserController) GetOne() { idStr := c.Ctx.Input.Param(":id") id, _ := strconv.ParseInt(idStr, 0, 64) v, err := models.GetUserById(id) if err != nil { c.Data["json"] = err.Error() } else { c.Data["json"] = v } c.ServeJSON() } // GetAll ... // @Title Get All // @Description get User // @Param query query string false "Filter. e.g. col1:v1,col2:v2 ..." // @Param fields query string false "Fields returned. e.g. col1,col2 ..." // @Param sortby query string false "Sorted-by fields. e.g. col1,col2 ..." // @Param order query string false "Order corresponding to each sortby field, if single value, apply to all sortby fields. e.g. desc,asc ..." // @Param limit query string false "Limit the size of result set. Must be an integer" // @Param offset query string false "Start position of result set. Must be an integer" // @Success 200 {object} models.User // @Failure 403 // @router / [get] func (c *UserController) GetAll() { var fields []string var sortby []string var order []string var query = make(map[string]string) var limit int64 = 10 var offset int64 // fields: col1,col2,entity.col3 if v := c.GetString("fields"); v != "" { fields = strings.Split(v, ",") } // limit: 10 (default is 10) if v, err := c.GetInt64("limit"); err == nil { limit = v } // offset: 0 (default is 0) if v, err := c.GetInt64("offset"); err == nil { offset = v } // sortby: col1,col2 if v := c.GetString("sortby"); v != "" { sortby = strings.Split(v, ",") } // order: desc,asc if v := c.GetString("order"); v != "" { order = strings.Split(v, ",") } // query: k:v,k:v if v := c.GetString("query"); v != "" { for _, cond := range strings.Split(v, ",") { kv := strings.SplitN(cond, ":", 2) if len(kv) != 2 { c.Data["json"] = errors.New("Error: invalid query key/value pair") c.ServeJSON() return } k, v := kv[0], kv[1] query[k] = v } } l, err := models.GetAllUser(query, fields, sortby, order, offset, limit) if err != nil { c.Data["json"] = err.Error() } else { c.Data["json"] = l } c.ServeJSON() } // Put ... // @Title Put // @Description update the User // @Param id path string true "The id you want to update" // @Param body body models.User true "body for User content" // @Success 200 {object} models.User // @Failure 403 :id is not int // @router /:id [put] func (c *UserController) Put() { idStr := c.Ctx.Input.Param(":id") id, _ := strconv.ParseInt(idStr, 0, 64) v := models.User{Id: id} json.Unmarshal(c.Ctx.Input.RequestBody, &v) if err := models.UpdateUserById(&v); err == nil { c.Data["json"] = "OK" } else { c.Data["json"] = err.Error() } c.ServeJSON() } // Delete ... // @Title Delete // @Description delete the User // @Param id path string true "The id you want to delete" // @Success 200 {string} delete success! // @Failure 403 id is empty // @router /:id [delete] func (c *UserController) Delete() { idStr := c.Ctx.Input.Param(":id") id, _ := strconv.ParseInt(idStr, 0, 64) if err := models.DeleteUser(id); err == nil { c.Data["json"] = "OK" } else { c.Data["json"] = err.Error() } c.ServeJSON() }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
package models import ( "errors" "fmt" "reflect" "strings" "github.com/beego/beego/v2/client/orm" ) type User struct { Id int64 Name string `orm:"size(128)"` Gender int Age int } func init() { orm.RegisterModel(new(User)) } // AddUser insert a new User into database and returns // last inserted Id on success. func AddUser(m *User) (id int64, err error) { o := orm.NewOrm() id, err = o.Insert(m) return } // GetUserById retrieves User by Id. Returns error if // Id doesn't exist func GetUserById(id int64) (v *User, err error) { o := orm.NewOrm() v = &User{Id: id} if err = o.QueryTable(new(User)).Filter("Id", id).RelatedSel().One(v); err == nil { return v, nil } return nil, err } // GetAllUser retrieves all User matches certain condition. Returns empty list if // no records exist func GetAllUser(query map[string]string, fields []string, sortby []string, order []string, offset int64, limit int64) (ml []interface{}, err error) { o := orm.NewOrm() qs := o.QueryTable(new(User)) // query k=v for k, v := range query { // rewrite dot-notation to Object__Attribute k = strings.Replace(k, ".", "__", -1) qs = qs.Filter(k, v) } // order by: var sortFields []string if len(sortby) != 0 { if len(sortby) == len(order) { // 1) for each sort field, there is an associated order for i, v := range sortby { orderby := "" if order[i] == "desc" { orderby = "-" + v } else if order[i] == "asc" { orderby = v } else { return nil, errors.New("Error: Invalid order. Must be either [asc|desc]") } sortFields = append(sortFields, orderby) } qs = qs.OrderBy(sortFields...) } else if len(sortby) != len(order) && len(order) == 1 { // 2) there is exactly one order, all the sorted fields will be sorted by this order for _, v := range sortby { orderby := "" if order[0] == "desc" { orderby = "-" + v } else if order[0] == "asc" { orderby = v } else { return nil, errors.New("Error: Invalid order. Must be either [asc|desc]") } sortFields = append(sortFields, orderby) } } else if len(sortby) != len(order) && len(order) != 1 { return nil, errors.New("Error: 'sortby', 'order' sizes mismatch or 'order' size is not 1") } } else { if len(order) != 0 { return nil, errors.New("Error: unused 'order' fields") } } var l []User qs = qs.OrderBy(sortFields...).RelatedSel() if _, err = qs.Limit(limit, offset).All(&l, fields...); err == nil { if len(fields) == 0 { for _, v := range l { ml = append(ml, v) } } else { // trim unused fields for _, v := range l { m := make(map[string]interface{}) val := reflect.ValueOf(v) for _, fname := range fields { m[fname] = val.FieldByName(fname).Interface() } ml = append(ml, m) } } return ml, nil } return nil, err } // UpdateUser updates User by Id and returns error if // the record to be updated doesn't exist func UpdateUserById(m *User) (err error) { o := orm.NewOrm() v := User{Id: m.Id} // ascertain id exists in the database if err = o.Read(&v); err == nil { var num int64 if num, err = o.Update(m); err == nil { fmt.Println("Number of records updated in database:", num) } } return } // DeleteUser deletes User by Id and returns error if // the record to be deleted doesn't exist func DeleteUser(id int64) (err error) { o := orm.NewOrm() v := User{Id: id} // ascertain id exists in the database if err = o.Read(&v); err == nil { var num int64 if num, err = o.Delete(&User{Id: id}); err == nil { fmt.Println("Number of records deleted in database:", num) } } return }
- 连接数据库,自动创建model