Golang中使用MySQL

GoMySQL教程展示了如何在Golang中使用MySQL。这些示例执行基本的数据库操作。

$ go version
go version go1.18.1 linux/amd64

我们使用Go版本1.18。

MySQL是领先的开源数据库管理系统。它是一个多用户、多线程的数据库管理系统。MySQL在网络上特别流行。MariaDB是MySQL关系数据库管理系统的一个社区开发的、商业支持的分支。

Go有sql包,它提供了一个围绕SQL(或类似SQL)数据库的通用接口。sql包必须与数据库驱动程序结合使用。

该包提供了自动连接池。每次我们查询数据库时,我们都在使用应用程序启动时已设置的连接池中的一个连接。连接被重用。

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

我们需要安装MySQL驱动。

USE testdb;
DROP TABLE IF EXISTS cities;
CREATE TABLE cities(id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(255), population INT);
INSERT INTO cities(name, population) VALUES('Bratislava', 432000);
INSERT INTO cities(name, population) VALUES('Budapest', 1759000);
INSERT INTO cities(name, population) VALUES('Prague', 1280000);
INSERT INTO cities(name, population) VALUES('Warsaw', 1748000);
INSERT INTO cities(name, population) VALUES('Los Angeles', 3971000);
INSERT INTO cities(name, population) VALUES('New York', 8550000);
INSERT INTO cities(name, population) VALUES('Edinburgh', 464000);
INSERT INTO cities(name, population) VALUES('Berlin', 3671000);

在本教程中,我们使用cities表。

GoMySQL版本

在第一个示例中,我们打印了MySQL的版本。

package main

import (
    "database/sql"
    "fmt"
    "log"

    _ "github.com/go-sql-driver/mysql"
)

func main() {

    db, err := sql.Open("mysql", "user7:s$cret@tcp(127.0.0.1:3306)/testdb")
    defer db.Close()

    if err != nil {
        log.Fatal(err)
    }

    var version string

    err2 := db.QueryRow("SELECT VERSION()").Scan(&version)

    if err2 != nil {
        log.Fatal(err2)
    }

    fmt.Println(version)
}

程序返回MySQL的版本。版本通过执行SELECTVERSION()语句确定。

_ "github.com/go-sql-driver/mysql"

当导入带有空白标识符前缀的包时,将调用包的init函数。该函数注册驱动程序。

db, err := sql.Open("mysql", "user7:s$cret@tcp(127.0.0.1:3306)/testdb")

使用sql.Open,我们打开一个数据库,该数据库由其数据库驱动程序名称和特定于驱动程序的数据源名称指定,通常至少包含数据库名称和连接信息。它不与数据库建立任何连接,也不验证驱动程序连接参数。相反,它只是准备数据库抽象供以后使用。到底层数据存储的第一个实际连接将在第一次需要时延迟建立。

defer db.Close()

Close将连接返回到连接池。如果sql.DB的生命周期不应超出函数范围,则延迟db.Close是惯用的.

err2 := db.QueryRow("SELECT VERSION()").Scan(&version)

QueryRow执行预计最多返回一行的查询。Scan函数将匹配行中的列复制到version变量中。

$ go run version.go
10.3.24-MariaDB-2

GoMySQL使用查询选择所有行

Query执行返回行的查询,通常是SELECT。可选参数用于查询中的任何占位符参数。

package main

import (
    "database/sql"
    "fmt"
    "log"

    _ "github.com/go-sql-driver/mysql"
)

type City struct {
    Id         int
    Name       string
    Population int
}

func main() {

    db, err := sql.Open("mysql", "user7:s$cret@tcp(127.0.0.1:3306)/testdb")
    defer db.Close()

    if err != nil {
        log.Fatal(err)
    }

    res, err := db.Query("SELECT * FROM cities")

    defer res.Close()

    if err != nil {
        log.Fatal(err)
    }

    for res.Next() {

        var city City
        err := res.Scan(&city.Id, &city.Name, &city.Population)

        if err != nil {
            log.Fatal(err)
        }

        fmt.Printf("%v\n", city)
    }
}

该示例打印cities表中的所有行。

