こんにちは、KOUKIです。
GolangのWebフレームワークであるfiberを使ってAPIを開発しています。
前回は、「is_ambassadorプロパティがtureのユーザーデータ」の取得APIを実装しました。
今回は、Product APIを追加します。
尚、この記事に出てくるソースコードは、Udemyの「React, NextJS and Golang: A Rapid Guide – Advanced」コースを参考にしています。解釈は私が勝手に付けているので、本物をみたい場合は受講をお勧めします!
<目次>
前回
事前準備
フォルダ/ファイル作成
1 2 |
touch src/models/product.go touch src/controllers/productController.go |
作るもの
Admin機能を作りたいと思います。エンドポイントは、次の通りです。
- GET/POST /api/admin/products
- GET/PUT/DELETE /api/admin/products/{product_id}
- GET /api/admin/users/{user_id}/links
- GET /api/admin/orders
- GET /api/admin/ambassadors
今回は、「/api/admin/products」「/api/admin/products/{product_id}」の処理を実装します。それぞれのエンドポイントで複数の形式(GET, POST, PUT, DELETE)を持つので、実装漏れに気をつけましょう。
Products API
Products APIは、商品の取り扱いに関するAPIになります。商品を追加、取得、更新、削除などの機能を追加していきましょう。
Product モデル
Productモデルを実装します。
1 2 3 4 5 6 7 8 9 10 |
// product.go package models type Product struct { ID uint `json:"id"` Title string `json:"title"` Description string `json:"description"` Image string `json:"image"` Price string `json:"price"` } |
マイグレーション
ProductモデルをGORMのマイグレーション対象にしましょう。
1 2 3 4 5 6 7 |
// database/db.go package database ... func AutoMigrate() { // User構造体に沿ってテーブルのスキーマーを作成する DB.AutoMigrate(models.User{}, models.Product{}) // 追加 } |
これで、dockerコンテナ起動時に、MySQL DBに対して、自動的にProductのスキーマーが作成されるようになります。
dockerコンテナを立ち上げましょう。
1 |
docker-compose up |
DBの中身を確認するとスキーマーができていることがわかります。

Products(全)ルートの追加
「/api/admin/products」のルートを追加します。
1 2 3 4 5 6 7 8 9 10 |
// routes/routes.go ... func Setup(app *fiber.App) { ... // Middleware ... adminAuthenticated.Get("products", controllers.Products) adminAuthenticated.Post("products", controllers.CreateProducts) } |
GET/POSTの2パターンあることに注意しましょう。
Products(全)コントローラーの追加
Productsコントローラーの処理を実装します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
// productController.go package controllers import ( "admin/src/database" "admin/src/models" "github.com/gofiber/fiber/v2" ) func Products(ctx *fiber.Ctx) error { var products []models.Product // 全てのプロダクトを取得 database.DB.Find(&products) return ctx.JSON(products) } func CreateProducts(ctx *fiber.Ctx) error { var product models.Product // リクエストデータをパースする if err := ctx.BodyParser(&product); err != nil { return err } // プロダクト取得 database.DB.Create(&product) return ctx.JSON(product) } |
検証
Productの追加と取得ができるようになったので、検証してみましょう。
Productの追加
- URL: http://localhost:8000/api/admin/products
- 形式: POST
1 2 3 4 5 6 |
{ "title": "Harry Potter", "description": "This book of masic world", "image": "img", "price": "100" } |

Productの取得
- URL: http://localhost:8000/api/admin/products
- 形式: GET

OKですね。
Product(個)ルートの追加
「/api/admin/products/{product_id}」へのルートを追加します。
1 2 3 4 5 6 7 8 9 10 |
// routes/routes.go ... func Setup(app *fiber.App) { ... // Middleware ... adminAuthenticated.Get("products/:id", controllers.GetProduct) adminAuthenticated.Put("products/:id", controllers.UpdateProduct) adminAuthenticated.Delete("products/:id", controllers.DeleteProduct) } |
GET/PUT/DELETEの3パターンあることに注意しましょう。
Product(個)コントローラーの追加
Productのコントローラーを実装しましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
// productController.go ... func GetProduct(ctx *fiber.Ctx) error { // リクエストからIDを取得 id, _ := strconv.Atoi(ctx.Params("id")) var product models.Product product.ID = uint(id) // プロダクト検索 database.DB.Find(&product) return ctx.JSON(product) } func UpdateProduct(ctx *fiber.Ctx) error { // リクエストからIDを取得 id, _ := strconv.Atoi(ctx.Params("id")) product := models.Product{ ID: uint(id), } if err := ctx.BodyParser(&product); err != nil { return err } // プロダクト更新 database.DB.Model(&product).Updates(&product) return ctx.JSON(product) } func DeleteProduct(ctx *fiber.Ctx) error { // リクエストからIDを取得 id, _ := strconv.Atoi(ctx.Params("id")) product := models.Product{ ID: uint(id), } // プロダクト削除 database.DB.Delete(&product) return nil } |
検証2
Product APIの検証をしましょう。
Productの取得
- URL: http://localhost:8000/api/admin/products/1
- 形式: GET

