通用的映射模式

query:="select id,name from user where id=?"
//单个结构体
ret:=&Activity{}
DbClient().Find(query,activityId).Unique(ret)
//结构体数组
ret:=[]Activity{}
DbClient().Find(query,activityId).List(&ret)

 

1.定义结构体

type Activity struct{
ID int64 `col:"id" json:"id"`
Name string `col:"name" json:"name"`
}

2.定义数据库对象

type dao struct {
data []map[string]string // 存储数据库查询数据
err error // 异常
}
var ProKDB *sql.DB

3. 将对象地址传给结构体

func (d *dao) Unique(in interface{}) error {
if len(d.data) > {
return d.mapping(d.data[], reflect.ValueOf(in))
}
return nil
}
func (d *dao) mapping(m map[string]string, v reflect.Value) error {
t := v.Type()
val := v.Elem()
typ := t.Elem() if !val.IsValid() {
return errors.New("数据类型不正确")
} for i := ; i < val.NumField(); i++ { value := val.Field(i)
kind := value.Kind()
tag := typ.Field(i).Tag.Get("col") if len(tag) > {
meta, ok := m[tag]
if !ok {
continue
} if !value.CanSet() {
return errors.New("结构体字段没有读写权限")
} if len(meta) == {
continue
} if kind == reflect.String {
value.SetString(meta)
} else if kind == reflect.Float32 {
f, err := strconv.ParseFloat(meta, )
if err != nil {
return err
}
value.SetFloat(f)
} else if kind == reflect.Float64 {
f, err := strconv.ParseFloat(meta, )
if err != nil {
return err
}
value.SetFloat(f)
} else if kind == reflect.Int64 {
integer64, err := strconv.ParseInt(meta, , )
if err != nil {
return err
}
value.SetInt(integer64)
} else if kind == reflect.Int {
integer, err := strconv.Atoi(meta)
if err != nil {
return err
}
value.SetInt(int64(integer))
} else if kind == reflect.Bool {
b, err := strconv.ParseBool(meta)
if err != nil {
return err
}
value.SetBool(b)
} else {
return errors.New("数据库映射存在不识别的数据类型")
}
}
}
return nil
} // 查询数据 func (d *dao) Find(sql string, args ...interface{}) *dao {
rows, err := ProKDB.Query(sql, args...)
if err != nil {
d.err = err
return d
} defer rows.Close()
err = d.query(rows)
if err != nil {
d.err = err
}
return d
} // 映射数据到 map[string]string
func (d *dao) query(rows *sql.Rows) error { column, err := rows.Columns() //读出查询出的列字段名
if err != nil {
logger.Error(err)
return err
} values := make([][]byte, len(column)) //values是每个列的值,这里获取到byte里
scans := make([]interface{}, len(column)) //因为每次查询出来的列是不定长的,用len(column)定住当次查询的长度 for i := range values {
scans[i] = &values[i]
} results := make([]map[string]string, ) //最后得到的map
for rows.Next() {
if err := rows.Scan(scans...); err != nil {
//query.Scan查询出来的不定长值放到scans[i] = &values[i],也就是每行都放在values里
logger.Error(err)
return err
} row := make(map[string]string) //每行数据
for k, v := range values {
//每行数据是放在values里面,现在把它挪到row里
key := column[k]
row[key] = string(v)
}
results = append(results, row)
}
d.data = results
return nil
}
// 将对象地址传出去
func (d *dao) Unique(in interface{}) error {
if len(d.data) > {
return d.mapping(d.data[], reflect.ValueOf(in))
}
return nil
}
func (d *dao) List(in interface{}) error {
if d.err != nil {
return d.err
} length := len(d.data) if length > {
v := reflect.ValueOf(in).Elem()
newv := reflect.MakeSlice(v.Type(), , length)
v.Set(newv)
v.SetLen(length) index :=
for i := ; i < length; i++ {
k := v.Type().Elem().Elem()
newObj := reflect.New(k)
err := d.mapping(d.data[i], newObj)
if err != nil {
return err
}
v.Index(index).Set(newObj)
index++
}
v.SetLen(index)
}
return nil
}


golang笔记(1)-数据库查询结果映射至结构体的更多相关文章

  1. 【Unity Shaders】学习笔记——SurfaceShader(二)两个结构体和CG类型

    [Unity Shaders]学习笔记——SurfaceShader(二)两个结构体和CG类型 转载请注明出处:http://www.cnblogs.com/-867259206/p/5596698. ...

  2. C/C++编程笔记:C语言对齐问题【结构体、栈内存以及位域对齐】

    引言 考虑下面的结构体定义: 假设这个结构体的成员在内存中是紧凑排列的,且c1的起始地址是0,则s的地址就是1,c2的地址是3,i的地址是4. 现在,我们编写一个简单的程序: 运行后输出: 为什么会这 ...

  3. oracle 开发笔记“跨数据库查询复制”

    1.方法一:创建DBL(data base link) CREATE PUBLIC DATABASE LINK 数据链名称 CONNECT TO 登陆用户名 IDENTIFIED BY 密码 USIN ...

  4. Java学习笔记 DbUtils数据库查询和log4j日志输出 使用

    DbUtils使用 QueryRunner DbUtils中定义了一个数据库操作类QueryRunner,所有的数据库操作CRUD都是通过此类来完成. 此类是线程安全的 方法名 对应sql语句 exc ...

  5. 【学习笔记】【C语言】指向结构体的指针

    1.指向结构体的指针的定义 struct Student *p;  2.利用指针访问结构体的成员 1> (*p).成员名称 2> p->成员名称 3.代码 #include < ...

  6. 《从零开始学Swift》学习笔记(Day 25)——类和结构体定义

    原创文章,欢迎转载.转载请注明:关东升的博客 Swift中的类和结构体定义的语法是非常相似的.类使用class关键词定义类,使用struct关键词定义结构体,它们的语法格式如下: class 类名 { ...

  7. Swift学习笔记(10):类和结构体

    目录: 基本 属性 方法 下标 继承 基本 使用class和struct关键字定义类和结构体. ・类是引用类型,结构体和枚举是值类型 ・值类型被赋予给一个变量.常量或被传递给一个函数时,已值拷贝方式传 ...

  8. Objective-C基础笔记(7)Foundation中的常用结构体

    一.NSRange NSRange的定义: typedef struct _NSRange { NSUInteger location; NSUInteger length; } NSRange; N ...

  9. C语言笔记 08_函数指针&回调函数&字符串&结构体&位域

    函数指针 函数指针是指向函数的指针变量. 通常我们说的指针变量是指向一个整型.字符型或数组等变量,而函数指针是指向函数. 函数指针可以像一般函数一样,用于调用函数.传递参数. 函数指针变量的声明: / ...

随机推荐

  1. AirplaceLogger源代码解析

    将源代码添加进Eclipse中,右键-->Import-->Existing Projects into Workspace-->选择AirplaceLogger源代码文件夹即可导入 ...

  2. java基础-day1

    第01天 java基础知识 今日内容介绍 u Java概述.helloworld案例 u 工具安装 .配置环境变量.注释.关键字 u 常量.变量.数据类型.标识符 第1章   Java概述 1.1  ...

  3. 几个经典的数学库之一学习---VCGlib(3)

    Camera and shot abstraction for managing views 视图的定义,以及mesh的操作说明. Shot(镜头) and camera(相机) shot摄像结构以及 ...

  4. 从SEQUENCE跳号说起

    http://blog.csdn.net/agaric717/article/details/6690890 一个应用上线后发现一个使用SEQUENCE值来生成的主键经常出现断号,而且断号不是一两个, ...

  5. Delphi 中 FindWindow 和 FindWindowEx 的语法和用法

    FindWindow(lpClassName,        {窗口的类名}lpWindowName: PChar {窗口的标题}): HWND;              {返回窗口的句柄; 失败返 ...

  6. Elasticsearch 的一些关键概念

    我更喜欢把 Elasticsearch 作为一种 nosql 去理解,它的一些开发概念和 MongoDB 以及 Redis 没有太大的区别,不过了解 Elasticsearch 中的一些核心概念对于你 ...

  7. test命令详解

    test命令格式: test condition 通常,在if-then-else语句中,用[]代替,即[ condition ].注意:方括号两边都要用空格.   1.数值比较 ========== ...

  8. C#基础复习(2) 之 装箱拆箱

    参考资料 [1] @只增笑耳Jason的回答 https://www.zhihu.com/question/57208269 [2] <C# 捷径教程> 疑难解答 装箱和拆箱是什么? 何时 ...

  9. WireShark 查看UDP码流的丢包率

    1.用wireshark抓包之后,右击,点decode as,转化为RTP 2. 点show all streams 3.分析

  10. [UWP]爱恋动漫BT开发小记

    在七月和某个人相识,在七月又和这个人重回陌路,在这个伤感的七月,让我来水一篇博客. 已经很久没有写博客了,最近现在来写一篇,总结一下这个七月. 今年的暑假特别的长,大概六月中旬就考完试了,而开学一直要 ...