大家好,欢迎来到IT知识分享网。
文章目录
框架设计
结构化输入输出
输出输出用结构体来定义结构,避免在方法中硬编码,并且方便生成接口文档
数据模型
包括MySQL、Redis、MongoDB、Kafka在内的持久化数据库的数据结构,是框架自动生成的,在/app/dao/internal/model/entity目录下
隐式初始化与显式初始化
main.go里import的包里自带的init方法是隐式初始化,goframe框架的很多模块使用隐式初始化;boot/boot.go里调用的方法是显式初始化吗,一般是与业务相关的用显式初始化
context
在一次请求中,协程共享的变量,类似于java的threadlocal
Quickstart
安装swagger / 更新swagger文档
gf swagger --pack
更改安装的swagger版本
go get -u github.com/swaggo/swag/cmd/swag@v1.8.6
(通过go.mod来执行的)
go get xxx.cn/gaea-server/x/core@master
来拉取分支
也可以来更新goframe版本
go get -u github.com/gogf/gf/v2
删除安装模块的缓存:
go clean --modcache
日志管理
没啥要看的
错误处理
没有用gerror,还是原生的error处理
数据校验
类似Laravel里面的validator : p - params , v - valid
,项目里没有自定义错误
缓存管理
fileDb.GetCache().SetAdapter(redis.NewRedis(redis2.DefaultClient()))
数据库ORM
能够自动生成DAO代码
gf gen dao -path ./app/ -c config/config.yml -g fic(group名,可见.sql的上层文件夹名) -t user_view_menu(表名) -modelFile test.go(输出文件名)
yaml配置文件里,放了两个数据库分组的配置信息,由于没有配置主从,所有读写都是在master节点上执行
orm 时间相关方法
.WhereLT(dao.EntExportQueue.Columns.CreatedAt, time.Now().UTC().Add(-7*24*time.Hour))
可是查出7天前数据
数据库升级脚本
存储过程示例
-- 创建删除索引的存储过程 DROP PROCEDURE IF EXISTS del_index; CREATE PROCEDURE del_index(IN target_table_name VARCHAR(100),IN target_index_name VARCHAR(100)) BEGIN IF EXISTS (SELECT * FROM information_schema.statistics WHERE table_schema = DATABASE() AND table_name = target_table_name AND index_name = target_index_name) THEN set @statement =( select concat ('alter table ',target_table_name, ' drop key ',target_index_name )); PREPARE STMT FROM @statement; EXECUTE STMT; END IF; END; call del_index('tag','name'); call del_index('tag','idx_name_ttype');
存储过程参考 https://blog.csdn.net/scdncby/article/details/
-- t 表名;i 索引名称;v 创建索引执行的sql ddl语句 -- 创建删除索引的存储过程 DROP PROCEDURE IF EXISTS del_index; DELIMITER $ CREATE PROCEDURE del_index(IN t VARCHAR(100),IN i VARCHAR(100),IN v VARCHAR(255)) BEGIN DECLARE target_database VARCHAR(100); DECLARE target_table_name VARCHAR(100); DECLARE target_column_name VARCHAR(100); DECLARE target_index_name VARCHAR(100); set target_table_name = t; set target_index_name = i; SELECT DATABASE() INTO target_database; IF EXISTS (SELECT * FROM information_schema.statistics WHERE table_schema = target_database AND table_name = target_table_name AND index_name = target_index_name) THEN set @statement = v; PREPARE STMT FROM @statement; EXECUTE STMT; END IF; END; $ DELIMITER ; call del_index('tag','name',"alter table tag drop key name"); call del_index('tag','name',"alter table tag drop key idx_name_ttype");
实用sql
# 查询表索引 SELECT * FROM information_schema.statistics WHERE table_schema = DATABASE() AND table_name = 'tag'; # 查数据库mode select @@session.sql_mode;
默认值
OmitEmptyData()让框架忽略零值
0, nil, false, "", len(slice/map/chan) == 0
,插入数据库默认值
所以禁止在数据库里填默认值为非0的,以防想写入0却被orm忽略插入数据库默认值;在数据库里默认为0,业务逻辑里写非0的默认值,在数据库里没有该条数据的时候直接返回默认值。
模型创建
Model方法用于创建基于数据表的Model对象
g.DB().Model("user") // g代表一个DAO对象
由于链式操作的每一个方法会对Model属性进行修改,造成Model对象不能重复使用
user := g.Model("user") user.Where("status", g.Slice{
1,2,3}) if vip {
// 查询条件自动叠加,修改当前模型对象 user.Where("money>=?", ) } else {
// 查询条件自动叠加,修改当前模型对象 user.Where("money<?", ) } // vip: SELECT * FROM user WHERE status IN(1,2,3) AND money >= // !vip: SELECT * FROM user WHERE status IN(1,2,3) AND money < r, err := user.All() // vip: SELECT COUNT(1) FROM user WHERE status IN(1,2,3) AND money >= // !vip: SELECT COUNT(1) FROM user WHERE status IN(1,2,3) AND money < n, err := user.Count()
所以通过Safe方法对每一个链式操作都返回一个新的Model操作,该Model对象可以重复使用。(项目中就用的这种方式)
// 定义一个用户模型单例 user := g.Model("user").Safe() m := user.Where("status", g.Slice{
1,2,3}) if vip {
// 查询条件通过赋值叠加 m = m.And("money>=?", ) } else {
// 查询条件通过赋值叠加 m = m.And("money<?", ) } // vip: SELECT * FROM user WHERE status IN(1,2,3) AND money >= // !vip: SELECT * FROM user WHERE status IN(1,2,3) AND money < r, err := m.All() // vip: SELECT COUNT(1) FROM user WHERE status IN(1,2,3) AND money >= // !vip: SELECT COUNT(1) FROM user WHERE status IN(1,2,3) AND money < n, err := m.Count()
事务处理
用闭包方式来使用事务
func (db DB) Transaction(ctx context.Context, f func(ctx context.Context, tx *TX) error) (err error)
func (dao *UserViewMenuDao) Transaction(ctx context.Context, f func(ctx context.Context, tx *gdb.TX) error) (err error) {
return dao.Ctx(ctx).Transaction(ctx, f)
}
是一种事务使用方式吗??(没看到哪个方法使用到了),反正只在web项目中看到只有2个方法显示用到了事务.Transaction
嵌套事务????
微服务
每个功能抽成服务,服务间通过rpc来访问
rpc示例:
服务端,注册服务
package main import ( "fmt" "log" "net" "net/rpc" "net/rpc/jsonrpc" ) type Params struct {
Width, Height int } type Rect struct {
} func (r *Rect) Area(p Params, ret *int) error {
*ret = p.Width * p.Height return nil } func (r *Rect) Perimeter(p Params, ret *int) error {
*ret = (p.Height + p.Width) * 2 return nil } func main() {
rpc.Register(new(Rect)) lis, err := net.Listen("tcp", ":8080") if err != nil {
log.Panicln(err) } for {
conn, err := lis.Accept() if err != nil {
continue } go func(conn net.Conn) {
fmt.Println("new client") jsonrpc.ServeConn(conn) }(conn) } }
客户端,调用服务
package main import ( "fmt" "log" "net/rpc/jsonrpc" ) type Params struct {
Width, Height int } func main() {
conn, err := jsonrpc.Dial("tcp", ":8080") if err != nil {
log.Panicln(err) } ret := 0 err2 := conn.Call("Rect.Area", Params{
50, 100}, &ret) if err2 != nil {
log.Panicln(err2) } fmt.Println("面积:", ret) err3 := conn.Call("Rect.Perimeter", Params{
50, 100}, &ret) if err3 != nil {
log.Panicln(err3) } fmt.Println("周长:", ret) }
其他常识
go mod tidy后go.mod还是标红,用go clean –modcache解决;
go.mod不标红,但是代码中有标红,清ide缓存
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/157502.html