Introduction
上一篇我们用 GraphQL 已经有个基本的认识
接着来模拟真实的情境搭配 Database 来使用
这篇主要都是在初始化环境
Sample Code
Setup MySQL database by Docker
https://hub.docker.com/_/mysqlPull MySQL Image from DockerHub
docker pull mysql
Create MySQL database
$ docker exec -it mysql bash$ mysql -u root -p$ CREATE DATABASE hackernews;
Models and migrations
接着我们需要利用 https://github.com/golang-migrate/migrate 这个 Package 来处理 Migrations
依照下列结构创建资料夹
go-graphql-hackernews--internal----pkg------db--------migrations----------mysql
最后所有步骤完成后的资料夹分布
依照指令初始化 migrate package
中间遇到缺少的 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.go
package databaseimport ("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.DBfunc 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)}}
改写 server.go
这段我有改写一些,教学的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))}