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_函数指针&回调函数&字符串&结构体&位域
函数指针 函数指针是指向函数的指针变量. 通常我们说的指针变量是指向一个整型.字符型或数组等变量,而函数指针是指向函数. 函数指针可以像一般函数一样,用于调用函数.传递参数. 函数指针变量的声明: / ...
随机推荐
- Android真机调试试验
之前一直使用模拟器,很不好用,今天使用真机调试试验. 准备材料:电脑,Android手机. 首先,就遇到了一个问题,我的手机是华为的,之前不知道怎么回事,打开调试总是自动关闭,而且切换总是切换不了,老 ...
- SQL Server 2008 清空删除日志文件(瞬间日志变几M)
sql 在使用中每次查询都会生成日志,但是如果你长久不去清理,可能整个硬都堆满哦,笔者就遇到这样的情况,直接网站后台都进不去了.下面我们一起来学习一下如何清理这个日志吧 SQL2008清空删除日志: ...
- MYC编译器源码之词法分析
前文 .NET框架源码解读之MYC编译器 和 MYC编译器源码分析之程序入口 分别讲解了 SSCLI 里示例编译器的架构和程序入口,本文接着分析它的词法分析部分的代码. 词法解析的工作都由Tok类处 ...
- 对php和java里面的static函数和static的一些理解
static function: "static方法就是没有this的方法.在static方法里面不可以调用非静态方法,反过来是可以的.并且可以在没有创建任何对象的前提下,仅仅通过类名来调用 ...
- BitAdminCore框架应用篇:(二)创建一个简单的增删改查模块
NET Core应用框架之BitAdminCore框架应用篇系列 框架演示:http://bit.bitdao.cn 框架源码:https://github.com/chenyinxin/cookie ...
- js判断是否是数组
//判断是否是数组function isArray(obj) { return Object.prototype.toString.call(obj) === '[object Array]' ...
- CodeForces 540B School Marks
http://codeforces.com/problemset/problem/540/B School Marks Time Limit:2000MS Memory Limit:26214 ...
- log4net 未生成log 原因分析
本文假定你对log4net的配置以及在代码中的使用都非常熟悉,但就是没有按预想的生成log文件,正当你抓耳挠腮之时,那以下原因很可能是你解决问题的办法: 1.log4net.dll是否生成到程序运行目 ...
- Android 创建自定义 View 的属性 (attrs) 时需要注意的问题
自定义 View 的属性并不难,可以参照官方的文档 https://developer.android.com/training/custom-views/create-view.html 但是需要注 ...
- python salt 实现windows账户自动化
import random import string import json import logging import time import os import sys def usage(): ...