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
}
总结
主要用到的是QueryOne
和QueryAll
函数!
一个是查询单个,返回得是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)
}