Tassdar资料

本文主要介绍Tassdar资料 方法和在新技术下所面对的“挑战”,方便大家深入理解Tassdar资料 过程。本文也将分享Tassdar资料 所遇到的问题和应对策略,怎么解决怎么做的问题。
通过深入本文可以理解代码原理,进行代码文档的下载,也可以查看相应 Demo 部署效果。

项目地址:https://github.com/yoyofxteam/yoyodata
欢迎星星,感谢

前言:最近在学习Go语言,就出于学习目的手撸个小架子,欢迎提出宝贵意见,项目使用Mysql数据库进行开发
我们还使用Go遵循ASP.NET Core的设计理念开发出了对应的Web框架:https://github.com/yoyofxteam/yoyogo
遵循C#命名规范开发出的反射帮助类库:https://github.com/yoyofxteam/yoyo-reflect
欢迎Star

首先,我们来看一下在Go中如果我想查询出数据库的数据都需要干些什么
1.引入MySQL驱动github.com/go-sql-driver/mysql
2.执行查询,可以看到控制台输出了数据库内容,并像你发出了祖安问候
Tassdar
但是这个驱动的自带方法十分原始,我们需要自己创建与数据库类型一致的变量,然后取值在给字段赋值,十分麻烦,所以我们要动手把这步搞成自动化的

想实现自动装配就要解决三个问题:1.自动创建变量来获取数据库值;2.把接受到值赋值给结构体对象;3.把对象拼接成一个对象数组进行返回
因为rows.Scan()方法要求我们必须传入和查询sql中:字段顺序和数量以及类型必须一致的变量,才可以成功接受到返回值,所以我们必须按需创建变量进行绑定,具体设计见下文

1. 创建两个结构体分别用来保存结构体和结构体的字段信息

 //类型缓存 type TypeInfo struct { 	//类型名称 	TypeName string 	//类型下的字段 	FieldInfo []FieldInfo }  //字段缓存 type FieldInfo struct { 	//字段索引值 	Index      int 	//字段名称 	FieldName  string 	FieldValue reflect.Value 	FieldType  reflect.StructField } 

2.封装一个方法用于获取结构体的元数据,保存到我们上面定义的结构体中

