Go sql查询直接转map

Go sql查询直接转map

前言

Hello,大家好,我是星期八!

事情是这样婶的。

曾经我是哪么终于Python,爱的死去活来,直到,我遇到了Go!

我就对他一见钟情,简洁的语法,随意的打包exe,完美戳中我的心灵!

然后,我____

完整示例代码请直接滑到最底部

在使用Go时,发现的一些问题

其实,Go已经是一门,非常方便的静态编译语言了,跟Java相比,已经是非常幸福了!

反复鞭尸Java,hhh。

Python是如何查询Mysql

先看一下老情人Python是如何查询Mysql的!

代码

import pymysql

database = "dev_xcrm"
# 初始化连接
db = pymysql.connect("127.0.0.1", "root", "rootroot", database, cursorclass=pymysql.cursors.DictCursor)
# 创建游标
cursor = db.cursor()

sqlStr = "SELECT  * from app01_carinfochoices;"
cursor.execute(sqlStr)
rows = cursor.fetchall()
print(rows)

# 关闭连接
cursor.close()
db.close()

执行结果

在这里插入图片描述

在简单来看一下Go是如何查询Mysql的

如果你熟读百度用法,通常情况下,上述代码翻译成Go代码应该是这样婶的!

代码

package main

import (
	"database/sql"
	"fmt"
	_ "github.com/go-sql-driver/mysql"
)

func main() {
	var username = "root"
	var password = "rootroot"
	var ip = "127.0.0.1"
	var port = "3306"
	var data = "dev_xcrm"
	var dsn = fmt.Sprintf("%s:%s@tcp(%s:%s)/%s", username, password, ip, port, data)
	fmt.Println(dsn)
	//Open只会验证dsb的格式是否正确,不会验证是否连接成功,同理,密码是否正确也不知道
	db, err := sql.Open("mysql", dsn)
	if err != nil {
		panic(err)
	}
	//关闭连接在 err 之后,因为可能直接就打开不成功,关闭一个没有打开的连接???
	defer db.Close()
	// 此时尝试连接数据库,会判断用户,密码,ip地址,端口是否正确
	err = db.Ping()
	if err != nil {
		fmt.Println("连接数据库失败,", err)
		return
	}
	//设置与数据库建立连接的最大数目,一般不管
	db.SetMaxOpenConns(100)
	//设置连接池中的最大闲置连接数,一般不管
	db.SetMaxIdleConns(50)

	//查询单条
	type CarinfoChoices struct {
		Id    int64
		Title string
	}
	sqlStr := "SELECT  id,title from app01_carinfochoices;"
	rows, err := db.Query(sqlStr)
	if err != nil {
		fmt.Println("查询失败:", err)
		return
	}
	defer rows.Close()
	var carinfoChoicesList = make([]CarinfoChoices, 0, 10)
	for rows.Next(){
		var carinfoChoices CarinfoChoices
		err = rows.Scan(&carinfoChoices.Id, &carinfoChoices.Title)
		if err != nil {
			fmt.Println("绑定数据失败", err)
			return
		}
		carinfoChoicesList = append(carinfoChoicesList,carinfoChoices)
	}

	fmt.Println(carinfoChoicesList)
}

执行结果

在这里插入图片描述

静态语言的通病,先来一个类,Go是先来一个结构体!

啊,阿西吧,为什么如此麻烦,就没有简单的方案吗?

就不能像Python那样,直接查出来就是字典吗?直接就是一个一个的数据吗?

Go sql查询转map

功夫不负有心人,经过熟读百度,在经过自己的不断实验,终于将其封装成函数,特此供食用!

代码解读

从上往下就是代码顺序,分开解读而已

go.mod文件
module sql_to_map

go 1.14

require github.com/go-sql-driver/mysql v1.5.0
导入的包和全局变量
package main

import (
	"database/sql"
	"fmt"
	_ "github.com/go-sql-driver/mysql"
)

