使用原生的Golang进行数据库CRUD感觉到诸多不变,于是参照之前使用数据库类的习惯用法,封装了一个数据库操作方法集:
import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"
"log"
"strings"
"time"
)
type Dblib struct {
db *sql.DB
}
const (
DRIVER_NAME = "mysql"
USER_NAME = "root"
PASS_WORD = "123456"
HOST = "localhost"
PORT = "3306"
DATABASE = "imooc"
CHARSET = "utf8"
)
// 初始化链接
func NewMysqlConn() (*Dblib, error) {
dbDSN := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=%s", USER_NAME, PASS_WORD, HOST, PORT, DATABASE, CHARSET)
// 打开连接失败
db, err := sql.Open(DRIVER_NAME, dbDSN)
//defer MysqlDb.Close();
if err != nil {
log.Println("dbDSN: " + dbDSN)
return nil, err
//panic("数据源配置不正确: " + MysqlDbErr.Error())
}
// 最大连接数
db.SetMaxOpenConns(100)
// 闲置连接数
db.SetMaxIdleConns(20)
// 最大连接周期
db.SetConnMaxLifetime(100 * time.Second)
if err = db.Ping(); nil != err {
panic("数据库链接失败: " + err.Error())
return nil, err
}
p := new(Dblib)
p.db = db
return p, nil
}
type dbRow map[string]interface{}
func scanRow(rows *sql.Rows) (dbRow, error) {
columns, _ := rows.Columns()
vals := make([]interface{}, len(columns))
valsPtr := make([]interface{}, len(columns))
for i := range vals {
valsPtr[i] = &vals[i]
}
err := rows.Scan(valsPtr...)
if err != nil {
return nil, err
}
r := make(dbRow)
for i, v := range columns {
if va, ok := vals[i].([]byte); ok {
r[v] = string(va)
} else {
r[v] = vals[i]
}
}
return r, nil
}
// 获取一行记录
func (d *Dblib) GetOne(sql string, args ...interface{}) (dbRow, error) {
rows, err := d.db.Query(sql, args...)
if err != nil {
return nil, err
}
defer rows.Close()
rows.Next()
result, err := scanRow(rows)
return result, err
}
// 获取多行记录
func (d *Dblib) GetAll(sql string, args ...interface{}) ([]dbRow, error) {
rows, err := d.db.Query(sql, args...)
if err != nil {
return nil, err
}
defer rows.Close()
result := make([]dbRow, 0)
for rows.Next() {
r, err := scanRow(rows)
if err != nil {
continue
}
result = append(result, r)
}
return result, nil
}
// 写入记录
func (d *Dblib) Insert(table string, data dbRow) (int64, error) {
fields := make([]string, 0)
vals := make([]interface{}, 0)
placeHolder := make([]string, 0)
for f, v := range data {
fields = append(fields, f)
vals = append(vals, v)
placeHolder = append(placeHolder, "?")
}
sql := fmt.Sprintf("INSERT INTO %s(%s) VALUES(%s) ", table, strings.Join(fields, ","), strings.Join(placeHolder, ","))
result, err := d.db.Exec(sql, vals...)
if err != nil {
return 0, err
}
lID, err := result.LastInsertId()
if err != nil {
return 0, err
}
return lID, nil
}
// 更新记录
func (d *Dblib) Update(table, condition string, data dbRow, args ...interface{}) (int64, error) {
params := make([]string, 0)
vals := make([]interface{}, 0)
for f, v := range data {
params = append(params, f+"=?")
vals = append(vals, v)
}
sql := "UPDATE %s SET %s"
if condition != "" {
sql += " WHERE %s"
sql = fmt.Sprintf(sql, table, strings.Join(params, ","), condition)
vals = append(vals, args...)
} else {
sql = fmt.Sprintf(sql, table, strings.Join(params, ","))
}
result, err := d.db.Exec(sql, vals...)
if err != nil {
return 0, err
}
aID, err := result.RowsAffected()
if err != nil {
return 0, err
}
return aID, nil
}
// 删除记录
func (d *Dblib) Delete(table, condition string, args ...interface{}) (int64, error) {
sql := "DELETE FROM %s "
if condition != "" {
sql += "WHERE %s"
sql = fmt.Sprintf(sql, table, condition)
} else {
sql = fmt.Sprintf(sql, table)
}
result, err := d.db.Exec(sql, args...)
if err != nil {
return 0, err
}
aID, err := result.RowsAffected()
if err != nil {
return 0, err
}
return aID, nil
}
或者:针对数据库中的数据,使用go语言进行增删改查
import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"
)
//创建mysql 连接
func NewMysqlConn() (db *sql.DB, err error) {
db, err = sql.Open("mysql", "root:123@tcp(127.0.0.1:3306)/imooc?charset=utf8")
return
}
//获取返回值,获取一条
func GetResultRow(rows *sql.Rows) map[string]string{
columns, _ := rows.Columns()
scanArgs := make([]interface{}, len(columns))
values := make([]interface{}, len(columns))
for j := range values {
scanArgs[j] = &values[j]
}
record := make(map[string]string)
for rows.Next() {
//将行数据保存到record字典
rows.Scan(scanArgs...)
for i, v := range values {
if v != nil {
//fmt.Println(reflect.TypeOf(col))
record[columns[i]] = string(v.([]byte))
}
}
}
return record
}
//获取所有
func GetResultRows(rows *sql.Rows) map[int]map[string]string {
fmt.Println("获取全局数据")
//返回所有列
columns, _ := rows.Columns()
//这里表示一行所有列的值,用[]byte表示
vals := make([][]byte, len(columns))
//这里表示一行填充数据
scans := make([]interface{}, len(columns))
//这里scans引用vals,把数据填充到[]byte里
for k, _ := range vals {
scans[k] = &vals[k]
}
i := 0
result := make(map[int]map[string]string)
for rows.Next() {
//填充数据
rows.Scan(scans...)
//每行数据
row := make(map[string]string)
//把vals中的数据复制到row中
for k, v := range vals {
key := columns[k]
//这里把[]byte数据转成string
row[key] = string(v)
}
//放入结果集
result[i] = row
i++
}
return result
}
工具类:将map[string]string转化为结构体
import (
"errors"
"fmt"
"reflect"
"strconv"
"time"
)
//根据结构体中sql标签映射数据到结构体中并且转换类型
func DataToStructByTagSql(data map[string]string, obj interface{}) {
objValue := reflect.ValueOf(obj).Elem()
for key, value := range data {
strKey := fmt.Sprintf("data的: %v", key)
strValue := fmt.Sprintf("data的val:%v", value)
data[strKey] = strValue
}
for i := 0; i < objValue.NumField(); i++ {
fmt.Println("i的值为:" + strconv.Itoa(i))
fmt.Println("obj 结构体对应的下标为:" + objValue.Type().Field(i).Tag.Get("sql"))
//获取sql对应的值
value := data[objValue.Type().Field(i).Tag.Get("sql")]
fmt.Println("当前下标回去的Map对应的value值为:" + value)
//获取对应字段的名称
name := objValue.Type().Field(i).Name
//获取对应字段类型
structFieldType := objValue.Field(i).Type()
//获取变量类型,也可以直接写"string类型"
val := reflect.ValueOf(value)
var err error
if structFieldType != val.Type() {
//类型转换
val, err = TypeConversion(value, structFieldType.Name()) //类型转换
if err != nil {
}
}
//设置类型值
objValue.FieldByName(name).Set(val)
}
}
//类型转换
func TypeConversion(value string, ntype string) (reflect.Value, error) {
if ntype == "string" {
return reflect.ValueOf(value), nil
} else if ntype == "time.Time" {
t, err := time.ParseInLocation("2006-01-02 15:04:05", value, time.Local)
return reflect.ValueOf(t), err
} else if ntype == "Time" {
t, err := time.ParseInLocation("2006-01-02 15:04:05", value, time.Local)
return reflect.ValueOf(t), err
} else if ntype == "int" {
i, err := strconv.Atoi(value)
return reflect.ValueOf(i), err
} else if ntype == "int8" {
i, err := strconv.ParseInt(value, 10, 64)
return reflect.ValueOf(int8(i)), err
} else if ntype == "int32" {
i, err := strconv.ParseInt(value, 10, 64)
return reflect.ValueOf(int64(i)), err
} else if ntype == "int64" {
i, err := strconv.ParseInt(value, 10, 64)
return reflect.ValueOf(i), err
} else if ntype == "float32" {
i, err := strconv.ParseFloat(value, 64)
return reflect.ValueOf(float32(i)), err
} else if ntype == "float64" {
i, err := strconv.ParseFloat(value, 64)
return reflect.ValueOf(i), err
}
//else if .......增加其他一些类型的转换
return reflect.ValueOf(value), errors.New("未知的类型:" + ntype)
}
参考:
一个封装的Goland数据库操作方法集:https://www.jianshu.com/p/d630e45da6a3
Iris后台管理Demo:https://www.cnblogs.com/double-W/p/12594817.html