for res.Next() {

Next准备下一个结果行以使用Scan方法读取。成功时返回true,如果没有下一个结果行或在准备结果行时发生错误,则返回false。

err := res.Scan(&city.Id, &city.Name, &city.Population)

我们将数据读入City结构Scan

$ go run select_all.go
{1 Bratislava 432000}
{2 Budapest 1759000}
{3 Prague 1280000}
{4 Warsaw 1748000}
{5 Los Angeles 3971000}
{6 New York 8550000}
{7 Edinburgh 464000}
{8 Berlin 3671000}

GoMySQLinsertrowwithExec

Exec函数执行查询而不返回任何行。它与INSERT、UPDATE、DELETE或DROP语句一起使用。可选参数用于查询中的任何占位符参数。

package main

import (
    "database/sql"
    "fmt"
    "log"

    _ "github.com/go-sql-driver/mysql"
)

func main() {

    db, err := sql.Open("mysql", "user7:s$cret@tcp(127.0.0.1:3306)/testdb")
    defer db.Close()

    if err != nil {
        log.Fatal(err)
    }

    sql := "INSERT INTO cities(name, population) VALUES ('Moscow', 12506000)"
    res, err := db.Exec(sql)

    if err != nil {
        panic(err.Error())
    }

    lastId, err := res.LastInsertId()

    if err != nil {
        log.Fatal(err)
    }

    fmt.Printf("The last inserted row id: %d\n", lastId)
}

该示例将一个新行插入到cities表中。

sql := "INSERT INTO cities(name, population) VALUES ('Moscow', 12506000)"
res, err := db.Exec(sql)

我们在表中插入一个新城市。

lastId, err := res.LastInsertId()

使用LastInsertId,我们可以获得最后插入的ID。

GoMySQL预处理语句

对于准备好的语句,我们使用占位符而不是直接将值写入语句。准备好的语句提高了数据库操作的安全性和性能。

Go在幕后为您创建准备好的语句。

db.Query(sql, param1, param2)

Query函数准备SQL,然后使用参数执行它,最后关闭语句。

package main

import (
    "database/sql"
    "fmt"
    "log"

    _ "github.com/go-sql-driver/mysql"
)

type City struct {
    Id         int
    Name       string
    Population int
}

func main() {

    db, err := sql.Open("mysql", "user7:s$cret@tcp(127.0.0.1:3306)/testdb")
    defer db.Close()

    if err != nil {
        log.Fatal(err)
    }

    var myid int = 1

    res, err := db.Query("SELECT * FROM cities WHERE id = ?", myid)
    defer res.Close()

    if err != nil {
        log.Fatal(err)
    }

    if res.Next() {

        var city City
        err := res.Scan(&city.Id, &city.Name, &city.Population)

        if err != nil {
            log.Fatal(err)
        }

        fmt.Printf("%v\n", city)
    } else {

        fmt.Println("No city found")
    }
}

该示例从数据库中选择一行。

res, err := db.Query("SELECT * FROM cities WHERE id = ?", myid)

?是一个占位符,其中填充了myid变量的值。在幕后,db.Query实际上准备、执行和关闭准备好的语句。

$ go run prepared.go
{1 Bratislava 432000}

GoMySQL受影响的行

RowsAffected返回受更新、插入或删除语句影响的行数。

package main

import (
    "database/sql"
    "fmt"
    "log"

    _ "github.com/go-sql-driver/mysql"
)

func main() {

    db, err := sql.Open("mysql", "user7:s$cret@tcp(127.0.0.1:3306)/testdb")
    defer db.Close()

    if err != nil {
        log.Fatal(err)
    }

    sql := "DELETE FROM cities WHERE id IN (2, 4, 6)"
    res, err := db.Exec(sql)

    if err != nil {
        panic(err.Error())
    }

    affectedRows, err := res.RowsAffected()

    if err != nil {
        log.Fatal(err)
    }

    fmt.Printf("The statement affected %d rows\n", affectedRows)
}

在代码示例中,我们使用DELETESQL语句删除了三行。然后我们使用RowsAffected打印删除的行数。

$ go run affected_rows.go 
The statement affected 3 rows

在本教程中,我们在Go中使用了MySQL。

列出所有Go教程。

赞(0) 打赏

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