本文將介紹如何使用 GORM 和 OceanBase 資料庫構建一個應用程式,實現建立表、插入資料和查詢資料等基本操作。
前提條件
安裝 OceanBase 資料庫、 Go 語言和相關驅動 ,並確保已經正確配置了環境變數。
本文檔編寫代碼使用的工具是 IntelliJ IDEA 2021.3.2 (Community Edition) 版本,您也可以根據個人喜好選擇適合自己的工具查看範例程式碼。
安裝 OceanBase 資料庫
安裝 Go 語言
安裝 Go-SQL-Driver/MySQL 驅動
操作步驟
本文中給出的操作步驟是在 Windows 環境下產生的。如果您使用的是其他動作系統內容或編譯器,那麼操作步驟可能會略有不同。
(可選)安裝 Go 語言和驅動。
擷取 OceanBase 資料庫連接資訊。
修改
gorm-oceanbase專案中的資料庫連接資訊。運行
gorm-oceanbase專案。
步驟一:(可選)安裝 Go 語言和驅動
若您已經安裝了 Go 語言和 Go-SQL-Driver/MySQL 驅動,可以直接跳過此步驟。若您未安裝,可根據以下步驟進行安裝。
安裝 Go 語言
下載 Go 語言安裝包:可以從Go 官網下載適合自己作業系統的安裝包。
說明本文檔使用的 Go 安裝包名為 go1.20.6.windows-amd64.msi。
安裝 Go 語言:雙擊下載的安裝包,按照提示進行安裝。
配置環境變數:將 Go 語言的安裝路徑添加到系統的 PATH 環境變數中。
在 Windows 環境中,可以在控制台 > 系統和安全 > 系統 > 進階系統設定 > 環境變數 > 系統變數中增加 Path 的值為
C:\usr\local\go\bin。在 Linux 或 macOS 環境中,可以編輯
~/.bashrc或~/.bash_profile檔案,在其中添加以下內容:export PATH=$PATH:/usr/local/go/bin
說明\usr\local\go\bin為預設安裝目錄,若在安裝 Go 語言時修改了安裝目錄,請替換為對應的目錄。驗證安裝:在 Shell 命令列中輸入以下命令,查看 Go 語言的版本資訊,以驗證安裝是否成功:
C:\Users\admin\> go version go version go1.20.6 windows/amd64
安裝 Go-SQL-Driver/MySQL 驅動
根據 Go 語言的不同版本,可以選擇不同的安裝方式,安裝 Go-SQL-Driver/MySQL 驅動時需要進入到對應的專案目錄下開啟命令列終端。關於
Go-SQL-Driver/MySQL的詳細資料,您可參考 Github。安裝命令如下:
C:\Users\admin\Desktop\go-oceanbase>go get -u github.com/go-sql-driver/mysql go: downloading github.com/go-sql-driver/mysql v1.7.1 go: added github.com/go-sql-driver/mysql v1.7.1如果由於版本或網路的原因,無法通過
go get命令安裝時,可通過go install命令進行go-sql-driver/mysql安裝。在
go/src目錄複製 github 中的go-sql-driver/mysql倉庫。cd /usr/local/go/src git clone https://github.com/go-sql-driver/mysql.git重要/usr/local/go/src需要替換成 Go 實際安裝目錄操作。通過
go install進行安裝。go install mysql重要部分版本
go install的預設執行目錄可能不是/src,可以通過go install執行後的報錯判斷實際目錄。例如,報錯cannot find package "mysql" in: /usr/local/go/src/vendor/mysql,則應該將 mysql 檔案夾放在/src/vendor目錄下再執行安裝命令。檢查 Go-SQL-Driver/MySQL 驅動是否已經安裝,若安裝失敗,請按照報錯資訊進行修改。
go list -m github.com/go-sql-driver/mysql
步驟二:擷取 OceanBase 資料庫連接資訊
聯絡 OceanBase 資料庫部署人員或者管理員擷取相應的資料庫連接資訊。
obclient -h{host} -u{user_name} -p****** -P{port} -D{schema_name}資料庫連接串包含了訪問資料庫所需的參數資訊,可通過資料庫連接串驗證登入資料庫,保證串連串參數資訊正確。
在test.go檔案中需要這裡的 URL 資訊。
參數說明:
host:OceanBase 資料庫連接的網域名稱。user_name:租戶的串連帳號。password:提供賬戶密碼。port:OceanBase 資料庫連接連接埠,MySQL 模式租戶預設是 3306。schema_name:需要訪問的 Schema 名稱。
步驟三: 修改gorm-oceanbase專案中的資料庫連接資訊
根據步驟二:擷取 OceanBase 資料庫連接資訊中的資訊修改test.go檔案中的資料庫連接資訊。選中test.go檔案,按右鍵選擇開啟檔案,可通過記事本或其他編輯軟體開啟。

