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_函数指针&回调函数&字符串&结构体&位域
函数指针 函数指针是指向函数的指针变量. 通常我们说的指针变量是指向一个整型.字符型或数组等变量,而函数指针是指向函数. 函数指针可以像一般函数一样,用于调用函数.传递参数. 函数指针变量的声明: / ...
随机推荐
- Hdu1978 How many ways 2017-01-18 14:32 40人阅读 评论(0) 收藏
How many ways Time Limit : 3000/1000ms (Java/Other) Memory Limit : 32768/32768K (Java/Other) Total ...
- MFC OnOk(),OnCancel(),OnClose(),OnDestroy()的区别总结
MFC OnOk(),OnCancel(),OnClose(),OnDestroy()的区别总结(转) 第一,OnOK()和OnCancel()是CDialog基类的成员函数,而OnClose()和O ...
- hdu 5017 模拟退火/三分求椭圆上离圆心最近的点的距离
http://acm.hdu.edu.cn/showproblem.php?pid=5017 求椭圆上离圆心最近的点的距离. 模拟退火和三分套三分都能解决 #include <cstdio> ...
- Need You Now --Lady Antebellum
战地女神(Lady Antebellum)由女主唱 Hillary Scott.男主唱 Charles Kelley .吉他/键盘手 Dave Haywood,2006夏天在美国乡村音乐重镇纳什维尔组 ...
- SSH中设置字符编码防止乱码
1.在web.xml中加入一个过滤器和过滤范围的配置 <filter><filter-name>encoding</filter-name><filter-c ...
- SyntaxError: Non-ASCII character '\xe5' in file test.py on line 1, but no encoding declared; see http://www.python.org/peps/pep-0263.html for details
python的默认编码文件是用的ASCII码,而你的python文件中使用了中文等非英语字符. 在Python源文件的最开始一行,加入一句: # coding=UTF-8
- c# list修改某一个属性的值
public class info() { public string name{get;set;} public string age{get;set;} } list<info> li ...
- 用.net开发音频编辑软件
智能语音机器人软件免不了需要对语音流进行处理,主要包括语音的播放.录制.读取.保存.图形化展示和剪辑等功能.这方面专业的软件有Adobe Audition,为了方便用户使用,我用.net实现了上述功能 ...
- 适合新手看的ref和out
面试的时候一般很高的概率会问到ref和out的区别...我们死记硬背的话很难记住. 建议大家和我一样简单的探索一下.动手试一下就能记住了. 共同点是我们在使用ref或者out的时候一定要在写的方法里面 ...
- onsrcoll和scrollTop兼容与实现
对于onscroll事件的支持 各浏览器 document.document.body.document.documentElement 对象的 onscroll 事件的支持存在差异. 所谓的支持性存 ...