gograme学习

gograme学习gfgendao path app cconfig config yml gfic group 名 可见 sql 的上层文件夹名 tuser view menu 表名 modelFiletes go 输出文件名 更改安装的 swagger 版本

大家好,欢迎来到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

(0)
上一篇 2025-01-29 22:15
下一篇 2025-01-29 22:20

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信