はじめ
案件にてGo言語を触ることになったので、かなり初歩的な内容ですがCRUD操作をしてみました。
Go言語の概要や活用方法を知りたい方はこちらをご覧ください。
ディレクトリ構成とバージョン
ディレクトリ構成
最終的なディレクトリ構成は以下になります。
.
├── README.md
├── docker-compose.yml
├── go.mod
├── go.sum
├── main.go
└── todo-app
バージョン
go 1.22.0
echo 4.11.4
gorm 1.25.7
DBの環境を作成する
まず初めに、DBの環境を作成します。今回はdockerでpostgres環境を立てていきたいと思います。
version: "3.8"
services:
db:
container_name: db_todo
image: postgres:latest
tty: true
platform: linux/x86_64
ports:
- "5432:5432"
environment:
POSTGRES_DB: go_todo # データベース名
POSTGRES_USER: test # データベースユーザー名
POSTGRES_PASSWORD: password
docker compose up --build
上記コマンドでdockerを立ち上げることで、postgresの環境が立ち上がります。
Go言語ファイルの作成 ~Hello World!~
go.modファイルの作成
go.modとは、モジュールの依存関係を管理するためのファイルで、プロジェクトのルートディレクトリ
に配置されます。
プロジェクトが依存する外部モジュールのリストとそれぞれのバージョンが記載されており、プロジェク
トのビルドが再現可能になります。
go mod init todo-app
上記コマンドを行い、go.modファイルを作成します。
Hello World!
main.goファイルを作成し、中身を下記にしてください。
package main
import (
"net/http"
"github.com/labstack/echo/v4"
)
func main() {
e := echo.New()
e.GET("/", func(c echo.Context) error {
return c.String(http.StatusOK, "Hello, World!")
})
e.Logger.Fatal(e.Start(":8989"))
}
今回、Echoフレームワークを使用していきたいと思いますので、importしていきます。
go mod tidy
この状態で、上記コマンドを実行すると、プロジェクトの全ソースコードを解析し、現在のコードベース
で実際に必要な依存関係を正確に把握します。その結果、go.mod
と go.sum
ファイルが更新され、依存関
係が整理されます。
go build
Go言語は、コンパイル型の言語のため上記コマンドで実行ファイルを作成します。
go run todo-app
上記コマンドで実行ファイルを実行し、http://localhost:8989/をブラウザで開くと「Hello, World!」
が表示されていると思います。
DBとの接続 〜gorm〜
main.goを下記に書き換えます。
package main
import (
"net/http"
"log"
"time"
"github.com/labstack/echo/v4"
"gorm.io/gorm"
"gorm.io/driver/postgres"
"gorm.io/gorm/logger"
)
type Todo struct {
gorm.Model
Content string `gorm:"not null"`
Done bool
Until time.Time
}
func main() {
connectionString := "host=localhost user=test password=password dbname=go_todo port=5432 sslmode=disable TimeZone=Asia/Tokyo"
db, err := gorm.Open(postgres.Open(connectionString), &gorm.Config{
Logger: logger.Default.LogMode(logger.Silent),
})
if err != nil {
log.Fatal("Failed to connect to database:", err)
}
err = db.AutoMigrate(&Todo{})
if err != nil {
log.Fatal("Failed to migrate database:", err)
}
e := echo.New()
e.GET("/", func(c echo.Context) error {
return c.String(http.StatusOK, "Hello, World!")
})
e.Logger.Fatal(e.Start(":8989"))
}
まず必要とされる外部パッケージ等をインポートします。
structから始まる箇所では、C言語と同様に構造体の型を定義していきます。
その後データベースの接続と初期化、テーブルの自動マイグレーションを行なっております。
こちらのファイルを実行することで、最初に作成したpostgresのデータベースにTodoテーブルが作成さ
れていると思います。
ルート作成
POST
まずは、POSTを作成し、データを作成できるようにしていきます。下記のコードをmian.goに追記して
いきます。
e.POST("/todos", func(c echo.Context) error {
var todo Todo
if err := c.Bind(&todo); err != nil {
return err
}
if result := db.Create(&todo); result.Error != nil {
return result.Error
}
return c.JSON(http.StatusCreated, todo)
})
こちらのコードを追加した後、再度build,runを行います。
その後、curlコマンドや、Postmanにてhttp://localhost:8989/todosこちらを叩いていきます。
Postmanにてbodyに加えるファイルをデータは下記に記載しておきます。
{
"Content": "新しいTodoアイテム",
"Done": false,
"Until": "2024-12-31T23:59:59Z"
}
GET
次に、下記ファイルを追記し、http://localhost:8989/todos/でGETを叩くと全データが取得でき、
http://localhost:8989/todos/1で選択したデータを取得できていると思います。
e.GET("/todos", func(c echo.Context) error {
var todos []Todo
if result := db.Find(&todos); result.Error != nil {
return result.Error
}
return c.JSON(http.StatusOK, todos)
})
e.GET("/todos/:id", func(c echo.Context) error {
id := c.Param("id")
var todo Todo
if result := db.First(&todo, id); result.Error != nil {
return result.Error
}
return c.JSON(http.StatusOK, todo)
})
PUT
こちらも下記コードを追加した後、bodyに修正したい内容を記載しhttp://localhost:8989/todos/1を
叩くと修正できるかと思います。
e.PUT("/todos/:id", func(c echo.Context) error {
id := c.Param("id")
var todo Todo
if err := c.Bind(&todo); err != nil {
return err
}
todo.ID = 0 // GORMが新しいレコードとして扱わないようにIDをリセット
if result := db.Model(&Todo{}).Where("id = ?", id).Updates(todo); result.Error != nil {
return result.Error
}
return c.JSON(http.StatusOK, todo)
})
DELETE
最後に削除のコードを追記していきます。
e.DELETE("/todos/:id", func(c echo.Context) error {
id := c.Param("id")
if result := db.Delete(&Todo{}, id); result.Error != nil {
return result.Error
}
return c.NoContent(http.StatusNoContent)
})
最終のコード
package main
import (
"net/http"
"log"
"time"
"github.com/labstack/echo/v4"
"gorm.io/gorm"
"gorm.io/driver/postgres"
"gorm.io/gorm/logger"
)
type Todo struct {
gorm.Model
Content string `gorm:"not null"`
Done bool
Until time.Time
}
func main() {
connectionString := "host=localhost user=test password=password dbname=go_todo port=5432 sslmode=disable TimeZone=Asia/Tokyo"
db, err := gorm.Open(postgres.Open(connectionString), &gorm.Config{
Logger: logger.Default.LogMode(logger.Silent),
})
if err != nil {
log.Fatal("Failed to connect to database:", err)
}
err = db.AutoMigrate(&Todo{})
if err != nil {
log.Fatal("Failed to migrate database:", err)
}
e := echo.New()
e.POST("/todos", func(c echo.Context) error {
var todo Todo
if err := c.Bind(&todo); err != nil {
return err
}
if result := db.Create(&todo); result.Error != nil {
return result.Error
}
return c.JSON(http.StatusCreated, todo)
})
e.GET("/todos", func(c echo.Context) error {
var todos []Todo
if result := db.Find(&todos); result.Error != nil {
return result.Error
}
return c.JSON(http.StatusOK, todos)
})
e.GET("/todos/:id", func(c echo.Context) error {
id := c.Param("id")
var todo Todo
if result := db.First(&todo, id); result.Error != nil {
return result.Error
}
return c.JSON(http.StatusOK, todo)
})
e.PUT("/todos/:id", func(c echo.Context) error {
id := c.Param("id")
var todo Todo
if err := c.Bind(&todo); err != nil {
return err
}
todo.ID = 0
if result := db.Model(&Todo{}).Where("id = ?", id).Updates(todo); result.Error != nil {
return result.Error
}
return c.JSON(http.StatusOK, todo)
})
e.DELETE("/todos/:id", func(c echo.Context) error {
id := c.Param("id")
if result := db.Delete(&Todo{}, id); result.Error != nil {
return result.Error
}
return c.NoContent(http.StatusNoContent)
})
e.GET("/", func(c echo.Context) error {
return c.String(http.StatusOK, "Hello, World!")
})
e.Logger.Fatal(e.Start(":8989"))
}
おわり
以上簡単な内容ですがとりあえずGo言語を触りたい方は試してみてはいかがでしょうか。