上一篇我們用 GraphQL 已經有個基本的認識
接著來模擬真實的情境搭配 Database 來使用
這篇主要都是在初始化環境
docker pull mysql
$ docker exec -it mysql bash
$ mysql -u root -p
$ CREATE DATABASE hackernews;
接著我們需要利用 https://github.com/golang-migrate/migrate 這個 Package 來處理 Migrations
go-graphql-hackernews
--internal
----pkg
------db
--------migrations
----------mysql
最後所有步驟完成後的資料夾分佈
中間遇到缺少的 dependency 就看 console 指示用 go get
抓下來
$ go get -u github.com/go-sql-driver/mysql
$ go build -tags 'mysql' -ldflags="-X main.Version=1.0.0" -o $GOPATH/bin/migrate
$ github.com/golang-migrate/migrate/v4/cmd/migrate/
$ cd internal/pkg/db/migrations/
$ migrate create -ext sql -dir mysql -seq create_users_table
$ migrate create -ext sql -dir mysql -seq create_links_table
.sql
在 000001_create_users_table.up.sql
內新增
CREATE TABLE IF NOT EXISTS Users(
ID INT NOT NULL UNIQUE AUTO_INCREMENT,
Username VARCHAR (127) NOT NULL UNIQUE,
Password VARCHAR (127) NOT NULL,
PRIMARY KEY (ID)
)
在 000002_create_links_table.up.sql
內新增
CREATE TABLE IF NOT EXISTS Links(
ID INT NOT NULL UNIQUE AUTO_INCREMENT,
Title VARCHAR (255) ,
Address VARCHAR (255) ,
UserID INT ,
FOREIGN KEY (UserID) REFERENCES Users(ID) ,
PRIMARY KEY (ID)
)
cd
回到根目錄執行$ migrate -database mysql://root:dbpass@/hackernews -path internal/pkg/db/migrations/mysql up
internal/pkg/db/mysql
新增 mysql.gopackage database
import (
"database/sql"
_ "github.com/go-sql-driver/mysql"
"github.com/golang-migrate/migrate"
"github.com/golang-migrate/migrate/database/mysql"
_ "github.com/golang-migrate/migrate/source/file"
"log"
)
var Db *sql.DB
func InitDB() {
// Use root:dbpass@tcp(172.17.0.2)/hackernews, if you're using Windows.
db, err := sql.Open("mysql", "root:dbpass@tcp(localhost)/hackernews")
if err != nil {
log.Panic(err)
}
if err = db.Ping(); err != nil {
log.Panic(err)
}
Db = db
}
func CloseDB() error {
return Db.Close()
}
func Migrate() {
if err := Db.Ping(); err != nil {
log.Fatal(err)
}
driver, _ := mysql.WithInstance(Db, &mysql.Config{})
m, _ := migrate.NewWithDatabaseInstance(
"file://internal/pkg/db/migrations/mysql",
"mysql",
driver,
)
if err := m.Up(); err != nil && err != migrate.ErrNoChange {
log.Fatal(err)
}
}
這段我有改寫一些,教學的sample直接拿來用會報錯,改了幾個地方
mysql.go
程式碼的 package
改名為 mig
,不然會抓不到 importgo get -u github.com/go-chi/chi/v5
抓取需要初始化 HTTP router 的 packagehackernews.XXX()
前綴打錯了,改成 graph.XXX()
func main() {
port := os.Getenv("PORT")
if port == "" {
port = defaultPort
}
router := chi.NewRouter()
mig.InitDB()
defer mig.CloseDB()
mig.Migrate()
server := handler.NewDefaultServer(graph.NewExecutableSchema(graph.Config{Resolvers: &graph.Resolver{}}))
router.Handle("/", playground.Handler("GraphQL playground", "/query"))
router.Handle("/query", server)
log.Printf("connect to http://localhost:%s/ for GraphQL playground", port)
log.Fatal(http.ListenAndServe(":"+port, router))
}