Go语言中database/sql的用法介绍

 更新时间:2023年05月19日 09:41:52   作者:今天捡到一百块钱  
Go语言中的database/sql包定义了对数据库的一系列操作,database/sql/driver包定义了应被数据库驱动实现的接口,这些接口会被sql包使用,本文将详细给大家介绍Go的database/sql的使用方法,需要的朋友可以参考下

零、windows系统安装MySQL

mysqld --install // 将mysql设置成系统服务
mysqld --remove  // 取消MySQL作为系统服务 
  • 修改MySQL的登录密码
mysqladmin -uroot -p原密码 password 新密码
mysqladmin -uroot -p password 123456 // 刚安装的MySQL默认是没有密码的

一、简介

Go 语言中的 database/sql 包定义了对数据库的一系列操作。database/sql/driver 包定义了应被数据库驱动实现的接口,这些接口会被 sql 包使用。但是 Go 语言没有提供任何官方的数据库驱动,所以我们需要导入第三方的数据库驱动。不过我们连接数据库之后对数据库操作的大部分代码都使用sql 包。 目前go用的比较多的关系型数据库有mysql和sqlite3,以下是第三方的驱动地址。

二、连接数据库

代码实现

package main

import (
	"database/sql"
	_ "github.com/go-sql-driver/mysql" // It is important
	"log"
)

func main() {
	dsn := "root:123456@tcp(127.0.0.1:3306)/test?charset=utf8mb4&parseTime=True&loc=Local"
	db, err := sql.Open("mysql", dsn)
	if err != nil {
		panic(err)
	}

	// ping是尝试连接MySQL数据库
	if err = db.Ping(); err != nil {
		panic(err)
	}
	log.Println("连接成功")
    
    // 关闭连接
    defer db.Close()
}

代码解释

  • 使用mysql驱动,必须引入"github.com/go-sql-mysql/mysql"
  • dsn:是待连接数据库信息。格式如下:
// username:password@[tcp(ip:port)]/dbname?charset=utf8mb4&parseTime=True&loc=Local
// 用户名:密码@[协议(地址:端口)]/数据库名?charset=utf8mb4&parseTime=True&loc=Local

dsn := "root:123456@tcp(127.0.0.1:3306)/test?charset=utf8mb4&parseTime=True&loc=Local"
  • sql.Open():打开一个数据库

  • Ping():检验数据库连接是否有效

三、增删改查操作

1. 数据的增删改查

package main

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

var db *sql.DB

// InitDB 数据库连接初始化
func InitDB() (err error) {
	dsn := "root:1qa2ws3ed@tcp(127.0.0.1:3306)/gouse"

	db, err = sql.Open("mysql", dsn)
	CheckErr(err)

	err = db.Ping()
	CheckErr(err)
	fmt.Println("数据库连接成功...")
	// 设置数据库连接池最大连接数
	db.SetConnMaxLifetime(10)

	//设置最大闲置连接数
	db.SetMaxIdleConns(5)

	return

}

// CheckErr 统一处理错误
func CheckErr(err error) {
	if err != nil {
		fmt.Println(err)
		panic(err)
	}
}

type User struct {
	ID       int32
	Username string
	Password string
	Email    string
}

func main() {
    if err := InitDB(); err != nil {
        fmt.Println("连接数据库失败")
        panic(err)
    }
    fmt.Println("接下来,请开始你的表演")
}

func createUser(user User) {
	// 1. 写sql语句
	sqlStr := "insert into user (username. password, email) values(?, ?, ?)"

	// 2. 执行sql语句
	exec, _ := db.Exec(sqlStr, user.Username, user.Password, user.Email)
	if affectCount, err := exec.RowsAffected(); affectCount == 0 && err != nil {
		fmt.Println("新建数据失败")
		panic(err)
	}
	fmt.Println("新建数据成功")
}