var (
	db       *sql.DB
	ip       string
	port     string
	username string
	password string
	database string
)
初始化Mysql连接信息
func initIni() {
    //可以从ini文件中获取
	ip = "127.0.0.1"
	port = "3306"
	username = "root"
	password = "rootroot"
	database = "dev_xcrm"
}
初始化Mysql连接
func initDB() (err error) {
	//连接字符串
	dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s", username, password, ip, port, database)
	fmt.Println(dsn)
	//Open只会验证dsb的格式是否正确,不会验证是否连接成功,同理,密码是否正确也不知道
	db, err = sql.Open("mysql", dsn)
	if err != nil {
		return err
	}
	// 此时尝试连接数据库,会判断用户,密码,ip地址,端口是否正确
	err = db.Ping()
	if err != nil {
		return err
	}
	return nil
}
查询一个
//查询一个
func QueryOne(sqlStr string, args ...interface{}) (map[string]string, error) {
	rows, err := db.Query(sqlStr, args...)
	if err != nil {
		return nil, err
	}
	//关闭rows链接
	defer rows.Close()
	//读出查询出的列字段名
	cols, _ := rows.Columns()
	//values是每个列的值,这里获取到byte里
	values := make([][]byte, len(cols))
	//query.Scan的参数,因为每次查询出来的列是不定长的,用len(cols)定住当次查询的长度
	scans := make([]interface{}, len(cols))
	//让每一行数据都填充到[][]byte里面,狸猫换太子
	for i := range values {
		scans[i] = &values[i]
	}
	//获取单行必须Next()
	rows.Next()
	row := make(map[string]string)
	//传指针进去,但是不通过指针能获取值
	err = rows.Scan(scans...)
	if err != nil {
		return row, nil
	}
	for k, v := range values {
		//cols[k]为字段名
		key := cols[k]
		row[key] = string(v)
	}
	return row, nil
}
查询所有
//查询所有
func QueryAll(sqlStr string, args ...interface{}) ([]map[string]string, error) {
	rows, err := db.Query(sqlStr, args...)
	if err != nil {
		return nil, err
	}
	//函数结束释放链接
	defer rows.Close()
	//读出查询出的列字段名
	cols, _ := rows.Columns()
	//values是每个列的值,这里获取到byte里
	values := make([][]byte, len(cols))
	//query.Scan的参数,因为每次查询出来的列是不定长的,用len(cols)定住当次查询的长度
	scans := make([]interface{}, len(cols))
	//让每一行数据都填充到[][]byte里面,狸猫换太子
	for i := range values {
		scans[i] = &values[i]
	}
	results := make([]map[string]string, 0, 10)
	for rows.Next() {
		err := rows.Scan(scans...)
		if err != nil {
			return nil, err
		}
		row := make(map[string]string, 10)
		for k, v := range values { //每行数据是放在values里面,现在把它挪到row里
			key := cols[k]
			row[key] = string(v)
		}
		results = append(results, row)
	}
	//返回数据
	return results, nil
}
main(使用示例)
func main() {
	initIni()
	err := initDB()
	if err != nil {
		fmt.Println("错误:", err)
		return
	}
	defer db.Close()
	//fmt.Println("-->",db)

	//查询单个
	sqlStr := "SELECT  * from app01_carinfochoices;"
	row, err := QueryOne(sqlStr, )
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println("查询单个:", row)

	//查询所有
	sqlStr = "SELECT  * from app01_carinfochoices;"
	rows, err := QueryAll(sqlStr, )
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println("查询所有:", rows)

	//查询多个,带条件查询,使用?占位符充当参数拼接
	sqlStr = "SELECT  * from app01_carinfochoices where id>?;"
	rows, err = QueryAll(sqlStr,1 )
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println("带条件查询:", rows)
}
执行结果

在这里插入图片描述

SQLServer配置

上述是Mysql配置,如果需要数据库是SQLServer,只需要修改initDB即可,其他不用变!

//全局变量
var (
	db       *sql.DB
	ip       string
	port     string
	username string
	password string
	database string
)

func initIni() {
	ip = "192.168.99.217"
	port = "53919"
	username = "sa"
	password = "123456"
	database = "test"
}

//初始化sqlserver
func initDB() (err error) {
	//连接字符串
	dsn := fmt.Sprintf("server=%s;port=%s;database=%s;user id=%s;password=%s;encrypt=disable", ip, port, database, username, password)
	fmt.Println(dsn)
	//Open只会验证dsb的格式是否正确,不会验证是否连接成功,同理,密码是否正确也不知道
	db, err = sql.Open("mssql", dsn)
	if err != nil {
		return errors.New("格式错误")
	}
	// 此时尝试连接数据库,会判断用户,密码,ip地址,端口是否正确
	err = db.Ping()
	if err != nil {
		return errors.New("配置错误")
	}
	return nil
}

