🎨 改进代码结构

This commit is contained in:
Yiwen-Chan
2021-03-18 18:13:50 +08:00
parent c7b86e767e
commit 0b9b507740
13 changed files with 543 additions and 813 deletions

View File

@@ -3,19 +3,22 @@ package utils
import (
"database/sql"
"errors"
"fmt"
"reflect"
"strings"
_ "github.com/mattn/go-sqlite3"
)
// Sqlite 数据库对象
type Sqlite struct {
DB *sql.DB
DBPath string
}
// DBCreate 根据结构体生成数据库tabletag为"id"为主键,自增
func (db *Sqlite) DBCreate(objptr interface{}) (err error) {
// Create 生成数据库
// 默认结构体的第一个元素为主键
// 返回错误
func (db *Sqlite) Create(table string, objptr interface{}) (err error) {
if db.DB == nil {
database, err := sql.Open("sqlite3", db.DBPath)
if err != nil {
@@ -23,95 +26,127 @@ func (db *Sqlite) DBCreate(objptr interface{}) (err error) {
}
db.DB = database
}
table := fmt.Sprintf("CREATE TABLE IF NOT EXISTS %s (", Struct2name(objptr))
for i, column := range strcut2columns(objptr) {
table += fmt.Sprintf(" %s %s NULL", column, column2type(objptr, column))
if i+1 != len(strcut2columns(objptr)) {
table += ","
} else {
table += " );"
var (
tags = tags(objptr)
kinds = kinds(objptr)
top = len(tags) - 1
cmd = []string{}
)
cmd = append(cmd, "CREATE TABLE IF NOT EXISTS")
cmd = append(cmd, table)
cmd = append(cmd, "(")
for i := range tags {
cmd = append(cmd, tags[i])
cmd = append(cmd, kinds[i])
switch i {
default:
cmd = append(cmd, "NULL,")
case 0:
cmd = append(cmd, "PRIMARY KEY")
cmd = append(cmd, "NOT NULL,")
case top:
cmd = append(cmd, "NULL);")
}
}
if _, err := db.DB.Exec(table); err != nil {
if _, err := db.DB.Exec(strings.Join(cmd, " ")); err != nil {
return err
}
return nil
}
// DBInsert 根据结构体插入一条数据
func (db *Sqlite) DBInsert(objptr interface{}) (err error) {
defer func() {
if err := recover(); err != nil {
panic(err)
}
}()
rows, err := db.DB.Query("SELECT * FROM " + Struct2name(objptr))
// Insert 插入数据
// 默认结构体的第一个元素为主键
// 返回错误
func (db *Sqlite) Insert(table string, objptr interface{}) (err error) {
rows, err := db.DB.Query("SELECT * FROM " + table)
if err != nil {
return err
}
defer rows.Close()
columns, _ := rows.Columns()
index := -1
names := "("
insert := "("
for i, column := range columns {
if column == "id" {
index = i
continue
}
if i != len(columns)-1 {
names += column + ","
insert += "?,"
} else {
names += column + ")"
insert += "?)"
tags, _ := rows.Columns()
var (
values = values(objptr)
top = len(tags) - 1
cmd = []string{}
)
cmd = append(cmd, "INSERT INTO")
cmd = append(cmd, table)
for i := range tags {
switch i {
default:
cmd = append(cmd, tags[i])
cmd = append(cmd, ",")
case 0:
cmd = append(cmd, "(")
cmd = append(cmd, tags[i])
cmd = append(cmd, ",")
case top:
cmd = append(cmd, tags[i])
cmd = append(cmd, ")")
}
}
stmt, err := db.DB.Prepare("INSERT INTO " + Struct2name(objptr) + names + " values " + insert)
for i := range tags {
switch i {
default:
cmd = append(cmd, "?")
cmd = append(cmd, ",")
case 0:
cmd = append(cmd, "VALUES (")
cmd = append(cmd, "?")
cmd = append(cmd, ",")
case top:
cmd = append(cmd, "?")
cmd = append(cmd, ")")
}
}
stmt, err := db.DB.Prepare(strings.Join(cmd, " "))
if err != nil {
return err
}
value := []interface{}{}
if index == -1 {
value = append(value, struct2values(objptr, columns)...)
} else {
value = append(value, append(struct2values(objptr, columns)[:index], struct2values(objptr, columns)[index+1:]...)...)
}
_, err = stmt.Exec(value...)
_, err = stmt.Exec(values...)
if err != nil {
return err
}
return nil
}
// DBSelect 根据结构体查询对应的表cmd可为"WHERE id = 0 "
func (db *Sqlite) DBSelect(objptr interface{}, cmd string) (err error) {
rows, err := db.DB.Query(fmt.Sprintf("SELECT * FROM %s %s", Struct2name(objptr), cmd))
// Select 查询数据库
// condition 可为"WHERE id = 0"
// 默认字段与结构体元素顺序一致
// 返回错误
func (db *Sqlite) Select(table string, objptr interface{}, condition string) (err error) {
var cmd = []string{}
cmd = append(cmd, "SELECT * FROM ")
cmd = append(cmd, table)
cmd = append(cmd, condition)
rows, err := db.DB.Query(strings.Join(cmd, " "))
if err != nil {
return err
}
defer rows.Close()
for rows.Next() {
columns, err := rows.Columns()
if err != nil {
return err
}
err = rows.Scan(struct2addrs(objptr, columns)...)
err = rows.Scan(addrs(objptr)...)
if err != nil {
return err
}
return nil
}
return errors.New("Database no such elem")
return errors.New("数据库无此条件项目")
}
// DBDelete 删除struct对应表的一行返回错误
func (db *Sqlite) DBDelete(objptr interface{}, cmd string) (err error) {
stmt, err := db.DB.Prepare(fmt.Sprintf("DELETE FROM %s %s", Struct2name(objptr), cmd))
// Delete 删除数据库
// condition 可为"WHERE id = 0"
// 返回错误
func (db *Sqlite) Delete(table string, condition string) (err error) {
var cmd = []string{}
cmd = append(cmd, "DELETE FROM")
cmd = append(cmd, table)
cmd = append(cmd, condition)
stmt, err := db.DB.Prepare(strings.Join(cmd, " "))
if err != nil {
return err
}
@@ -122,9 +157,13 @@ func (db *Sqlite) DBDelete(objptr interface{}, cmd string) (err error) {
return nil
}
// DBNum 查询struct对应表的行数,返回行数以及错误
func (db *Sqlite) DBNum(objptr interface{}) (num int, err error) {
rows, err := db.DB.Query(fmt.Sprintf("SELECT * FROM %s", Struct2name(objptr)))
// Num 查询数据库行数
// 返回行数以及错误
func (db *Sqlite) Num(table string) (num int, err error) {
var cmd = []string{}
cmd = append(cmd, "SELECT * FROM")
cmd = append(cmd, table)
rows, err := db.DB.Query(strings.Join(cmd, " "))
if err != nil {
return num, err
}
@@ -135,90 +174,72 @@ func (db *Sqlite) DBNum(objptr interface{}) (num int, err error) {
return num, nil
}
// strcut2columns 反射得到结构体的 tag 数组
func strcut2columns(objptr interface{}) []string {
var columns []string
// tags 反射 返回结构体对象的 tag 数组
func tags(objptr interface{}) []string {
var tags []string
elem := reflect.ValueOf(objptr).Elem()
// TODO 判断第一个元素是否为匿名字段
if elem.Type().Field(0).Anonymous {
elem = elem.Field(0)
}
for i, flen := 0, elem.Type().NumField(); i < flen; i++ {
columns = append(columns, elem.Type().Field(i).Tag.Get("db"))
tags = append(tags, elem.Type().Field(i).Tag.Get("db"))
}
return columns
return tags
}
// Struct2name 反射得到结构体的名字
func Struct2name(objptr interface{}) string {
return reflect.ValueOf(objptr).Elem().Type().Name()
}
// column2type 反射得到结构体对应 tag 的 数据库数据类型
func column2type(objptr interface{}, column string) string {
type_ := ""
// kinds 反射 返回结构体对象的 kinds 数组
func kinds(objptr interface{}) []string {
var kinds []string
elem := reflect.ValueOf(objptr).Elem()
// TODO 判断第一个元素是否为匿名字段
if elem.Type().Field(0).Anonymous {
elem = elem.Field(0)
}
for i, flen := 0, elem.Type().NumField(); i < flen; i++ {
if column == elem.Type().Field(i).Tag.Get("db") {
type_ = elem.Field(i).Type().String()
switch elem.Field(i).Type().String() {
case "int64":
kinds = append(kinds, "INT")
case "string":
kinds = append(kinds, "TEXT")
default:
kinds = append(kinds, "TEXT")
}
}
if column == "id" {
return "INTEGER PRIMARY KEY"
}
switch type_ {
case "int64":
return "INT"
case "string":
return "TEXT"
default:
return "TEXT"
}
return kinds
}
// struct2addrs 反射得到结构体对应数据库字段的属性地址
func struct2addrs(objptr interface{}, columns []string) []interface{} {
var addrs []interface{}
elem := reflect.ValueOf(objptr).Elem()
// TODO 判断第一个元素是否为匿名字段
if elem.Type().Field(0).Anonymous {
elem = elem.Field(0)
}
for _, column := range columns {
for i, flen := 0, elem.Type().NumField(); i < flen; i++ {
if column == elem.Type().Field(i).Tag.Get("db") {
addrs = append(addrs, elem.Field(i).Addr().Interface())
}
}
}
return addrs
}
// struct2values 反射得到结构体对应数据库字段的属性值
func struct2values(objptr interface{}, columns []string) []interface{} {
// values 反射 返回结构体对象的 values 数组
func values(objptr interface{}) []interface{} {
var values []interface{}
elem := reflect.ValueOf(objptr).Elem()
// TODO 判断第一个元素是否为匿名字段
if elem.Type().Field(0).Anonymous {
elem = elem.Field(0)
}
for _, column := range columns {
for i, flen := 0, elem.Type().NumField(); i < flen; i++ {
if column == elem.Type().Field(i).Tag.Get("db") {
switch elem.Field(i).Type().String() {
case "int64":
values = append(values, elem.Field(i).Int())
case "string":
values = append(values, elem.Field(i).String())
default:
values = append(values, elem.Field(i).String())
}
}
for i, flen := 0, elem.Type().NumField(); i < flen; i++ {
switch elem.Field(i).Type().String() {
case "int64":
values = append(values, elem.Field(i).Int())
case "string":
values = append(values, elem.Field(i).String())
default:
values = append(values, elem.Field(i).String())
}
}
return values
}
// addrs 反射 返回结构体对象的 addrs 数组
func addrs(objptr interface{}) []interface{} {
var addrs []interface{}
elem := reflect.ValueOf(objptr).Elem()
// TODO 判断第一个元素是否为匿名字段
if elem.Type().Field(0).Anonymous {
elem = elem.Field(0)
}
for i, flen := 0, elem.Type().NumField(); i < flen; i++ {
addrs = append(addrs, elem.Field(i).Addr().Interface())
}
return addrs
}