func createUser(user User) {
	// 1. 写sql语句
	sqlStr := "insert into user (username. password, email) values(?, ?, ?)"

	// 2. 执行sql语句
	exec, _ := db.Exec(sqlStr, user.Username, user.Password, user.Email)
	if affectCount, err := exec.RowsAffected(); affectCount == 0 && err != nil {
		fmt.Println("新建数据失败")
		panic(err)
	}
	fmt.Println("新建数据成功")
}

func createUser(user User) {
	// 1. 写sql语句
	sqlStr := "insert into user (username. password, email) values(?, ?, ?)"

	// 2. 执行sql语句
	exec, _ := db.Exec(sqlStr, user.Username, user.Password, user.Email)
	if affectCount, err := exec.RowsAffected(); affectCount == 0 && err != nil {
		fmt.Println("新建数据失败")
		panic(err)
	}
	fmt.Println("新建数据成功")
}

func deleteUser(id int) {
	// 1. 写sql语句
	sqlStr := "delete from user where id = ?"

	// 2. 执行sql语句
	exec, _ := db.Exec(sqlStr, id)
	if affectCount, err := exec.RowsAffected(); affectCount == 0 && err != nil {
		fmt.Println("删除数据失败")
		panic(err)
	}
	fmt.Println("删除数据成功")

}

func updateUser(user User) {
	// 1. 写sql语句
	sqlStr := "update user set username = ?, password = ? where id = ?"

	// 2. 执行sql语句
	exec, _ := db.Exec(sqlStr, user.Username, user.Password, user.ID)
	if affectCount, err := exec.RowsAffected(); affectCount == 0 && err != nil {
		fmt.Println("更新数据失败")
		panic(err)
	}
	fmt.Println("更新数据成功")

}

func selectUserRow(id int32) {
	// 1. 写sql语句
	sqlStr := "select * from user where id = ?"

	// 2. 执行sql语句
	row := db.QueryRow(sqlStr, id)
	user := User{}
	err := row.Scan(&user.ID, &user.Username, &user.Password, &user.Email)
	if err != nil {
		fmt.Println("查询数据失败")
		panic(err)
	}
	fmt.Printf("id = %d,username = %s,password = %s,email = %s\n", user.ID, user.Username, user.Password, user.Email)
}

func selectUserRows(id []int) {
	// 1. 写sql语句
	sqlStr := "select * from user where id in (?)"

	// 2. 执行sql语句
	rows, err := db.Query(sqlStr, id)

	if err != nil {
		fmt.Println("查询数据失败")
		panic(err)
	}
	for rows.Next() {
		user := User{}
		err := rows.Scan(&user.ID, &user.Username, &user.Password, &user.Email)
		if err != nil {
			fmt.Println("解析数据失败")
			panic(err)
		}
		fmt.Printf("id = %d,username = %s,password = %s,email = %s\n", user.ID, user.Username, user.Password, user.Email)
	}

}

2. SQL的预处理

  • 什么是预处理?
    • 普通SQL语句的执行过程
      • 客户端对SQL语句进行占位符的替换得到了完整的SQL语句
      • 客户端发送完整SQL语句到MySQL服务端
      • MySQL服务端执行完整的SQL语句并将结果返回终端
    • 预处理的执行过程
      • 先把SQL语句拆分成两部分,SQL语句部分和参数部分
      • 先把SQL语句部分发送给MySQL服务端进行SQL预处理
      • 然后参数部分发送给MySQL服务端,MySQL对SQL语句进行拼接
      • MySQL服务端执行完整的SQL语句返回结果
  • 为什么要预处理
    • 优化MySQL服务器重复执行SQL的方法。可以执行服务器的性能,提前让服务器编译,一次编译多次执行,节省后续重复编译的成本
    • 避免SQL注入

对于go中操作数据库的预处理,方法是Proload,重要的是返回一个Stmt结构体的指针,和之前的DB结构体一样的使用。

func preloadSelect(id int)  {
	// 1. 写sql语句
	sqlStr := "select * from user where id = ?"

	stmt, err := db.Prepare(sqlStr)
	if err != nil {
		fmt.Println("预处理sql语句失败")
		panic(err)
	}
	row := stmt.QueryRow(id)
	user := User{}
	err = row.Scan(&user.ID, &user.Username, &user.Password, &user.Email)
	if err != nil {
		fmt.Println("查询数据失败")
		panic(err)
	}
	fmt.Printf("id = %d,username = %s,password = %s,email = %s\n", user.ID, user.Username, user.Password, user.Email)
}

