GoFrame代码优化gconv类型转换避免重复定义map

目录
  • 前言
  • 核心重点
  • 优化前
  • 优化后:
    • 可以这么写的原因
  • 进一步优化 批量写入
    • 更优雅的写法如下
  • 总结

前言

最近一直在研究 GoFrame 框架,经过一段时间的使用、总结、思考,发现确实不失为一款非常值得使用的企业级开发框架。

在我初识GoFrame教程后,曾整理过一篇文章: 非常适合PHP同学学习的GO框架:GoFrame,有兴趣的同学可以阅读一下。

今天重点讲一下我使用GoFrame的代码优化之旅。

核心重点

GoFrame几乎封装了所有能封装的东西,而我们需要做的就是在框架的基础上约定好自己项目的开发规范。

一定要遵守统一的规范!

一定要遵守统一的规范!

一定要遵守统一的规范!

类型转换GoFrame框架提供了非常强大易用的类型转换包gconv,可以实现将常用数据类型转换为指定的数据类型,对常用基本数据类型之间的无缝转换,同时也支持任意类型到struct对象的转换。由于gconv模块内部大量优先使用了断言而非反射,因此执行的效率非常高。

数据库ORM:通过Scan方法自动识别Map/Struct接收查询结果,自动化查询结果初始化、结构体类型转换; 完美支持GoFrame框架层面的DAO设计,全自动化Model/DAO代码生成,极大提高开发效率。

以上两个部分是重中之重,建议大家好好研究。

类型转换 和 数据库ORM 也是我下面优化代码的重要参考。

优化前

//获取商品类目接口
func (s *goMeGoodsService) GetCategory(pid ...interface{}) {
	ctx := context.Background()
	res, err := gome.Category.Get(ctx, pid)
	if err != nil {
		checkErr(err, "GetCategory AddCategory")
	}
	data := res.Data
	for _, v := range data {
		if v.Code != "" && v.Name != "" {
			_, err = s.AddCategory(v.Level, v.Code, v.Name, v.ParentCode)
			checkErr(err, "GetCategory AddCategory")
		}
	}
}
//添加分类
func (s *goMeGoodsService) AddCategory(level int, code, name, parent_code string) (id int64, err error) {
	categoryMapping := map[string]interface{}{
		"level":       level,
		"code":        code,
		"name":        name,
		"parent_code": parent_code,
	}
	sqlRes, err := dao.GomeCategory.Data(categoryMapping).Insert()
	if err != nil {
		return
	}
	id, err = sqlRes.RowsAffected()
	if err != nil {
		return
	}
	return
}

这种重复定义让我很难受:

categoryMapping := map[string]interface{}{
		"level":       level,
		"code":        code,
		"name":        name,
		"parent_code": parent_code,
	}

优化后:

去掉定义map:

//获取商品类目接口
func (s *goMeGoodsService) GetCategory(pid ...interface{}) {
	ctx := context.Background()
	res, err := gome.Category.Get(ctx, pid)
	if err != nil {
		checkErr(err, "GetCategory AddCategory")
	}
        //循环单条插入
        for _, v := range res.Data {
         _, err := dao.GomeCategory.Data(v).Insert()
         if err != nil {
            checkErrGome(err, "db添加分类失败")
         }
        }
}

可以这么写的原因

func (categoryGome) Get(ctx context.Context, pid ...interface{}) (res *CategoryRes, err error) {
	method := "alemein.basic.get.category"
	req := g.Map{}
	if len(pid) > 0 {
		req["parentCode"] = pid[0]
	}
	result, err := server.requestApi(ctx, method, req)
	if err != nil {
		return
	}
	_ = gjson.New(result).Scan(&res)
	return
}

gome.Category.Get(ctx, pid) 返回的是 CategoryRes结构体:

type CategoryRes struct {
	*CommonRes
	Data []struct {
		Code       string `json:"code"`
		Level      int    `json:"level"`
		ParentCode string `json:"parentCode"`
		Name       string `json:"name"`
	} `json:"data"`
}

进一步优化 批量写入

CategoryRes.Data 就是需要入库的数组,我们直接使用Data()函数赋值,进行批量插入就行了。(默认每次插入10条数据,可以通过batch(x)指定每次插入的数据条数)

dao.GomeCategory.Data(res.Data).Insert()

更优雅的写法如下

//获取商品类目接口
func (s *goMeGoodsService) GetCategory() {
	ctx := context.Background()
	//一级类名
	res, err := gome.Category.Get(ctx)
	if err != nil {
		checkErr(err, "GetCategory AddCategory")
	}
	//批量插入 优雅
	_, batchErr := dao.GomeCategory.Data(res.Data).Insert()
	if batchErr != nil {
		checkErr(batchErr, "批量更新一级目录失败")
	}
}

