背景
前回はGO言語を使って自分のPCでWEBサーバー構築するという課題でしたが、今回の課題は、データベースを利用してGOから接続したデータを取り出して表示して、WEBサーバーで接続した結果を表示するというものでした。そこで、今回はオブジェクト指向プログラムとリレーショナルデータベースをつなぐ役割をしてくれるGORMを使用して構築していこうと思います。GORMとは、GOのORM(Object-relational mapping)のことをいいます。簡単にいうと、SQL文を書かずにデータベースを使える便利なものと考えてみてください。
#プロジェクトを作成してGOからユーザーテーブルを作成
プロジェクト名のフォルダを作成して、その中に入ります。プロジェクト名をcommunicateWithPostgresとします。
mkdir communicateWithPostgres
cd communicateWithPostgres
まずgo mod initでモジュールを初期化します。GOはモジュール形式での開発が可能になったので、GOPATHの設定などは不要です。
go mod init communicateWithPostgres
GORMのPOSTGRESQL用ライブラリ(gorm+driver/postgres)をインストール。sqlite向けのインストールコマンドをpostgres用に書き換えました。
go get -u gorm.io/gorm
go get -u gorm.io/driver/postgres
###サンプルコードはこちらを参照
package main
import (
"fmt"
"gorm.io/driver/postgres"
"gorm.io/gorm"
)
type User struct {
gorm.Model
Name string
Email string
}
func main() {
dsn := "host=localhost user=sampleuser dbname=blogapp port=xxxx sslmode=disable TimeZone=Asia/Shanghai"
db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
if err != nil {
panic("failed to connect database")
}
db.AutoMigrate(&User{})
fmt.Println("migrated")
}
GORMの関数であるAutoMigrate関数を使用し名前(Name)とEメール(Email)を持ったユーザーテーブルを作成します。頭文字が大文字のものはPublic、頭文字が小文字のものはPrivateなのでカラム(列)名を大文字にしています。下記のコマンドを入力して、ビルドして実行してみます。
go build main.go && ./main
その結果がこちらになります。
migrated
DBの中身を確認してみます。例として、私の環境では下記のコマンドでPOSTGRESQLにログインしております。(xxxxはDBのポート番号に合わせて変更して下さい。)
Applications/Postgres.app/Contents/Versions/13/bin/psql -pxxxx "blogapp"
\dt
でテーブル一覧を表示すると期待通りユーザーテーブルが作成されていました。
blogapp=# \dt
List of relations
Schema | Name | Type | Owner
--------+-------+-------+---------
public | users | table | sampleuser
(1 row)
#ユーザーを3名作成して、表示
package main
import (
"fmt"
"gorm.io/driver/postgres"
"gorm.io/gorm"
)
type User struct {
gorm.Model
Name string
Email string
}
func main() {
dsn := "host=localhost user=sampleuser dbname=blogapp port=xxxx sslmode=disable TimeZone=Asia/Shanghai"
db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
if err != nil {
panic("failed to connect database")
}
db.AutoMigrate(&User{})
fmt.Println("migrated")
var count int64
db.Model(&User{}).Count(&count)
if count == 0 {
db.Create(&User{Name: "user01", Email: "xxxxxx@xxx01.com"})
db.Create(&User{Name: "user02", Email: "xxxxxx@xxx02.com"})
db.Create(&User{Name: "user03", Email: "xxxxxx@xxx03.com"})
}
var user User
db.First(&user)
fmt.Println(user)
}
要所の説明をしていきます
var count int64 // レコードの数を入れる変数
db.Model(&User{}).Count(&count) // ユーザーのテーブルのレコード数をカウントし、結果がcount変数に入る
if count == 0 { // レコードが0の場合下記3名が作成されます
db.Create(&User{Name: "user01", Email: "xxxxxx@xxx01.com"})
db.Create(&User{Name: "user02", Email: "xxxxxx@xxx02.com"})
db.Create(&User{Name: "user03", Email: "xxxxxx@xxx03.com"})
}
POSTGRESQL上ではこの段階でcount変数が3になっています。select * from users;
のコマンドでテーブル内のレコード(行)を表示してみます。3名の名前とEメールが表示されました。再度、レコードを表示させようと試みても、count変数の値が3になっているので、テーブルの情報は更新されません。
blogapp=# select * from users;
id | created_at | updated_at | deleted_at | name | email
----+-------------------------------+-------------------------------+------------+--------+------------------
1 | 2021-03-27 16:31:58.707403+09 | 2021-03-27 16:31:58.707403+09 | | user01 | xxxxxx@xxx01.com
2 | 2021-03-27 16:31:58.709548+09 | 2021-03-27 16:31:58.709548+09 | | user02 | xxxxxx@xxx02.com
3 | 2021-03-27 16:31:58.710747+09 | 2021-03-27 16:31:58.710747+09 | | user03 | xxxxxx@xxx03.com
(3 rows)
条件に一致した最初のレコードを取得します。Where句を使用することでデータベースに保存された大量のデータの中からレコードを検索することが可能になります。
var user User
db.Where(User{Name: "user02"}).First(&user)
fmt.Println(user)
ビルドして実行してみると、migrated
とuser02が表示されました。
migrated
{{2 2021-03-27 16:31:58.709548 +0900 JST 2021-03-27 16:31:58.709548 +0900 JST {0001-01-01 00:00:00 +0000 UTC false}} user02 xxxxxx@xxx02.com}
以下の書き方もあります。カウントのエラー処理を追加しました。
package main
import (
"fmt"
"gorm.io/driver/postgres"
"gorm.io/gorm"
)
type User struct {
gorm.Model
Name string
Email string
}
func main() {
dsn := "host=localhost user=umehara dbname=blogapp port=5432 sslmode=disable TimeZone=Asia/Tokyo"
db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
if err != nil {
panic("failed to open database")
}
db.AutoMigrate(&User{})
fmt.Println("migrated")
var count int64
if err = db.Model(&User{}).Count(&count).Error; err != nil {
panic("failed to count user table")
}
fmt.Println(count)
if count == 0 {
db.Create(&User{Name: "user01", Email: "xxxxxx@xxx01.com"})
db.Create(&User{Name: "user02", Email: "xxxxxx@xxx02.com"})
db.Create(&User{Name: "user03", Email: "xxxxxx@xxx03.com"})
}
var user User
db.Where(User{Name: "user02"}).First(&user)
fmt.Println(user)
}
参考