3. SQL的事务

在go中开启数据库的事务主要就是三个函数:Begin()Commit()RollBack()

  • func (db *DB) Begin()(*Tx, error):开启事务
  • func (tx *Tx) Commit() error:提交输入
  • func (tx *Tx) Rollback() error:事务回滚、
func TranSaCtIon() {
	// 开启事务
	tx, err := db.Begin()
    if err != nil {
        fmt.Println("开启事务失败")
        panic(err)
    }

	// 执行多个SQL操作
	sqlStr := "update test set id=id+100000 where password = ?"
	result, err := tx.Exec(sqlStr, "xcxcxc")
	if err != nil {
        fmt.Println("更新数据事变")
        panic(err)
    }
	id, err := result.LastInsertId()
	if err != nil {
		// 语句回滚
		err := tx.Rollback()
		fmt.Println("事务回滚")
		if err != nil {
            fmt.Println("事务回滚失败失败")
            panic(err)
        }
	}
	fmt.Printf("修改后的id为%d\n", id)
}

以上就是Go语言中database/sql的用法介绍的详细内容,更多关于Go语言 database/sql的资料请关注脚本之家其它相关文章!

相关文章

  • Go垃圾回收提升内存管理效率优化最佳实践

    Go垃圾回收提升内存管理效率优化最佳实践

    这篇文章主要为大家介绍了Go垃圾回收提升内存管理效率优化最佳实践,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-12-12
  • Go实现文件上传和下载

    Go实现文件上传和下载

    这篇文章主要为大家详细介绍了Go实现文件上传和下载,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-07-07
  • golang协程池模拟实现群发邮件功能

    golang协程池模拟实现群发邮件功能

    这篇文章主要介绍了golang协程池模拟实现群发邮件功能,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-05-05
  • Go语言Select chan用法小结

    Go语言Select chan用法小结

    select语句是Go语言中用于处理多个通道操作的关键字,它允许你在多个通道上进行非阻塞的选择操作,本文就详细介绍一下如何使用,感兴趣的可以了解一下
    2023-09-09
  • golang利用pprof与go-torch如何做性能分析

    golang利用pprof与go-torch如何做性能分析

    这篇文章主要给大家介绍了关于golang利用pprof与go-torch如何做性能分析的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-07-07
  • Golang10进制转16进制的几种方法代码示例

    Golang10进制转16进制的几种方法代码示例

    这篇文章主要给大家介绍了关于Golang10进制转16进制的几种方法,进制转换是Golang的一些基本操作,文中通过实例代码介绍的非常详细,对大家的学习或者工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-07-07
  • 详解Golang中结构体方法的高级应用

    详解Golang中结构体方法的高级应用

    本文旨在深度剖析Go中结构体方法的高级应用。我们不仅会回顾结构体方法的基本概念和用法,还将探讨如何通过高级技巧和最佳实践,希望对大家有所帮助
    2024-01-01
  • 安装GoLang环境和开发工具的图文教程

    安装GoLang环境和开发工具的图文教程

    Go是一门由Google开发的编程语言,GoLand的安装非常简单,本文主要介绍了安装GoLang环境和开发工具的图文教程,具有一定的参考价值,感兴趣的可以了解一下
    2023-09-09
  • Golang实现秒读32GB大文件示例步骤

    Golang实现秒读32GB大文件示例步骤

    这篇文章主要为大家介绍了Golang实现秒读32GB大文件的示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-12-12
  • 关于Golang标准库flag的全面讲解

    关于Golang标准库flag的全面讲解

    这篇文章主要介绍了关于Golang标准库flag的全面讲解,这个库的代码量只有1000行左右,却提供了非常完善的命令行参数解析功能,更多相关内容需要的朋友可以参考一下
    2022-09-09

最新评论