8

golang操作MySQL数据库总结

 2 years ago
source link: https://segmentfault.com/a/1190000041081619
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

golang操作MySQL数据库总结

本文视频链接:https://www.bilibili.com/vide...

关注公众号,下载课程资料和源码:

file

准备数据库和表

下载安装MySQL

https://dev.mysql.com/downloads/mysql/

创建一个go_db数据库

create database go_db

打开数据库

use go_db

创建表

CREATE TABLE user_tbl (
  id INTEGER PRIMARY KEY AUTO_INCREMENT,
  username VARCHAR (20),
  PASSWORD VARCHAR (20)
)

添加模拟数据

INSERT INTO user_tbl (username, PASSWORD) VALUES ("tom", "123")
INSERT INTO user_tbl (username, PASSWORD) VALUES ("kite", "456")

安装配置mysql驱动

安装驱动

go get -u github.com/go-sql-driver/mysql

初始化模块

go mod init m

执行go mod tidy

go mod tidy

导入驱动

package main

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

func main() {
    
}

获得数据库连接

导入包

package main

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

获得连接

package main

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

func main() {
    db, err := sql.Open("mysql", "root:123456@/go_db")
    if err != nil {
        panic(err)
    }
    print(db)
    // 最大连接时长
    db.SetConnMaxLifetime(time.Minute * 3)
    // 最大连接数
    db.SetMaxOpenConns(10)
    // 空闲连接数
    db.SetMaxIdleConns(10)
}

初始化连接

Open函数可能只是验证其参数格式是否正确,实际上并不创建与数据库的连接。如果要检查数据源的名称是否真实有效,应该调用Ping方法。

返回的DB对象可以安全地被多个goroutine并发使用,并且维护其自己的空闲连接池。因此,Open函数应该仅被调用一次,很少需要关闭这个DB对象。

package main

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

// 定义一个全局对象db
var db *sql.DB

// 定义一个初始化数据库的函数
func initDB() (err error) {
    dsn := "root:123456@tcp(127.0.0.1:3306)/go_db?charset=utf8mb4&parseTime=True"
    // 不会校验账号密码是否正确
    // 注意!!!这里不要使用:=,我们是给全局变量赋值,然后在main函数中使用全局变量db
    db, err = sql.Open("mysql", dsn)
    if err != nil {
        return err
    }
    // 尝试与数据库建立连接(校验dsn是否正确)
    err = db.Ping()
    if err != nil {
        return err
    }
    return nil
}

func main() {
    err := initDB() // 调用输出化数据库的函数
    if err != nil {
        fmt.Printf("初始化失败!,err:%v\n", err)
        return
    }else{
        fmt.Printf("初始化成功")
    }
}

单行查询db.QueryRow()执行一次查询,并期望返回最多一行结果(即Row)。QueryRow总是返回非nil的值,直到返回值的Scan方法被调用时,才会返回被延迟的错误。

定义一个结构体

type user struct {
    id int
    username string
    password string
}

查询

// 查询一条用户数据
func queryRowDemo() {
    sqlStr := "select id, username, password from user_tbl where id=?"
    var u user
    // 确保QueryRow之后调用Scan方法,否则持有的数据库链接不会被释放
    err := db.QueryRow(sqlStr, 1).Scan(&u.id, &u.username, &u.password)
    if err != nil {
        fmt.Printf("scan failed, err:%v\n", err)
        return
    }
    fmt.Printf("id:%d name:%s age:%s\n", u.id, u.username, u.password)
}

测试

func main() {
    err := initDB() // 调用输出化数据库的函数
    if err != nil {
        fmt.Printf("初始化失败!,err:%v\n", err)
        return
    }else{
        fmt.Printf("初始化成功")
    }
    queryRowDemo()
}
初始化成功id:1 name:tom age:123

多行查询db.Query()执行一次查询,返回多行结果(即Rows),一般用于执行select命令。参数args表示query中的占位参数。

// 查询多条数据示例
func queryMultiRow() {
    sqlStr := "select id, username, password from user_tbl where id > ?"
    rows, err := db.Query(sqlStr, 0)
    if err != nil {
        fmt.Printf("query failed, err:%v\n", err)
        return
    }
    // 非常重要:关闭rows释放持有的数据库链接
    defer rows.Close()

    // 循环读取结果集中的数据
    for rows.Next() {
        var u user
        err := rows.Scan(&u.id, &u.username, &u.password)
        if err != nil {
            fmt.Printf("scan failed, err:%v\n", err)
            return
        }
        fmt.Printf("id:%d username:%s password:%s\n", u.id, u.username, u.password)
    }
}
初始化成功
id:1 username:tom password:123
id:2 username:kite password:456

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

func (db *DB) Exec(query string, args ...interface{}) (Result, error)
// 插入数据
func insertData() {
    sqlStr := "insert into user_tbl(username,password) values (?,?)"
    ret, err := db.Exec(sqlStr, "张三", "zs123")
    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 main() {
    err := initDB() // 调用输出化数据库的函数
    if err != nil {
        fmt.Printf("初始化失败!,err:%v\n", err)
        return
    }else{
        fmt.Printf("初始化成功\n")
    }
    //queryRowDemo()
    //queryMultiRow()
    insertData()
}
初始化成功
insert success, the id is 3.

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

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

删除

func delData()  {
    sql := "delete from user_tbl where id =?"
    ret, err := db.Exec(sql, "1")
    if err != nil {
        fmt.Printf("删除失败, err:%v\n", err)
        return
    }
    rows, err := ret.RowsAffected()
    if err != nil {
        fmt.Printf("删除行失败, err:%v\n", err)
        return
    }
    fmt.Printf("删除成功, 删除的行数: %d.\n", rows)
}

测试

func main() {
    err := initDB() // 调用输出化数据库的函数
    if err != nil {
        fmt.Printf("初始化失败!,err:%v\n", err)
        return
    }else{
        fmt.Printf("初始化成功\n")
    }
    delData()
}
初始化成功
删除成功, 删除的行数: 1.

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

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

更新

func updateData()  {
    sql := "update user_tbl set username=?, password=? where id=?"
    ret, err := db.Exec(sql, "kite2", "kite123", "2")
    if err != nil {
        fmt.Printf("更新失败, err:%v\n", err)
        return
    }
    rows, err := ret.RowsAffected()
    if err != nil {
        fmt.Printf("更新行失败, err:%v\n", err)
        return
    }
    fmt.Printf("更新成功, 更新的行数: %d.\n", rows)
}

测试

func main() {
    err := initDB() // 调用输出化数据库的函数
    if err != nil {
        fmt.Printf("初始化失败!,err:%v\n", err)
        return
    }else{
        fmt.Printf("初始化成功\n")
    }
    //queryRowDemo()
    //queryMultiRow()
    //insertData()
    //delData()
    updateData()
}
初始化成功
更新成功, 更新的行数: 1.

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK