go操作数据库(原生版)

Posted issue是fw

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了go操作数据库(原生版)相关的知识,希望对你有一定的参考价值。

目录

连接数据库

package main

import (
	"database/sql"
	"fmt"
	_ "github.com/go-sql-driver/mysql"
)
var db *sql.DB
func initMySql() (err error)   //初始化数据库函数
	dsn := "root:123456@tcp(127.0.0.1:3306)/test" //用户名:密码@连接方式(ip地址)/数据库名
	db, err = sql.Open("mysql", dsn)
	if err != nil 
		panic(err)
	

	err = db.Ping()
	if err != nil
		return err
	
	return nil

func main() 
	if err := initMySql(); err!=nil
		fmt.Printf("连接数据库失败")
	
	defer db.Close()
	fmt.Printf("连接数据库成功")

创建表

CREATE TABLE `user` (
    `id` BIGINT(20) NOT NULL AUTO_INCREMENT,
    `name` VARCHAR(20) DEFAULT '',
    `age` INT(11) DEFAULT '0',
    PRIMARY KEY(`id`)
)ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;

查询

查询单条数据

type user struct
	id int
	age int
	name string

// 查询单条数据示例
func queryRowDemo() 
	sqlStr := "select id, name, age from user where id=?"
	var u user
	// 非常重要:确保QueryRow之后调用Scan方法,否则持有的数据库链接不会被释放
	err := db.QueryRow(sqlStr, 1).Scan(&u.id, &u.name, &u.age)  //将数据库中的字段按顺序绑定上去
	if err != nil 
		fmt.Printf("scan failed, err:%v\\n", err)
		return
	
	fmt.Printf("id:%d name:%s age:%d\\n", u.id, u.name, u.age)

需要注意的是Scan方法把数据库的字段一一绑定到结构体上(结构体的字段名不需要和数据库中完全一致)

err := db.QueryRow(sqlStr, 1).Scan(&u.id, &u.name, &u.age)  //这里把&u.id和&u.age交换一下也不会报错

查询多行数据

使用函数Query

type user struct
	id int
	age int
	name string

// 查询单条数据示例
func queryRowDemo() 
	sqlStr := "select id, name, age from user where id!=?"
	var u user
	// 非常重要:确保QueryRow之后调用Scan方法,否则持有的数据库链接不会被释放
	rows,err := db.Query(sqlStr, -1)
	if err != nil 
		fmt.Printf("scan failed, err:%v\\n", err)
		return
	
	defer rows.Close()
	for rows.Next()
		err := rows.Scan(&u.id,&u.name,&u.age)
		if err!=nil
			fmt.Printf("Scan fail,err: %v\\n",err )
			return
		
		fmt.Printf("id:%d name:%s age:%d\\n", u.id, u.name, u.age)
	

增删改

插入、更新和删除操作都使用Exec方法。

func (db *DB) Exec(query string, args ...interface) (Result, error)

Exec执行一次命令(包括查询、删除、更新、插入等)

返回的Result是对已执行的SQL命令的总结。参数args表示query中的占位参数。

增加(插入)

// 插入数据
func insertRowDemo() 
	sqlStr := "insert into user(name, age) values (?,?)"
	ret, err := db.Exec(sqlStr, "小由纪同学", 17)
	if err != nil 
		fmt.Printf("insert failed, err:%v\\n", err)
		return
	
	theID, err := ret.LastInsertId() // 新插入数据的id
	if err != nil 
		fmt.Printf("get lastinsert ID failed, err:%v\\n", err)
		return
	
	fmt.Printf("insert success, the id is %d.\\n", theID)

更新

// 更新数据
func updateRowDemo() 
	sqlStr := "update user set age=? where id = ?"
	ret, err := db.Exec(sqlStr, 39, 3)
	if err != nil 
		fmt.Printf("update failed, err:%v\\n", err)
		return
	
	n, err := ret.RowsAffected() // 操作影响的行数
	if err != nil 
		fmt.Printf("get RowsAffected failed, err:%v\\n", err)
		return
	
	fmt.Printf("update success, affected rows:%d\\n", n)

删除

// 删除数据
func deleteRowDemo() 
	sqlStr := "delete from user where id = ?"
	ret, err := db.Exec(sqlStr, 3)
	if err != nil 
		fmt.Printf("delete failed, err:%v\\n", err)
		return
	
	n, err := ret.RowsAffected() // 操作影响的行数
	if err != nil 
		fmt.Printf("get RowsAffected failed, err:%v\\n", err)
		return
	
	fmt.Printf("delete success, affected rows:%d\\n", n)

Go实现MySQL预处理

预处理的好处

1.优化MySQL服务器重复执行SQL的方法,可以提升服务器性能.

提前让服务器编译,一次编译多次执行,节省后续编译的成本

2.避免SQL注入问题。

查询预处理示例

// 预处理查询示例
func prepareQueryDemo() 
	sqlStr := "select id, name, age from user where id > ?"
	stmt, err := db.Prepare(sqlStr)  //获得stmt对象,后续只需要不断替换参数就可以执行不同的sql
	if err != nil 
		fmt.Printf("prepare failed, err:%v\\n", err)
		return
	
	defer stmt.Close()
	rows, err := stmt.Query(0)
	if err != nil 
		fmt.Printf("query failed, err:%v\\n", err)
		return
	
	defer rows.Close()
	// 循环读取结果集中的数据
	for rows.Next() 
		var u user
		err := rows.Scan(&u.id, &u.name, &u.age)
		if err != nil 
			fmt.Printf("scan failed, err:%v\\n", err)
			return
		
		fmt.Printf("id:%d name:%s age:%d\\n", u.id, u.name, u.age)
	

以上是关于go操作数据库(原生版)的主要内容,如果未能解决你的问题,请参考以下文章

go操作数据库(原生版)

go操作数据库(原生版)

ExtJs 4:如何在一个请求中发送所有修改、新和删除的记录?

云原生版java与Go的大比拼 | Gopher Daily (2020.10.25) ʕ◔ϖ◔ʔ

Dubbo-go 发布 1.5 版,朝云原生迈出关键一步

Go语言增强版操作Mysql(Sqlx)