可以向上滑,看看优化前的代码是怎么写的。

优化后的代码完全实现了优化代码前的功能,且性能更好,因为使用了批量插入。

总结

避免这种重复定义map的代码, 合理使用gconv对map、结构体、结构体数组进行转换。

不要像下面这样写代码!NO!

//添加分类
func (s *goMeGoodsService) AddCategory(level int, code, name, parent_code string) (id int64, err error) {
	categoryMapping := map[string]interface{}{
		"level":       level,
		"code":        code,
		"name":        name,
		"parent_code": parent_code,
	}
	sqlRes, err := dao.GomeCategory.Data(categoryMapping).Insert()
	if err != nil {
		return
	}
	id, err = sqlRes.RowsAffected()
	if err != nil {
		return
	}
	return
}

要有这种优化代码的意识,当我们意识到重复定义时,就一定有办法优化。

当我们意识到逻辑混乱时,就一定有办法优化结构,混乱的逻辑往往是设计的不合理导致的。

以上就是GoFrame代码优化gconv类型转换避免重复定义map的详细内容,更多关于GoFrame gconv类型转换的资料请关注我们其它相关文章!

(0)

相关推荐

  • GoFrame框架garray对比PHP的array优势

    目录 打印结果 打印结果 打印结果 打印结果: 打印结果 打印结果 打印结果 写过PHP的同学都知道 PHP的数组Array非常好用,特别灵活. 我在写PHP之前使用Java做安卓开发,在接触PHP的数组Array之后,直呼太香了! 而在学习Go基础知识的时候了解到Go的数组和PHP的数组并不一样:从一定程度上讲,Go的slice切片类型和PHP的数组array比较像(不固定长度.引用类型.动态扩容等),但是在开发使用中远远不像PHP的array灵活. 初识GoFrame 最近在使用基于Go语言

  • GoFrame框架Scan类型转换实例

    目录 前言 方法定义 自动识别转换Struct结构体 示例代码 运行结果 自动识别转换Struct数组 示例代码 运行结果 自动识别转换Map 示例代码 运行结果 自动识别转换Map数组 示例代码 运行结果 总结 前言 Scan转换方法可以实现对任意参数到struct/struct数组/map/map数组的转换,并且根据开发者输入的转换目标参数自动识别执行转换. 方法定义 // Scan automatically calls MapToMap, MapToMaps, Struct or Str

  • GoFrame框架gset交差并补集使用实例

    目录 使用场景方法介绍 Intersect: 交集 Diff: 差集 Union: 并集 Complement: 补集 举例 总结 上一篇文章:GoFrame gset使用入门 | 对比PHP.Java.Redis 得到了大家不错的反馈,今天继续为大哥分享gset的更多知识点. 使用场景方法介绍 交差并补集有非常多的应用场景,合理的使用交差并补集能减少我们的DB查询次数. Intersect: 交集 交集,属于set且属于others的元素为元素的集合. func (set *Set) Inte

  • GoFrame框架gset使用对比PHP Java Redis优势

    目录 特点 使用入门 对比PHP和Java PHP JAVA GO原生 GoFrame 延伸 这篇文章将会为大家介绍GoFrame gset使用入门,为了让大家更好的理解,会简明扼要的分析一下集合类型Set的特点,对比一下Java.PHP.原生Go对集合Set类型的支持情况,如果不支持Set类型,我们如何找到解决方案,来实现元素不可重复性和交差并补集的需求. 特点 集合gset:一组不可重复的元素,元素可以是任何类型 上一篇文章介绍的: GoFrame的garray为什么比PHP的array还好

  • GoFrame gcache 缓存控制 淘汰策略

    目录 打印结果 缓存控制 打印结果 场景分析 代码示例 打印结果 GetOrSetFunc的使用 基本概念 gcache模块默认提供的是一个高速的内存缓存,操作效率非常高效,CPU性能损耗在ns纳秒级别.使用简单易上手,非常适合单机应用使用. 基本使用 我们可以通过gcache.New()创建一个缓存对象 也可以直接使用gcache包方法,使用方式都是一样的. 下面代码段介绍了gcache的基本使用: package main import ( "fmt" "github.c

  • GoFrame代码优化gconv类型转换避免重复定义map

    目录 前言 核心重点 优化前 优化后: 可以这么写的原因 进一步优化 批量写入 更优雅的写法如下 总结 前言 最近一直在研究 GoFrame 框架,经过一段时间的使用.总结.思考,发现确实不失为一款非常值得使用的企业级开发框架. 在我初识GoFrame教程后,曾整理过一篇文章: 非常适合PHP同学学习的GO框架:GoFrame,有兴趣的同学可以阅读一下. 今天重点讲一下我使用GoFrame的代码优化之旅. 核心重点 GoFrame几乎封装了所有能封装的东西,而我们需要做的就是在框架的基础上约定好

  • 基于spring cloud多个消费端重复定义feign client的问题

    目录 springcloud多个消费端重复定义feign client 在spring cloud+feignClient报错 springcloud多个消费端重复定义feign client spring cloud消费端调用服务提供者,有两种方式rest+ribbon和Feign,Feign是一个声明式的伪Http客户端更为简单易用,所以我们项目选用Feign作为服务通讯方式 项目有6个模块,A,B,C,D,E,F,模块之前必不可少的会存在相互调用的情况 问题来了.通过FeignClient

  • 浅谈Pytorch 定义的网络结构层能否重复使用

    前言:最近在构建网络的时候,有一些层参数一样,于是就没有定义新的层,直接重复使用了原来已经有的层,发现效果和模型大小都没有什么变化,心中产生了疑问:定义的网络结构层能否重复使用?因此接下来利用了一个小模型网络实验了一下. 一.网络结构一:(连续使用相同的层) 1.网络结构如下所示: class Cnn(nn.Module): def __init__(self): super(Cnn, self).__init__() self.conv1 = nn.Sequential( nn.Conv2d(

  • C++利用容器查找重复列功能实现

    复制代码 代码如下: # include <vector> # include <iostream> # include <set> using namespace std; int main(int argc, char * argv[]) { vector<int> v; //找一些数据来测试 for (int i = 0; i < 50; i++) v.push_back(rand() % 25); for (int i = 0; i <

  • Java map的学习及代码示例

    前言 最近正在做的高校云平台项目中接触Map比较多,关于map的使用不是很熟悉,所以在此将map的几个方法再次学习下. Map与Collection 提到Map集合接口就不能不提到Collection集合接口,map和Collection都是集合接口,Collection中包含了我们经常用的list和set子接口:而Map是与Collection处于平级的地位:Collection中存储的是一组对象,而Map存储的是一个键值对(key/value). Map java为数据结构中的映射定义了一个

  • Java 集合框架掌握 Map 和 Set 的使用(内含哈希表源码解读及面试常考题)

    目录 1. 搜索 1.1 场景引入 1.2 模型 2. Map 2.1 关于 Map 的介绍 2.2 关于 Map.Entry<K, V> 的介绍 2.3 Map 的常用方法说明 2.4 关于 HashMap 的介绍 2.5 关于 TreeMap 的介绍 2.6 HashMap 和 TreeMap 的区别 2.7 Map 使用示例代码 3. Set 3.1 关于 Set 的介绍 3.1 Set 的常用方法说明 3.3 关于 TreeSet 的介绍 3.4 关于 HashSet 的介绍 3.5

  • Java详解数据类型的定义与使用

    目录 标识符和关键字 标识符 什么是标识符 标识符的定义规则 关键字 常量和变量 常量 变量 变量的声明格式 变量的声明 基本数据类型 整数类型 浮点类型 浮点类型常量 浮点类型变量 字符类型 字符型 字符串型 布尔类型 基本数据类型的转换 自动类型转换 强制类型转换 标识符和关键字 标识符 读音 biao zhi fu 什么是标识符 包.类.变量.方法…等等,只要是起名的地方,那个名字就是标识符 标识符的定义规则 四个可以:可以是数字.字母.下划线(_).美元符号($),我们一般起名尽量使用英

  • Golang中map数据类型的使用方法

    目录 前言 案例 map map定义 map声明 map的操作 总结 前言 今天咱们来学习一下golang中的map数据类型,单纯的总结一下基本语法和使用场景,也不具体深入底层.map类型是什么呢?做过PHP的,对于数组这种数据类型是一点也不陌生了.PHP中的数组分为索引数组和关联数组.例如下面的代码: // 索引数组[数组的key是一个数字, 从0,1,2开始递增] $array = [1, '张三', 12]; // 关联数组[数组的key是一个字符串,可以自定义key的名称] $array

  • C++类中如何使用定义的类型别名

    目录 类中使用定义的类型别名 1 typedef定义类型别名 2 在类中使用typedef定义的类型别名 关于类型别名的总结 类中使用定义的类型别名 1 typedef定义类型别名 1.1 使用方法 在C++中,typedef关键字用来定义类型的别名. typedef int MYINT; 此时,MYINT是int的别名,可以将MYINT作为数据类型来定义其他变量. MYINT myint; 其中,myint的类型是MYINT . 1.2 注意事项 不能使用typedef对类型别名MYINT进行

随机推荐