71

golang 碎片整理之MySQL

 4 years ago
source link: https://www.tuicool.com/articles/eIFJNzb
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.

MySQL是常用的关系型数据库,本文介绍了go语言如何操作MySQL数据库。

Go操作MySQL

连接

Go语言中的database/sql 包提供了保证SQL或类SQL数据库的广泛接口,并不提供具体的数据库驱动。使用database/sql包时必须注入一个数据库驱动。

下载依赖

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

使用MySQL驱动

func Open(driverName,dataSourceName string)(*DB,error)

Open打开一个driverName 指定的数据库,dataSourceName指定数据源,一般包至少包括数据库文件名和可能的连接信息。

package main

import (
    "database/sql"
)

func main() {
    dsn := "user:password@tcp(127.0.0.1:3306)/dbname"
    db, err := sql.Open("mysql", dsn)
    if err != nil {
        panic(err)
    }
    defer db.Close()
}

初始化连接

Open函数可能只是验证其参数,而不创建与数据库的连接。如果要检查数据源的名称的合法性,应该调用返回值的ping方法。

返回的DB可以安全的被多个goroutine同时调用,并会维护自身的闲置连接池。这样一来,Open函数只需要调用一次。很少需要关闭DB.

var db *sql.DB

func initDB() (err error) {
    dsn := "user:password@tcp(127.0.0.1:3306)/test"
    db, err = sql.Open("mysql", dsn)
    if err != nil {
        return err
    }
    err = db.Ping()
    if err != nil {
        return err
    }
    return nil
}
func main() {
    err := initDB()
    if err != nil {
        fmt.Printf("init db failed,err:%v\n", err)
        return
    }
}

其中的sql.DB 是一个数据库操作句柄,代表一个具有零到读个底层连接的连接池。它可以安全的被多个goroutine 同时使用。database/sql 包会自动创建和释放连接;它也会维护一个闲置的连接池。

SetMaxOpenConns

func (db *DB) SetMaxOpenConns(n int)

SetMaxOpenConns 设置与数据库建立连接的最大数目。如果n大于0且小于最大闲置连接数,会将最大闲置连接数减小到匹配最大开启连接数的限制。如果n<=0,不会限制最大开启连接数,默认是0.

SetMaxIdleConns

func (db *DB)SetMaxIdleConns(n int)

SetMaxIdleConns设置连接池中的最大闲置连接数。如果n大于最大开启连接数,则新的最大闲置连接数会减小到匹配最大开启连接数的限制。如果n<=0,不会保留限制连接。

CRUD

建库建表

我们先在MySQL中创建一个名为sql_test的数据库。

CREATE DATABASE sql_test;

进入数据库:

use sql_test;

执行下面命令创建一张用于测试的数据表:

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;

查询

单行查询

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

func (db *DB)QueryRow(query string, args ...interface{})*Row

具体示例代码:

func queryRowDeme() {
    sqlstr := "select id ,name,age from user where id =?"
    var u user
    err := db.QueryRow(sqlstr, 1).Scan(&u.id, &u.name, &u.name)
    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)

}

多行查询

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

func (db *DB) Query(query string, args ...interface{}) (*Rows, error)

具体示例代码:

func queryMultiRowDemo() {
    sqlstr := "select id,name,age from user where id >?"
    rows, err := db.Query(sqlstr, 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)
    }
}

插入数据

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

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

Exec执行一次命令(包括查询,删除,更新,插入等),返回的Result是对已执行的SQL命令的总结。参数args表示query中的占位参数。

具体插入数据示例代码如下:

func insertRowDemo(){
    sqlstr := "insert into user(name, age) values (?,?)"
    ret,err :db.Exec(sqlstr,"张一",18)
    if err != nil{
        fmt.Printf("insert failed,err:%v\n",err)
        return
    }

    theID,err := ret.LastInsertId()
    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 Rowaffected 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)
}

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK