golang笔记(1)-数据库查询结果映射至结构体
通用的映射模式
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)-数据库查询结果映射至结构体的更多相关文章
- 【Unity Shaders】学习笔记——SurfaceShader(二)两个结构体和CG类型
[Unity Shaders]学习笔记——SurfaceShader(二)两个结构体和CG类型 转载请注明出处:http://www.cnblogs.com/-867259206/p/5596698. ...
- C/C++编程笔记:C语言对齐问题【结构体、栈内存以及位域对齐】
引言 考虑下面的结构体定义: 假设这个结构体的成员在内存中是紧凑排列的,且c1的起始地址是0,则s的地址就是1,c2的地址是3,i的地址是4. 现在,我们编写一个简单的程序: 运行后输出: 为什么会这 ...
- oracle 开发笔记“跨数据库查询复制”
1.方法一:创建DBL(data base link) CREATE PUBLIC DATABASE LINK 数据链名称 CONNECT TO 登陆用户名 IDENTIFIED BY 密码 USIN ...
- Java学习笔记 DbUtils数据库查询和log4j日志输出 使用
DbUtils使用 QueryRunner DbUtils中定义了一个数据库操作类QueryRunner,所有的数据库操作CRUD都是通过此类来完成. 此类是线程安全的 方法名 对应sql语句 exc ...
- 【学习笔记】【C语言】指向结构体的指针
1.指向结构体的指针的定义 struct Student *p; 2.利用指针访问结构体的成员 1> (*p).成员名称 2> p->成员名称 3.代码 #include < ...
- 《从零开始学Swift》学习笔记(Day 25)——类和结构体定义
原创文章,欢迎转载.转载请注明:关东升的博客 Swift中的类和结构体定义的语法是非常相似的.类使用class关键词定义类,使用struct关键词定义结构体,它们的语法格式如下: class 类名 { ...
- Swift学习笔记(10):类和结构体
目录: 基本 属性 方法 下标 继承 基本 使用class和struct关键字定义类和结构体. ・类是引用类型,结构体和枚举是值类型 ・值类型被赋予给一个变量.常量或被传递给一个函数时,已值拷贝方式传 ...
- Objective-C基础笔记(7)Foundation中的常用结构体
一.NSRange NSRange的定义: typedef struct _NSRange { NSUInteger location; NSUInteger length; } NSRange; N ...
- C语言笔记 08_函数指针&回调函数&字符串&结构体&位域
函数指针 函数指针是指向函数的指针变量. 通常我们说的指针变量是指向一个整型.字符型或数组等变量,而函数指针是指向函数. 函数指针可以像一般函数一样,用于调用函数.传递参数. 函数指针变量的声明: / ...
随机推荐
- AirplaceLogger源代码解析
将源代码添加进Eclipse中,右键-->Import-->Existing Projects into Workspace-->选择AirplaceLogger源代码文件夹即可导入 ...
- java基础-day1
第01天 java基础知识 今日内容介绍 u Java概述.helloworld案例 u 工具安装 .配置环境变量.注释.关键字 u 常量.变量.数据类型.标识符 第1章 Java概述 1.1 ...
- 几个经典的数学库之一学习---VCGlib(3)
Camera and shot abstraction for managing views 视图的定义,以及mesh的操作说明. Shot(镜头) and camera(相机) shot摄像结构以及 ...
- 从SEQUENCE跳号说起
http://blog.csdn.net/agaric717/article/details/6690890 一个应用上线后发现一个使用SEQUENCE值来生成的主键经常出现断号,而且断号不是一两个, ...
- Delphi 中 FindWindow 和 FindWindowEx 的语法和用法
FindWindow(lpClassName, {窗口的类名}lpWindowName: PChar {窗口的标题}): HWND; {返回窗口的句柄; 失败返 ...
- Elasticsearch 的一些关键概念
我更喜欢把 Elasticsearch 作为一种 nosql 去理解,它的一些开发概念和 MongoDB 以及 Redis 没有太大的区别,不过了解 Elasticsearch 中的一些核心概念对于你 ...
- test命令详解
test命令格式: test condition 通常,在if-then-else语句中,用[]代替,即[ condition ].注意:方括号两边都要用空格. 1.数值比较 ========== ...
- C#基础复习(2) 之 装箱拆箱
参考资料 [1] @只增笑耳Jason的回答 https://www.zhihu.com/question/57208269 [2] <C# 捷径教程> 疑难解答 装箱和拆箱是什么? 何时 ...
- WireShark 查看UDP码流的丢包率
1.用wireshark抓包之后,右击,点decode as,转化为RTP 2. 点show all streams 3.分析
- [UWP]爱恋动漫BT开发小记
在七月和某个人相识,在七月又和这个人重回陌路,在这个伤感的七月,让我来水一篇博客. 已经很久没有写博客了,最近现在来写一篇,总结一下这个七月. 今年的暑假特别的长,大概六月中旬就考完试了,而开学一直要 ...