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 の起動
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 /tasks
を CreateTaskHandler
method にバインドする実装です。
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 にバインドする実装です。
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 にバインドする実装です。
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(¶m); 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 にバインドする実装です。
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(¶m); 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 にバインドする実装です。
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(¶m); 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 ではデータベースとのやり取りがあったりしますが、今回の例には含めていないためイメージがわきづらいものとなってしまったかもしれません。申し訳ないです。