func ReflectTypeInfo(model interface{}) cache.TypeInfo { 	modelValue := reflect.ValueOf(model) 	modelType := reflect.TypeOf(model) 	//获取包名 	pkg := modelType.PkgPath() 	//获取完全限定类名 	typeName := pkg + modelType.Name() 	//判断对象的类型必须是结构体 	if modelValue.Kind() != reflect.Struct { 		panic("model must be struct !") 	} 	var fieldInfoArray []cache.FieldInfo 	for i := 0; i < modelValue.NumField(); i++ { 		fieldValue := modelValue.Field(i) 		//如果字段是一个结构体则不进行元数据的获取 		if fieldValue.Kind() == reflect.Struct { 			continue 		} 		//按照索引获取字段 		fieldType := modelType.Field(i) 		fieldName := fieldType.Name 		fieldInfoElement := cache.FieldInfo{ 			Index:      i, 			FieldName:  fieldName, 			FieldType:  fieldType, 			FieldValue: fieldValue, 		} 		fieldInfoArray = append(fieldInfoArray, fieldInfoElement) 	} 	typeInfo := cache.TypeInfo{ 		TypeName:  typeName, 		FieldInfo: fieldInfoArray, 	} 	return typeInfo } 

3.设计一个简单的缓存,把已经获取到元数据进行缓存避免重复获取

var TypeCache TypeInfoCache  type TypeInfoCache struct { 	sync.RWMutex 	Items map[string]TypeInfo }  //缓存初始化 func NewTypeInfoCache() {  	TypeCache = TypeInfoCache{ 		Items: make(map[string]TypeInfo), 	} }  //获取缓存 func (c *TypeInfoCache) GetTypeInfoCache(key string) (TypeInfo, bool) { 	c.RLock() 	defer c.RUnlock() 	value, ok := c.Items[key] 	if ok { 		return value, ok 	} 	return  value, false }  //添加缓存 func (c *TypeInfoCache) SetTypeInfoCache(key string, typeInfo TypeInfo) { 	c.RLock() 	defer c.RUnlock() 	c.Items[key] = typeInfo }  /** 从缓存中获取类型元数据信息 */ func GetTypeInfo(model interface{}) cache.TypeInfo { 	//使用 包名+结构体名作为缓存的Key 	modelType := reflect.TypeOf(model) 	typeName := modelType.PkgPath() + modelType.Name() 	typeInfo, ok := cache.TypeCache.GetTypeInfoCache(typeName) 	if ok { 		return typeInfo 	} 	typeInfo = ReflectTypeInfo(model) 	cache.TypeCache.SetTypeInfoCache(typeName, typeInfo) 	return typeInfo } 

4.封装一个方法执行SQL语句并返回对应结构体的数组(划重点)
设计思路:
执行sql语句获取到返回的数据集
获取要装配的结构体的元数据
根据sql返回字段找到对应的结构体字段进行匹配
装配要返回的结构体对象
组装一个对象数据进行返回

package queryable  import ( 	"database/sql" 	"github.com/yoyofxteam/yoyodata/cache" 	"github.com/yoyofxteam/yoyodata/reflectx" 	"reflect" 	"sort" 	"strings" )  type Queryable struct { 	DB    DbInfo 	Model interface{} }  /** 执行不带参数化的SQL查询 */ func (q *Queryable) Query(sql string, res interface{}) { 	db, err := q.DB.CreateNewDbConn() 	if err != nil { 		panic(err) 	} 	rows, err := db.Query(sql) 	if err != nil { 		panic(err) 	} 	//获取返回值的原始数据类型 	resElem := reflect.ValueOf(res).Elem() 	if resElem.Kind() != reflect.Slice { 		panic("value must be slice") 	} 	//获取对象完全限定名称和元数据 	modelName := reflectx.GetTypeName(q.Model) 	typeInfo := getTypeInfo(modelName, q.Model) 	//获取数据库字段和类型字段的对应关系键值对 	columnFieldSlice := contrastColumnField(rows, typeInfo) 	//创建用于接受数据库返回值的字段变量对象 	scanFieldArray := createScanFieldArray(columnFieldSlice) 	resEleArray := make([]reflect.Value, 0) 	//数据装配 	for rows.Next() { 		//创建对象 		dataModel := reflect.New(reflect.ValueOf(q.Model).Type()).Interface() 		//接受数据库返回值 		rows.Scan(scanFieldArray...) 		//为对象赋值 		setValue(dataModel, scanFieldArray, columnFieldSlice) 		resEleArray = append(resEleArray, reflect.ValueOf(dataModel).Elem()) 	} 	//利用反射动态拼接切片 	val := reflect.Append(resElem, resEleArray...) 	resElem.Set(val) 	//查询完毕后关闭链接 	db.Close() }  /** 数据库字段和类型字段键值对 */ type ColumnFieldKeyValue struct { 	//SQL字段顺序索引 	Index int 	//数据库列名 	ColumnName string 	//数据库字段名 	FieldInfo cache.FieldInfo }  /** 把数据库返回的值赋值到实体字段上 */ func setValue(model interface{}, data []interface{}, columnFieldSlice []ColumnFieldKeyValue) { 	modelVal := reflect.ValueOf(model).Elem() 	for i, cf := range columnFieldSlice { 		modelVal.Field(cf.FieldInfo.Index).Set(reflect.ValueOf(data[i]).Elem()) 	} }  /** 创建用于接受数据库数据的对应变量 */ func createScanFieldArray(columnFieldSlice []ColumnFieldKeyValue) []interface{} { 	var res []interface{} 	for _, data := range columnFieldSlice { 		res = append(res, reflect.New(data.FieldInfo.FieldValue.Type()).Interface()) 	} 	return res }  /** 根据SQL查询语句中的字段找到结构体的对应字段,并且记录索引值,用于接下来根据索引值来进行对象的赋值 */ func contrastColumnField(rows *sql.Rows, typeInfo cache.TypeInfo) []ColumnFieldKeyValue { 	var columnFieldSlice []ColumnFieldKeyValue 	columns, _ := rows.Columns() 	for _, field := range typeInfo.FieldInfo { 		for i, column := range columns { 			if strings.ToUpper(column) == strings.ToUpper(field.FieldName) { 				columnFieldSlice = append(columnFieldSlice, ColumnFieldKeyValue{ColumnName: column, Index: i, FieldInfo: field}) 			} 		} 	} 	//把获取到的键值对按照SQL语句查询字段的顺序进行排序,否则会无法赋值 	sort.SliceStable(columnFieldSlice, func(i, j int) bool { 		return columnFieldSlice[i].Index < columnFieldSlice[j].Index 	}) 	return columnFieldSlice }    /** 获取要查询的结构体的元数据,这个就是调用了一下第二部的那个方法 */ func getTypeInfo(key string, model interface{}) cache.TypeInfo { 	typeInfo, ok := cache.TypeCache.GetTypeInfoCache(key) 	if !ok { 		typeInfo = reflectx.GetTypeInfo(model) 	} 	return typeInfo }  

方法封装完毕,我们跑个单元测试看一下效果
Tassdar

目前这个小架子刚开始写,到发布这篇文档为止仅封装出了最基础的查询,接下来会实现Insert/Update等功能,并且会支持参数化查询,请
Tassdar资料部分资料来自网络,侵权毕设源码联系删除

区块链毕设网(www.qklbishe.com)全网最靠谱的原创区块链毕设代做网站
部分资料来自网络,侵权联系删除!
资源收费仅为搬运整理打赏费用,用户自愿支付 !
qklbishe.com区块链毕设代做网专注|以太坊fabric-计算机|java|毕业设计|代做平台 » Tassdar资料

提供最优质的资源集合

立即查看 了解详情