Aaron Li

Blog-App: 連接 MySQL

Table of Content

目標

  1. 連接 Mysql
  2. 把 raw sql 轉換成 golang code
  3. migration

連接 MySQL

我們可以使用 database/sqlgithub.com/go-sql-driver/mysql

go-sql-driver/mysql 會自動處理好 註冊 MySQLDriver 到 database/mysql, 重連斷開的連接, pooling 等等

import (
  "database/sql"

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

func main() {
  dbSource := "username:password@tcp(url:port)/db"
  db, err := sql.Open("mysql", dbSource)
  if err != nil {
    log.Fatal(err.Error())
  }
  ...
}

migration

我們將使用 golang-migrate 去實現 db 的 migration

How to use ?

  1. download golang-migrate
brew install golang-migrate
  1. 新增一個 migration
migrate create -ext sql -dir {{generated migration file location}} -seq {{migration name}}

我們可以在 Makefile 加上這段, 這樣我們需要新增新的 migration 時只需要簡單的 make new_migrate 後輸入 migration 的名字後即可

new_migrate:
	@read -p "Enter migration name: " name; \
		migrate create -ext sql -dir pkg/db/migration -seq $$name

我們輸入 create_user 後可以發現多了 migrate down 和 up 的 file 用來定義兩者分別要進行的動作

.
└── pkg
    └── db
        └── migration
            ├── 000001_create_user.down.sql
            └── 000001_create_user.up.sql
# 000001_create_user.down.sql
DROP TABLE IF EXISTS users;

# 000001_create_user.up.sql
CREATE TABLE `users` (
  `id` BIGINT AUTO_INCREMENT PRIMARY KEY,
  `username` varchar(255) NOT NULL,
  `email` varchar(255) UNIQUE NOT NULL,
  `password` varchar(255) UNIQUE NOT NULL,
  `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  `updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX `users_index_on_email_password` ON `users` (`email`, `password`);
  1. 如何 migrate up/down ? 我們一樣可以把 migtate up/down 的動作定義在 Makefile 裡, 這樣我們只需要執行 make migrateup/migratedown 就可以完成動作了
migrateup:
	migrate -path pkg/db/migration/ -database {{mysql address}} -verbose up

migratedown:
	migrate -path pkg/db/migration/ -database {{mysql address}} -verbose down 1

sqlc

sqlc generates fully type-safe idiomatic Go code from SQL

DOC

sqlc 可以直接將 raw sql 轉換成 golang code. 可以生成 model struct, querier interface 等等

How to use ?

  1. download sqlc
# for mac
brew install sqlc

# for ubuntu
sudo snap install sqlc

# go install (require Go 1.21+)
go install github.com/sqlc-dev/sqlc/cmd/sqlc@latest
  1. configuration
# 定義好是哪個版本的 sqlc configuration
version: "2" 
sql:
  # 我們將使用 mysql
  - engine: "mysql" 
    # 會讀取哪裡去生成 schema, sqlc 會忽略 .down sql 所以可以直接指向我們之前放 migration 的 dir
    schema: "./pkg/db/migration/"
    # 會讀取哪裡取得我們支援的 query
    queries: "./pkg/db/query/"
    gen:
      go:
        # package 名稱
        package: "sqlc"
        # 生成的 code 的位置
        out: "./pkg/db/sqlc"
        # addition 的 configuration 可依照需求修改
        emit_json_tags: true
        emit_prepared_queries: false
        emit_interface: true
        emit_exact_table_names: false
        emit_empty_slices: true