Productのアップデート
- URL: http://localhost:8000/api/admin/products/1
- 形式: PUT
1 2 3 4 5 6 |
{ "title": "Harry Potter_update", "description": "This book of masic world_update", "image": "img_update", "price": "3000" } |

Productの削除
- URL: http://localhost:8000/api/admin/products/1
- 形式: DELETE

削除されたか確認してみましょう。
- URL: http://localhost:8000/api/admin/products
- 形式: GET

OKですね。
次回
次回は、StructのEmbeddedとProductデータの作成を行います。
Go言語まとめ
ソースコード
ここまでのソースコードを以下に記載します。
product.go
1 2 3 4 5 6 7 8 9 10 |
// product.go package models type Product struct { ID uint `json:"id"` Title string `json:"title"` Description string `json:"description"` Image string `json:"image"` Price string `json:"price"` } |
productController.go
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
// productController.go package controllers import ( "admin/src/database" "admin/src/models" "strconv" "github.com/gofiber/fiber/v2" ) func Products(ctx *fiber.Ctx) error { var products []models.Product // 全てのプロダクトを取得 database.DB.Find(&products) return ctx.JSON(products) } func CreateProducts(ctx *fiber.Ctx) error { var product models.Product // リクエストデータをパースする if err := ctx.BodyParser(&product); err != nil { return err } // プロダクト取得 database.DB.Create(&product) return ctx.JSON(product) } func GetProduct(ctx *fiber.Ctx) error { // リクエストからIDを取得 id, _ := strconv.Atoi(ctx.Params("id")) var product models.Product product.ID = uint(id) // プロダクト検索 database.DB.Find(&product) return ctx.JSON(product) } func UpdateProduct(ctx *fiber.Ctx) error { // リクエストからIDを取得 id, _ := strconv.Atoi(ctx.Params("id")) product := models.Product{ ID: uint(id), } if err := ctx.BodyParser(&product); err != nil { return err } // プロダクト更新 database.DB.Model(&product).Updates(&product) return ctx.JSON(product) } func DeleteProduct(ctx *fiber.Ctx) error { // リクエストからIDを取得 id, _ := strconv.Atoi(ctx.Params("id")) product := models.Product{ ID: uint(id), } // プロダクト削除 database.DB.Delete(&product) return nil } |
routes.go
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
// routes/routes.go package routes import ( "admin/src/controllers" "admin/src/middleware" "github.com/gofiber/fiber/v2" ) func Setup(app *fiber.App) { // GROUP api := app.Group("api") admin := api.Group("admin") // No Middleware admin.Post("register", controllers.Register) admin.Post("login", controllers.Login) // Middleware adminAuthenticated := admin.Use(middleware.IsAuthenticate) adminAuthenticated.Get("user", controllers.User) adminAuthenticated.Post("logout", controllers.Logout) adminAuthenticated.Put("info", controllers.UpdateInfo) adminAuthenticated.Put("password", controllers.UpdatePassword) adminAuthenticated.Get("ambassadors", controllers.Ambassadors) adminAuthenticated.Get("products", controllers.Products) adminAuthenticated.Post("products", controllers.CreateProducts) adminAuthenticated.Get("products/:id", controllers.GetProduct) adminAuthenticated.Put("products/:id", controllers.UpdateProduct) adminAuthenticated.Delete("products/:id", controllers.DeleteProduct) } |
db.go
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
// database/db.go package database import ( "admin/src/models" "gorm.io/driver/mysql" "gorm.io/gorm" ) const ( // ユーザー:パスワード@tcp(dockerのサービス名(db):port)/db名 dsn = "admin:admin@tcp(db:3306)/ambassador?charset=utf8mb4&parseTime=True&loc=Local" ) var DB *gorm.DB func Connect() { var err error DB, err = gorm.Open(mysql.Open(dsn), &gorm.Config{}) if err != nil { panic("Could not connect with the database!") } } func AutoMigrate() { // User構造体に沿ってテーブルのスキーマーを作成する DB.AutoMigrate(models.User{}, models.Product{}) } |
コメントを残す
コメントを投稿するにはログインしてください。