開啟資料庫控制代碼

database/sql 包透過減少您管理連線的需要來簡化資料庫訪問。與許多資料訪問 API 不同,使用 database/sql 時,您無需顯式開啟連線、執行工作,然後關閉連線。相反,您的程式碼會開啟一個表示連線池的資料庫控制代碼,然後使用該控制代碼執行資料訪問操作,僅在需要釋放資源時(例如由檢索到的行或預處理語句持有的資源)才呼叫 Close 方法。

換句話說,是由 sql.DB 表示的資料庫控制代碼負責連線管理,代表您的程式碼開啟和關閉它們。當您的程式碼使用控制代碼執行資料庫操作時,這些操作可以併發訪問資料庫。有關更多資訊,請參閱管理連線

注意:您也可以保留資料庫連線。有關更多資訊,請參閱使用專用連線

除了 database/sql 包中可用的 API 外,Go 社群還為所有最常見(和許多不常見)的資料庫管理系統(DBMSes)開發了驅動程式。

開啟資料庫控制代碼時,您需要遵循以下高階步驟:

  1. 查詢驅動程式。

    驅動程式在您的 Go 程式碼和資料庫之間轉換請求和響應。有關更多資訊,請參閱查詢和匯入資料庫驅動程式

  2. 開啟資料庫控制代碼。

    匯入驅動程式後,您可以為特定資料庫開啟一個控制代碼。有關更多資訊,請參閱開啟資料庫控制代碼

  3. 確認連線。

    開啟資料庫控制代碼後,您的程式碼可以檢查連線是否可用。有關更多資訊,請參閱確認連線

您的程式碼通常不會顯式開啟或關閉資料庫連線——這由資料庫控制代碼完成。但是,您的程式碼應該釋放它在過程中獲得的資源,例如包含查詢結果的 sql.Rows。有關更多資訊,請參閱釋放資源

查詢和匯入資料庫驅動程式

您需要一個支援您正在使用的 DBMS 的資料庫驅動程式。要查詢您的資料庫的驅動程式,請參閱SQLDrivers

要使驅動程式可用於您的程式碼,您需要像匯入其他 Go 包一樣匯入它。這是一個示例:

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

請注意,如果您沒有直接從驅動程式包呼叫任何函式——例如當它被 sql 包隱式使用時——您將需要使用空白匯入,即在匯入路徑前加上下劃線:

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

注意:作為最佳實踐,避免使用資料庫驅動程式自己的 API 進行資料庫操作。相反,使用 database/sql 包中的函式。這將有助於保持您的程式碼與 DBMS 的鬆散耦合,從而在需要時更容易切換到不同的 DBMS。

開啟資料庫控制代碼

一個 sql.DB 資料庫控制代碼提供了單獨或在事務中讀寫資料庫的能力。

您可以透過呼叫 sql.Open(它接受一個連線字串)或 sql.OpenDB(它接受一個 driver.Connector)來獲取資料庫控制代碼。兩者都返回一個指向 sql.DB 的指標。

注意:請務必將您的資料庫憑據排除在 Go 原始碼之外。有關更多資訊,請參閱儲存資料庫憑據

使用連線字串開啟

當您希望使用連線字串進行連線時,請使用sql.Open 函式。字串的格式會因您使用的驅動程式而異。

這是一個 MySQL 的示例:

db, err = sql.Open("mysql", "username:password@tcp(127.0.0.1:3306)/jazzrecords")
if err != nil {
    log.Fatal(err)
}

但是,您可能會發現以更結構化的方式捕獲連線屬性會使您的程式碼更具可讀性。具體細節會因驅動程式而異。

例如,您可以用以下程式碼替換前面的示例,它使用 MySQL 驅動程式的 Config 來指定屬性,並使用其 FormatDSN 方法 來構建連線字串。

// Specify connection properties.
cfg := mysql.NewConfig()
cfg.User = username
cfg.Passwd = password
cfg.Net = "tcp"
cfg.Addr = "127.0.0.1:3306"
cfg.DBName = "jazzrecords"

// Get a database handle.
db, err = sql.Open("mysql", cfg.FormatDSN())
if err != nil {
    log.Fatal(err)
}

使用 Connector 開啟

當您希望利用連線字串中不可用的驅動程式特定連線功能時,請使用

處理錯誤

您的程式碼應該檢查嘗試建立控制代碼時(例如使用 sql.Open)是否出現錯誤。這不是連線錯誤。相反,如果 sql.Open 無法初始化控制代碼,您將收到錯誤。例如,如果它無法解析您指定的 DSN,就可能發生這種情況。

確認連線

當您開啟資料庫控制代碼時,sql 包可能不會立即建立新的資料庫連線。相反,它可能會在您的程式碼需要時建立連線。如果您不會立即使用資料庫並希望確認可以建立連線,請呼叫 PingPingContext

以下示例中的程式碼透過 ping 資料庫來確認連線。

db, err = sql.Open("mysql", connString)

// Confirm a successful connection.
if err := db.Ping(); err != nil {
    log.Fatal(err)
}

儲存資料庫憑據

避免將資料庫憑據儲存在 Go 原始碼中,這可能會將資料庫內容暴露給他人。相反,找到一種方法將它們儲存在程式碼外部但可供程式碼訪問的位置。例如,考慮一個儲存憑據並提供您的程式碼可以用來檢索憑據以向 DBMS 進行身份驗證的 API 的秘密保管應用程式。

一種流行的方法是在程式啟動之前將秘密儲存在環境中,可能從秘密管理器載入,然後您的 Go 程式可以使用 os.Getenv 讀取它們:

username := os.Getenv("DB_USER")
password := os.Getenv("DB_PASS")

這種方法還允許您自己設定環境變數以進行本地測試。

釋放資源

儘管您不使用 database/sql 包顯式管理或關閉連線,但您的程式碼應該在不再需要時釋放它已獲得的資源。這些資源可以包括由表示查詢返回資料的 sql.Rows 或表示預處理語句的 sql.Stmt 持有的資源。

通常,您透過推遲呼叫 Close 函式來關閉資源,以便在包含函式退出之前釋放資源。

以下示例中的程式碼推遲 Close 以釋放由 sql.Rows 持有的資源。

rows, err := db.Query("SELECT * FROM album WHERE artist = ?", artist)
if err != nil {
    log.Fatal(err)
}
defer rows.Close()

// Loop through returned rows.