樣本如下:
OBServer 節點的 IP 位址為
xxx.xxx.xxx.xxx。訪問連接埠使用的是 3306。
需要訪問的 Schema 名稱為
test。租戶的串連賬戶是
root。密碼是
******。
範例程式碼如下:
dsn := "root:******@tcp(xxx.xxx.xxx.xxx:3306)/test?charset=utf8mb4&parseTime=True&loc=Local"步驟四:運行go-oceanbase專案
代碼編輯完成後,在專案目錄下開啟命令列終端,通過go run直接運行 Go 檔案運行如下命令運行:
PS D:\demo\go-demo\gorm-oceanbase> go run test.go(可選)在 Linux 或 macOS 環境中需要配置臨時環境變數後,才能運行go run。
export PATH=$PATH:/usr/local/go/bin
go run test.go運行後返回如下內容,說明資料庫連接成功,樣本語句正確執行:
PS D:\demo\go-demo\gorm-oceanbase> go run test.go
1
<nil>
1
{1 OceanBase 12 2022-06-01 08:00:00 +0800 CST}
<nil>
1
{1 ob 13 2023-06-01 00:00:00 +0000 UTC}
<nil>
1
1
<nil>
1
time="2023-08-09T15:55:46+08:00" level=debug msg=DropTable duration=589.2031ms
2023/08/09 15:55:47 D:/demo/go-demo/gorm-oceanbase/test.go:85 SLOW SQL >= 200ms
[336.194ms] [rows:0] DROP TABLE IF EXISTS `users` CASCADE專案代碼介紹
點擊 gorm-oceanbase 下載專案代碼,是一個名稱為gorm-oceanbase的壓縮包。 解壓後,得到一個名為gorm-oceanbase的檔案夾。目錄結構如下所示:
|-- go.mod
|-- go.sum
|-- test.go檔案說明:
go.mod:Go 語言模組檔案,用於定義專案的模組依賴關係和版本資訊。go.sum:Go V1.11 及以上版本中新增的模組管理檔案,用於記錄專案依賴的模組及其版本資訊,以及對應的校正和(Checksum)。test.go: Go 原始碼檔案,其中包含專案的範例程式碼。
go.mod 代碼介紹
go.mod檔案用於定義專案的模組名稱、Go 版本號碼以及依賴項相關聲明。
go.mod檔案包含以下內容:
module gorm-oceanbase:這是專案的模組名稱,它定義了專案的命名空間。在 Go 1.16 及更高版本中,模組名稱必須與專案的根目錄名稱匹配。go 1.20:這是專案所需的 Go 版本。require:這是專案的依賴項聲明。它指定了列出了專案所依賴的第三方庫及其版本資訊。該依賴項是間接依賴項,與另一個依賴項go.sum相關聯。github.com/go-sql-driver/mysql:Go-SQL-Driver/MySQL 驅動,用於串連和操作 MySQL 資料庫。github.com/jinzhu/inflection:字串轉換庫,用於將字串轉換為單數形式、複數形式、駝峰形式等。github.com/jinzhu/now:時間處理庫,用於擷取目前時間、計算時間差、格式化時間等。github.com/sirupsen/logrus:日誌庫,用於記錄程式運行時的日誌資訊。golang.org/x/sys:系統庫,提供了一些系統層級的操作函數和常量。golang.org/x/text:文本處理庫,用於處理 Unicode 字串、格式化數字等。gorm.io/driver/mysql:GORM 的 MySQL 驅動,用於在 GORM 中串連和操作 MySQL 資料庫。gorm.io/gorm:GORM ORM 架構,用於簡化資料庫操作。
代碼如下:
module gorm-oceanbase
go 1.20
require (
github.com/go-sql-driver/mysql v1.7.1 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
golang.org/x/sys v0.5.0 // indirect
golang.org/x/text v0.12.0 // indirect
gorm.io/driver/mysql v1.5.1 // indirect
gorm.io/gorm v1.25.2 // indirect
)go.sum 代碼介紹
go.sum檔案用於定義專案的依賴項資訊,每個依賴項都由三部分組成,分別是庫的名稱、版本號碼和雜湊值。
go.sum檔案包含以下內容:
github.com/sirupsen/logrus:日誌庫,用於記錄程式運行時的日誌資訊。golang.org/x/text:文本處理庫,用於處理 Unicode 字串、格式化數字等。gorm.io/driver/mysql:GORM 的 MySQL 驅動,用於在 GORM 中串連和操作 MySQL 資料庫。gorm.io/gorm:GORM ORM 架構,用於簡化資料庫操作。
go.sum檔案根據運行環境的不同所需要的依賴不同,請根據執行提示下載您所需的依賴項。
代碼如下:
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc=
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
gorm.io/driver/mysql v1.5.1 h1:WUEH5VF9obL/lTtzjmML/5e6VfFR/788coz2uaVCAZw=
gorm.io/driver/mysql v1.5.1/go.mod h1:Jo3Xu7mMhCyj8dlrb3WoCaRd1FhsVh+yMXb1jUInf5o=
gorm.io/gorm v1.25.2 h1:gs1o6Vsa+oVKG/a9ElL3XgyGfghFfkKA2SInQaCyMho=
gorm.io/gorm v1.25.2/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=test.go 代碼介紹
test.go檔案定義了如何使用 Go-SQL-Driver/MySQL 驅動來串連 MySQL 資料庫,並使用 GORM 提供的 API 進行資料庫操作。test.go檔案包含以下內容:
定義
main包。package main表示這是一個可執行程式的包,這個包包含了一個main()函數,這個函數會在程式運行時被執行。定義
import包。import語句匯入了以下幾個包:fmt:用於提供格式化輸入和輸出的函數。它定義了一組函數,用於將資料格式化為字串並輸出到控制台或其他裝置。time:用於提供了一些時間相關的函數和類型。os:用於提供了一些作業系統相關的函數和類型。gorm.io/driver/mysql:MySQL 資料庫驅動,用於串連和操作 MySQL 資料庫。gorm.io/gorm:用於將 Go 語言的結構體映射到資料庫表中,並提供了一些查詢和操作資料庫的方法。golang.org/x/text/transform:用於提供了一些文本處理的基礎功能,如字元集轉換、Unicode 處理等。github.com/sirupsen/logrus:用於提供了一些日誌輸出和格式化的功能。
代碼如下:
import ( "fmt" "time" "os" "gorm.io/driver/mysql" "gorm.io/gorm" "golang.org/x/text/transform" "github.com/sirupsen/logrus" )定義
User結構體。定義了一個名為
User的結構體,用於表示一個使用者的基本資料,它包含了四個欄位:使用者的唯一識別碼ID,使用者的姓名Name, 使用者的年齡Age, 使用者的生日Birthday。代碼如下:
type User struct { ID int Name string Age int Birthday time.Time }定義
transformString函數。 定義一個名為transformString的函數,用於將一個字串轉換為指定的編碼格式。它接受兩個參數:str和encoder,函數通過調用transform.String函數將字串轉換為指定的編碼格式,如果轉換過程中出現錯誤,則返回原始字串。最後,函數返迴轉換後的字串或原始字串。代碼如下:
func transformString(str string, encoder transform.Transformer) string { result, _, err := transform.String(encoder, str) if err != nil { return str } return result }定義
main函數。通過調用
main函數,對建立的使用者資訊進行了增刪改查的操作,並使用了logrus輸出相應的調試日誌到控制台。初始化
logrus。使用
logrus包對日誌輸出進行初始化,設定日誌輸出格式為文字格式設定,記錄層級為Debug層級,並輸出到標準輸出資料流中。代碼如下:
logrus.SetFormatter(&logrus.TextFormatter{}) logrus.SetLevel(logrus.DebugLevel) logrus.SetOutput(os.Stdout)串連資料庫。
定義名為
dsn的字串變數,它包含了串連 MySQL 資料庫所需的資訊,包括使用者名稱、密碼、主機地址、連接埠號碼、資料庫名稱、字元集等。調用gorm.Open函數串連 MySQL 資料庫,傳入dsn變數和一個gorm.Config類型的參數,並返回一個連線物件。如果串連出現錯誤,則輸出錯誤資訊並退出程式。代碼如下:
dsn := "user_name:******@tcp(host:port)/schema_name?charset=utf8mb4&parseTime=True&loc=Local" db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{}) if err != nil { fmt.Println(err.Error()) return }資料庫操作。
使用
gorm.DB對象進行資料庫操作,包括自動遷移、插入資料、查詢資料、更新資料和刪除資料等操作。具體過程如下:調用
db.AutoMigrate函數,自動遷移User結構體對應的表,如果表不存在則建立表。使用defer關鍵字和db.Migrator().DropTable函數,延遲刪除users表,即在程式結束時刪除表。建立一個名為
user的User結構體執行個體,並將其插入到資料庫中。查詢 ID 為 1 的使用者,並輸出查詢結果。
更新 ID 為 1 的使用者的資訊,並將其儲存到資料庫中。
刪除 ID 為 1 的使用者,並輸出刪除結果。
代碼如下:
db.AutoMigrate(&User{}) defer db.Migrator().DropTable("users") // 記錄開始時間 start := time.Now() // 建立一個名為 user 的 User 結構體執行個體,並將其插入到資料庫中。 user := User{Name: "OceanBase", Age: 12, Birthday: time.Date(2022, 06, 01, 00, 00, 00, 00, time.UTC)} result := db.Create(&user) fmt.Println(user.ID) fmt.Println(result.Error) fmt.Println(result.RowsAffected) // 查詢 ID 為 1 的使用者,並輸出查詢結果。 user = User{ID: 1} result = db.First(&user) fmt.Println(user) fmt.Println(result.Error) fmt.Println(result.RowsAffected) // 更新 ID 為 1 的使用者的資訊,並將其儲存到資料庫中。 user = User{ID: 1, Name: "ob", Age: 13, Birthday: time.Date(2023, 06, 01, 00, 00, 00, 00, time.UTC)} result = db.Save(&user) fmt.Println(user) fmt.Println(result.Error) fmt.Println(result.RowsAffected) // 刪除 ID 為 1 的使用者,並輸出刪除結果。 user = User{ID: 1} result = db.Delete(&user) fmt.Println(user.ID) fmt.Println(result.Error) fmt.Println(result.RowsAffected)
輸出日誌。
調用
time.SinceFunction Compute程式已耗用時間,調用logrus.WithFields函數建立帶有欄位的日誌記錄器,調用Debug函數輸出日誌資訊。代碼如下:
logrus.WithFields(logrus.Fields{ "duration": time.Since(start), }).Debug("DropTable")
完整的代碼展示
go.mod
module gorm-oceanbase
go 1.20
require (
github.com/go-sql-driver/mysql v1.7.1 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
golang.org/x/sys v0.5.0 // indirect
golang.org/x/text v0.12.0 // indirect
gorm.io/driver/mysql v1.5.1 // indirect
gorm.io/gorm v1.25.2 // indirect
)go.sum
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc=
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
gorm.io/driver/mysql v1.5.1 h1:WUEH5VF9obL/lTtzjmML/5e6VfFR/788coz2uaVCAZw=
gorm.io/driver/mysql v1.5.1/go.mod h1:Jo3Xu7mMhCyj8dlrb3WoCaRd1FhsVh+yMXb1jUInf5o=
gorm.io/gorm v1.25.2 h1:gs1o6Vsa+oVKG/a9ElL3XgyGfghFfkKA2SInQaCyMho=
gorm.io/gorm v1.25.2/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
test.go
package main
import (
"fmt"
"time"
"os"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"golang.org/x/text/transform"
"github.com/sirupsen/logrus"
)
type User struct {
ID int
Name string
Age int
Birthday time.Time
}
// 將字串轉換為指定的編碼格式
func transformString(str string, encoder transform.Transformer) string {
result, _, err := transform.String(encoder, str)
if err != nil {
return str
}
return result
}
func main() {
// 初始化 logrus
logrus.SetFormatter(&logrus.TextFormatter{})
logrus.SetLevel(logrus.DebugLevel)
logrus.SetOutput(os.Stdout)
dsn := "user_name:******@tcp(host:port)/schema_name?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
fmt.Println(err.Error())
return
}
db.AutoMigrate(&User{})
defer db.Migrator().DropTable("users")
// 記錄開始時間
start := time.Now()
user := User{Name: "OceanBase", Age: 12, Birthday: time.Date(2022, 06, 01, 00, 00, 00, 00, time.UTC)}
result := db.Create(&user)
fmt.Println(user.ID)
fmt.Println(result.Error)
fmt.Println(result.RowsAffected)
user = User{ID: 1}
result = db.First(&user)
fmt.Println(user)
fmt.Println(result.Error)
fmt.Println(result.RowsAffected)
user = User{ID: 1, Name: "ob", Age: 13, Birthday: time.Date(2023, 06, 01, 00, 00, 00, 00, time.UTC)}
result = db.Save(&user)
fmt.Println(user)
fmt.Println(result.Error)
fmt.Println(result.RowsAffected)
user = User{ID: 1}
result = db.Delete(&user)
fmt.Println(user.ID)
fmt.Println(result.Error)
fmt.Println(result.RowsAffected)
// 輸出日誌
logrus.WithFields(logrus.Fields{
"duration": time.Since(start),
}).Debug("DropTable")
}相關文檔
有關 Go-SQL-Driver/MySQL 的內容在 OceanBase 資料庫開源社區中也有更多資訊,詳情請參考 Go-SQL-Driver/MySQL。
