在Go中使用SQL数据库

在本文中,我列出了如何使用Go执行常见的SQL数据库操作。

简介database/sql

Go在其标准库中提供了干净的SQL数据库APIdatabase/sql软件包,但必须单独安装特定的数据库驱动程序。

这是一种明智的方法,因为它提供了几乎每个数据库驱动程序都实现的通用接口。

如果要使用MySQL,可以使用https://github.com/go-sql-driver/mysql

如果您使用的是PostgreSQL,请使用https://github.com/lib/pq

您只需要使用以下内容包含libimport _database/sqlAPI将配置为启用该驱动程序:

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

打开数据库连接

尽管目标是使其抽象化,但在某些方面仍然存在差异,例如在连接数据库的方式上:

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

//… db, err := sql.Open(“mysql”, “theUser:[email protected]/theDbName”) if err != nil { panic(err) }

import “database/sql”
import _ github.com/lib/pq

//… db, err := sql.Open(“postgres”, “user=theUser dbname=theDbName sslmode=verify-full”) if err != nil { panic(err) }

但是实际的大多数API都是与数据库无关的,并且可以很容易地互换(这里不谈论SQL,仅指数据库API)。

关闭数据库连接

在有意义的地方,您应该始终关闭数据库连接。

您可以照常使用defer在打开数据库连接的函数结束时将其关闭:

db, err := sql.Open("postgres", psqlInfo)
defer db.Close()

从数据库中提取数据

选择单行

查询表分两个步骤。首先你打电话db.QueryRow(),然后您致电Scan()结果。

例子:

id := 1
var col string
sqlStatement := `SELECT col FROM my_table WHERE id=$1`
row := db.QueryRow(sqlStatement, id)
err := row.Scan(&col)
if err != nil {
    if err == sql.ErrNoRows {
        fmt.Println("Zero rows found")
    } else {
        panic(err)
    }
}

db.QueryRow()用于查询表中的单个值。

签名:

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

它返回一个指向db.Row价值。

(*Row) Scan扫描行,将列值复制到传递给它的参数中。

签名:

func (r *Row) Scan(dest ...interface{}) error

如果返回了多个行,则仅扫描第一行并忽略其余部分。

如果未返回任何行,则返回一个ErrNoRows错误

var ErrNoRows = errors.New("sql: no rows in result set")

选择多行

为了查询单行,我们使用了db.QueryRow()。要查询多行,我们使用db.Query(),它返回一个*Rows价值。

从文档中:

//Rows is the result of a query. Its cursor starts before  the first row of the result set. Use Next to advance through the rows:

    rows, err := db.Query("SELECT ...")
    ...
    defer rows.Close()
    for rows.Next() {
        var id int
        var name string
        err = rows.Scan(&id, &name)
        ...
    }
     err = rows.Err() // get any error encountered ing iteration
    ...

// Err返回在迭代过程中遇到的错误(如果有)。 //可以在显式或隐式的Close之后调用Err。

我们需要迭代rows.Next(),这使我们可以致电rows.Scan()进入循环。

如果在准备下一行时发生任何错误,则循环结束,我们可以通过调用来获取错误rows.Err()

type Timeline struct {
    Id int
    Content string
}
rows, err := db.Query(`SELECT id, content FROM timeline`)
if err != nil {
    panic(err)
}
defer rows.Close()
for rows.Next() {
    timeline := Timeline{}
    err = rows.Scan(&timeline.Id, &timeline.Content)
    if err != nil {
        panic(err)
    }
    fmt.Println(timeline)
}
err = rows.Err()
if err != nil {
    panic(err)
}

更多教程: