0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

gofiber を使用した API 開発

Posted at

gofiber とは

Fiber is an Express inspired web framework built on top of Fasthttp, the fastest HTTP engine for Go. Designed to ease things up for fast development with zero memory allocation and performance in mind.

gofiber は Go のための Web フレームワークです。
Node.js のための Web フレームワークである express にインスパイアされているようです。

Installation

Installation に従い gofiber をインストールします。

go get github.com/gofiber/fiber/v2

Server の起動

main.go
package main

import (
	"github.com/gofiber/fiber/v2"
)

func main() {
	app := fiber.New()

	if err := app.Listen(":3000"); err != nil {
		println(err.Error())
	}
}
go run ./main.go 

起動が成功すると以下のログが表示されます。

 ┌───────────────────────────────────────────────────┐ 
 │                   Fiber v2.52.5                   │ 
 │               http://127.0.0.1:3000               │ 
 │       (bound on host 0.0.0.0 and port 3000)       │ 
 │                                                   │ 
 │ Handlers ............. 0  Processes ........... 1 │ 
 │ Prefork ....... Disabled  PID ............. 31623 │ 
 └───────────────────────────────────────────────────┘ 

Routing

Fiber の routing 機能では、HTTP request method と path を handler に対応させることができます。

試してみた

いくつかのリクエストを実装してみて、routing がどのように機能するのか試してみました。

POST request

POST /tasksCreateTaskHandler method にバインドする実装です。

main.go
package main

import (
	"github.com/gofiber/fiber/v2"
)

func main() {
	app := fiber.New()

	taskHandler := NewTaskHandler()

	app.Post("/tasks", taskHandler.CreateTaskHandler)

	if err := app.Listen(":3000"); err != nil {
		println(err.Error())
	}
}

type TaskHandler struct{}

type CreateTaskRequest struct {
	Name string `json:"name"`
}

type CreateTaskResponse struct {
	Name string `json:"name"`
}

func (h *TaskHandler) CreateTaskHandler(c *fiber.Ctx) error {
	request := new(CreateTaskRequest)

	if err := c.BodyParser(request); nil != err {
		return err
	}

	response := CreateTaskResponse{
		Name: request.Name,
	}

	if err := c.Status(fiber.StatusCreated).JSON(response); nil != err {
		return err
	}

	return nil
}

func NewTaskHandler() *TaskHandler {
	return &TaskHandler{}
}

Ctx API の BodyParser メソッド を使用することで Request Body をパースできます。

Request

curl -X POST localhost:3000/tasks \
    -H "Content-Type: application/json" \
    --data "{\"name\": \"Test name\"}"

Server

Test name

Response

{"name":"Test name"}

GET request (1)

GET /tasks request を ListTasksHandler method にバインドする実装です。

main.go
package main

import (
	"github.com/gofiber/fiber/v2"
)

func main() {
	app := fiber.New()

	taskHandler := NewTaskHandler()

	app.Get("/tasks", taskHandler.ListTasksHandler)

	if err := app.Listen(":3000"); err != nil {
		println(err.Error())
	}
}

type TaskHandler struct{}

type ListTaskResponse struct {
	Name string `json:"name"`
}

func (h *TaskHandler) ListTasksHandler(c *fiber.Ctx) error {
	response := make([]ListTaskResponse, 0, 2)
	response = append(response, ListTaskResponse{
		Name: "Test Name 1",
	})
	response = append(response, ListTaskResponse{
		Name: "Test Name 2",
	})

	if err := c.Status(fiber.StatusOK).JSON(response); nil != err {
		return err
	}

	return nil
}

func NewTaskHandler() *TaskHandler {
	return &TaskHandler{}
}

Go の slice は JSON の配列として返されます。

Request

curl -X GET localhost:3000/tasks \
    -H "Content-Type: application/json"

Response

[{"name":"Test Name 1"},{"name":"Test Name 2"}]

GET request (2)

GET /tasks/:id request を GetTaskHandler method にバインドする実装です。

main.go
package main

import (
	"github.com/gofiber/fiber/v2"
)

func main() {
	app := fiber.New()

	taskHandler := NewTaskHandler()

	app.Get("/tasks/:id", taskHandler.GetTaskHandler)

	if err := app.Listen(":3000"); err != nil {
		println(err.Error())
	}
}

type TaskHandler struct{}

type Task struct {
	ID   int
	Name string
}

type GetTaskResponse struct {
	ID   int    `json:"id"`
	Name string `json:"name"`
}

func (h *TaskHandler) GetTaskHandler(c *fiber.Ctx) error {
	param := struct {
		ID int `params:"id"`
	}{}

	if err := c.ParamsParser(&param); err != nil {
		return err
	}

	tasks := make([]Task, 0, 2)
	tasks = append(tasks, Task{
		ID:   1,
		Name: "Test Name 1",
	})
	tasks = append(tasks, Task{
		ID:   2,
		Name: "Test Name 2",
	})

	var response GetTaskResponse
	for _, task := range tasks {
		if task.ID == param.ID {
			response = GetTaskResponse{
				ID:   task.ID,
				Name: task.Name,
			}
		}
	}

	if err := c.Status(fiber.StatusOK).JSON(response); nil != err {
		return err
	}

	return nil
}

func NewTaskHandler() *TaskHandler {
	return &TaskHandler{}
}

Ctx API の paramsparser method を使用することで path parameter の値を取得できます。

Request

curl -X GET localhost:3000/tasks/2 \
    -H "Content-Type: application/json"

Response

{"id":2,"name":"Test Name 2"}

PUT request

PUT /tasks/:id request を UpdateTaskHandler method にバインドする実装です。

main.go
package main

import (
	"github.com/gofiber/fiber/v2"
)

func main() {
	app := fiber.New()

	taskHandler := NewTaskHandler()

	app.Put("/tasks/:id", taskHandler.UpdateTaskHandler)

	if err := app.Listen(":3000"); err != nil {
		println(err.Error())
	}
}

type TaskHandler struct{}

type Task struct {
	ID   int
	Name string
}

type UpdateTaskRequest struct {
	Name string `json:"name"`
}

type UpdateTaskResponse struct {
	ID   int    `json:"id"`
	Name string `json:"name"`
}

func (h *TaskHandler) UpdateTaskHandler(c *fiber.Ctx) error {
	request := new(UpdateTaskRequest)

	if err := c.BodyParser(request); nil != err {
		return err
	}

	param := struct {
		ID int `params:"id"`
	}{}

	if err := c.ParamsParser(&param); err != nil {
		return err
	}

	tasks := make([]Task, 0, 2)
	tasks = append(tasks, Task{
		ID:   1,
		Name: "Test Name 1",
	})
	tasks = append(tasks, Task{
		ID:   2,
		Name: "Test Name 2",
	})

	var response UpdateTaskResponse
	for _, task := range tasks {
		if task.ID == param.ID {
			task.Name = request.Name

			response = UpdateTaskResponse{
				ID:   task.ID,
				Name: task.Name,
			}
		}
	}

	if err := c.Status(fiber.StatusOK).JSON(response); nil != err {
		return err
	}

	return nil
}

func NewTaskHandler() *TaskHandler {
	return &TaskHandler{}
}

Request

curl -X PUT localhost:3000/tasks/2 \
    -H "Content-Type: application/json" \
    --data "{\"name\": \"Test name 3\"}"

Response

{"id":2,"name":"Test name 3"}

DELETE request

DELETE /tasks/:id request を DeleteTaskHandler method にバインドする実装です。

main.go
package main

import (
	"github.com/gofiber/fiber/v2"
)

func main() {
	app := fiber.New()

	taskHandler := NewTaskHandler()

	app.Delete("/tasks/:id", taskHandler.DeleteTaskHandler)

	if err := app.Listen(":3000"); err != nil {
		println(err.Error())
	}
}

type TaskHandler struct{}

func (h *TaskHandler) DeleteTaskHandler(c *fiber.Ctx) error {
	param := struct {
		ID int `params:"id"`
	}{}

	if err := c.ParamsParser(&param); err != nil {
		return err
	}

	println(param.ID)

	if err := c.Status(fiber.StatusNoContent).JSON(nil); nil != err {
		return err
	}

	return nil
}

func NewTaskHandler() *TaskHandler {
	return &TaskHandler{}
}

Request

curl -X DELETE localhost:3000/tasks/5 \
    -H "Content-Type: application/json"

Server

5

最後に

今回は routing や Ctx API を主に触りましたが、特に routing 機能は直感的で扱いやすく感じました。また gofiber は公式ドキュメントが充実しており、サンプルを見ながら手を動かすことができる点が良いと思いました。
実際の API ではデータベースとのやり取りがあったりしますが、今回の例には含めていないためイメージがわきづらいものとなってしまったかもしれません。申し訳ないです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?