🔖
Gin & GormでPOST/GETできるようにする
概要
先日バックエンドとしてインターンに参加したのですが、急遽バックエンドはSupabaseに変更となり、バックエンドを触る機会が無くなってしまいました。せっかくバックエンド挑戦したのに書き方忘れたくない!ということで思い出そうと思ってPOST/GETできるAPIを実装してみたのでまとめます。
構成
- Gin: GoのWebフレームワーク。現状最速らしい。。?
- Gorm: GoのORMライブラリ。データベースをオブジェクトで扱うやつ。
- PostgreSQL: 今後render.comにデプロイすることを見据えてポスグレをチョイス
早速コード書きます。
今回の目標は「POST/GETが動作すること」、「データベースと接続すること」なのでアーキテクチャは一旦無視。main.goに処理を全て書くことにしました。
データベース接続のための環境変数を.env
に書きます。
DB_USER=tetsuro
DB_PASSWORD=postgres
DB_HOST=localhost
DB_PORT=5432
DB_NAME=bulletin
ここからmain.goに書いていきます。
まずはTODOアプリのモデルを構造体を定義します。
type Todo struct {
// KEY - 型 - json内の定義
ID string `json:"id"`
Title string `json:"title"`
}
ここからmain関数
です。
データベース接続のため環境変数を読み込みます。
err := godotenv.Load()
if err != nil {
log.Fatal("Error loading .env file")
}
user := os.Getenv("DB_USER")
password := os.Getenv("DB_PASSWORD")
host := os.Getenv("DB_HOST")
port := os.Getenv("DB_PORT")
dbName := os.Getenv("DB_NAME")
データベースの接続を行います。
dsn := "host=" + host + " user=" + user + " password=" + password + " dbname=" + dbName + " port=" + port + " sslmode=disable TimeZone=Asia/Tokyo"
db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
if err != nil {
panic("failed to connect database")
}
db.AutoMigrate(&Todo{})
db.AutoMigrate(&Todo{})
と書くことで構造体に合わせてマイグレーションしてくれるようです。
次にrouter
を定義しリクエストごとの処理を書きます。
router := gin.Default() //routerを定義
router.GET("/ping", func(c *gin.Context) { //接続テスト用
c.JSON(200, gin.H{
"message": "pong",
})
})
router.GET("/todos", func(c *gin.Context) { //TODO取得
var todos []Todo
db.Find(&todos)
c.JSON(200, todos)
})
router.POST("/todos", func(c *gin.Context) { //TODO追加
var todo Todo
c.BindJSON(&todo)
db.Create(&todo)
c.JSON(200, todo)
})
router.Run() //これでAPIサーバーを起動。引数なしの場合は自動でportが決まる。
コード全体はこのようになります。
main.go
package main
import (
"log"
"os"
"github.com/gin-gonic/gin"
"github.com/joho/godotenv"
"gorm.io/driver/postgres"
"gorm.io/gorm"
)
type Todo struct {
ID string `json:"id"`
Title string `json:"title"`
}
func main() {
err := godotenv.Load()
if err != nil {
log.Fatal("Error loading .env file")
}
user := os.Getenv("DB_USER")
password := os.Getenv("DB_PASSWORD")
host := os.Getenv("DB_HOST")
port := os.Getenv("DB_PORT")
dbName := os.Getenv("DB_NAME")
dsn := "host=" + host + " user=" + user + " password=" + password + " dbname=" + dbName + " port=" + port + " sslmode=disable TimeZone=Asia/Tokyo"
db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
if err != nil {
panic("failed to connect database")
}
db.AutoMigrate(&Todo{})
router := gin.Default()
router.GET("/ping", func(c *gin.Context) {
c.JSON(200, gin.H{
"message": "pong",
})
})
router.GET("/todos", func(c *gin.Context) {
var todos []Todo
db.Find(&todos)
c.JSON(200, todos)
})
router.POST("/todos", func(c *gin.Context) {
var todo Todo
c.BindJSON(&todo)
db.Create(&todo)
c.JSON(200, todo)
})
router.Run()
}
CURLコマンドでテスト
go run main.go
でローカルでサーバーを立てます。
次にCURLコマンドでテストしてみます。
メッセージを確認するコマンド
curl http://localhost:8080/ping -X GET
TODOを追加するコマンド
curl curl --json '{"id": "3", "title": "MYTASK"}' http://localhost:8080/todos
TODOを取得するコマンド
curl http://localhost:8080/todos -X GET
もし上手く行かなければポートを確認するなどしてみてください。
感想
データベース接続に結構時間がかかりました。
アーキテクチャを気にせずPOST/GETする程度なら案外簡単に実装できますね。
今度はアーキテクチャを意識して書こうと思います。
Discussion