总结

主要用到的是QueryOneQueryAll函数!

一个是查询单个,返回得是map[string]string格式数据!

一个是查询所有,返回得是[map[string]string,...]格式数据!

注意了啊,Go的map[id:1]等于Python的{"id":"1"},只是展现形式不一样!

如果在操作过程中有任何问题,记得下面留言,我们看到会第一时间解决问题。

乾坤未定,你我皆是黑马。

我是码农星期八,如果觉得还不错,记得动手点赞一下哈。

感谢你的观看。

完整代码

// main.go
package main

import (
	"database/sql"
	"fmt"
	_ "github.com/go-sql-driver/mysql"
)

var (
	db       *sql.DB
	ip       string
	port     string
	username string
	password string
	database string
)

func initIni() {
	ip = "127.0.0.1"
	port = "3306"
	username = "root"
	password = "rootroot"
	database = "dev_xcrm"
}

//查询一个
func QueryOne(sqlStr string, args ...interface{}) (map[string]string, error) {
	rows, err := db.Query(sqlStr, args...)
	if err != nil {
		return nil, err
	}
	//关闭rows链接
	defer rows.Close()
	//读出查询出的列字段名
	cols, _ := rows.Columns()
	//values是每个列的值,这里获取到byte里
	values := make([][]byte, len(cols))
	//query.Scan的参数,因为每次查询出来的列是不定长的,用len(cols)定住当次查询的长度
	scans := make([]interface{}, len(cols))
	//让每一行数据都填充到[][]byte里面,狸猫换太子
	for i := range values {
		scans[i] = &values[i]
	}
	//获取单行必须Next()
	rows.Next()
	row := make(map[string]string)
	//传指针进去,但是不通过指针能获取值
	err = rows.Scan(scans...)
	if err != nil {
		return row, nil
	}
	for k, v := range values {
		//cols[k]为字段名
		key := cols[k]
		row[key] = string(v)
	}
	return row, nil
}

//查询所有
func QueryAll(sqlStr string, args ...interface{}) ([]map[string]string, error) {
	rows, err := db.Query(sqlStr, args...)
	if err != nil {
		return nil, err
	}
	//函数结束释放链接
	defer rows.Close()
	//读出查询出的列字段名
	cols, _ := rows.Columns()
	//values是每个列的值,这里获取到byte里
	values := make([][]byte, len(cols))
	//query.Scan的参数,因为每次查询出来的列是不定长的,用len(cols)定住当次查询的长度
	scans := make([]interface{}, len(cols))
	//让每一行数据都填充到[][]byte里面,狸猫换太子
	for i := range values {
		scans[i] = &values[i]
	}
	results := make([]map[string]string, 0, 10)
	for rows.Next() {
		err := rows.Scan(scans...)
		if err != nil {
			return nil, err
		}
		row := make(map[string]string, 10)
		for k, v := range values { //每行数据是放在values里面,现在把它挪到row里
			key := cols[k]
			row[key] = string(v)
		}
		results = append(results, row)
	}
	//返回数据
	return results, nil
}

//初始化mysql
func initDB() (err error) {
	//连接字符串
	dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s", username, password, ip, port, database)
	fmt.Println(dsn)
	//Open只会验证dsb的格式是否正确,不会验证是否连接成功,同理,密码是否正确也不知道
	db, err = sql.Open("mysql", dsn)
	if err != nil {
		return err
	}
	// 此时尝试连接数据库,会判断用户,密码,ip地址,端口是否正确
	err = db.Ping()
	if err != nil {
		return err
	}
	return nil
}
func main() {
	initIni()
	err := initDB()
	if err != nil {
		fmt.Println("错误:", err)
		return
	}
	defer db.Close()
	//fmt.Println("-->",db)

	//查询单个
	sqlStr := "SELECT  * from app01_carinfochoices;"
	row, err := QueryOne(sqlStr, )
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println("查询单个:", row)

	//查询所有
	sqlStr = "SELECT  * from app01_carinfochoices;"
	rows, err := QueryAll(sqlStr, )
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println("查询所有:", rows)

	//查询多个,带条件查询,使用?占位符充当参数拼接
	sqlStr = "SELECT  * from app01_carinfochoices where id>?;"
	rows, err = QueryAll(sqlStr,1 )
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println("带条件查询:", rows)
}
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值