ساخت API سریع با Go و Fiber

شروع کار با زبان Go و فریم‌ورک Fiber؛ ساخت مسیرهای CRUD، میدل‌ورها، هم‌زمانی امن با Mutex و استقرار یک فایل اجرایی سبک و بدون وابستگی.

ساخت API سریع با Go و Fiber
زمان انتشار:
۸ شهریور ۱۴۰۵
زمان مطالعه:
حدود 3 دقیقه
نویسنده:
علیرضا مهدی زاده
دسته‌بندی:بک‌اند

چرا Go برای ساخت API؟

وقتی تعداد کاربران یک سرویس رشد می‌کند، مصرف حافظه و زمان پاسخ اهمیت پیدا می‌کنند. زبان Go با کامپایل به یک فایل اجرایی مستقل، مدیریت هم‌زمانی ساده با Goroutineها و مصرف منابع بسیار کم، انتخاب محبوبی برای سرویس‌های پرترافیک است. فریم‌ورک Fiber هم با الهام از Express.js ساخته شده؛ بنابراین اگر با Node.js کار کرده باشید، خیلی سریع با آن احساس راحتی می‌کنید.

قطار مترو در حال عبور با سرعت زیاد؛ پاسخ‌گویی سریع API نوشته‌شده با Go

راه‌اندازی پروژه

mkdir notes-api && cd notes-api
go mod init github.com/username/notes-api
go get github.com/gofiber/fiber/v2

اولین سرور Fiber

package main

import (
	"log"

	"github.com/gofiber/fiber/v2"
	"github.com/gofiber/fiber/v2/middleware/logger"
	"github.com/gofiber/fiber/v2/middleware/recover"
)

func main() {
	app := fiber.New(fiber.Config{AppName: "Notes API"})

	app.Use(recover.New())
	app.Use(logger.New())

	app.Get("/health", func(c *fiber.Ctx) error {
		return c.JSON(fiber.Map{"status": "ok"})
	})

	log.Fatal(app.Listen(":8080"))
}

میدل‌ور recover جلوی از کار افتادن کل سرور در صورت بروز panic را می‌گیرد و logger هر درخواست را همراه با زمان پاسخ ثبت می‌کند.

هواپیماهای نمایشی در آرایش منظم در آسمان مه‌آلود؛ Goroutineهایی که هم‌زمان و هماهنگ کار می‌کنند

ساخت مسیرهای CRUD

برای نظم بیشتر، مسیرها را گروه‌بندی و ورودی را به یک struct تبدیل می‌کنیم:

type Note struct {
	ID    int    `json:"id"`
	Title string `json:"title"`
	Body  string `json:"body"`
}

func registerNotes(app *fiber.App, store *NoteStore) {
	api := app.Group("/api/notes")

	api.Get("/", func(c *fiber.Ctx) error {
		return c.JSON(store.All())
	})

	api.Post("/", func(c *fiber.Ctx) error {
		var n Note
		if err := c.BodyParser(&n); err != nil || n.Title == "" {
			return fiber.NewError(fiber.StatusUnprocessableEntity, "invalid note")
		}
		return c.Status(fiber.StatusCreated).JSON(store.Add(n))
	})

	api.Delete("/:id", func(c *fiber.Ctx) error {
		id, err := c.ParamsInt("id")
		if err != nil || !store.Remove(id) {
			return fiber.ErrNotFound
		}
		return c.SendStatus(fiber.StatusNoContent)
	})
}

هم‌زمانی امن

Fiber هر درخواست را هم‌زمان پردازش می‌کند؛ پس اگر داده‌ای در حافظه‌ی مشترک دارید، باید از آن محافظت کنید:

type NoteStore struct {
	mu    sync.RWMutex
	notes map[int]Note
	next  int
}

func (s *NoteStore) Add(n Note) Note {
	s.mu.Lock()
	defer s.mu.Unlock()
	s.next++
	n.ID = s.next
	s.notes[n.ID] = n
	return n
}

در پروژه‌ی واقعی این لایه با پایگاه داده (مثلاً pgx یا GORM) جایگزین می‌شود، اما الگوی جداسازی Handler از لایه‌ی ذخیره‌سازی ثابت می‌ماند.

لپ‌تاپ، گوشی و لیوان آب روی میز چوبی؛ محیط توسعه‌ی سبک برای پروژه‌های Go

یک نکته‌ی مهم درباره‌ی Fiber

Fiber برای سرعت بیشتر، مقادیر درون Ctx را بازاستفاده می‌کند. یعنی رشته‌ای که از c.Params() می‌گیرید، پس از پایان Handler معتبر نیست. اگر باید آن را در Goroutine یا حافظه نگه دارید، ابتدا یک کپی بسازید یا در تنظیمات گزینه‌ی Immutable: true را فعال کنید.

استقرار؛ یک فایل، بدون وابستگی

CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o notes-api

خروجی یک فایل اجرایی چند مگابایتی است که بدون نصب هیچ Runtime روی سرور اجرا می‌شود. ایمیج Docker آن هم می‌تواند از scratch یا distroless ساخته شود و حجمی کمتر از ۲۰ مگابایت داشته باشد.

پلکان برقی در یک ایستگاه مدرن و خلوت؛ مسیر مستقیم و بی‌وقفه‌ی درخواست تا پاسخ

چه زمانی Go را انتخاب کنیم؟

  • سرویس‌های پرترافیک: وقتی هزاران درخواست هم‌زمان و زمان پاسخ پایین اهمیت دارد.
  • میکروسرویس‌ها: فایل اجرایی کوچک و زمان راه‌اندازی چند میلی‌ثانیه‌ای.
  • ابزارهای خط فرمان: یک فایل برای ویندوز، مک و لینوکس.
  • سرورهای کم‌منبع: مصرف حافظه‌ی چند ده مگابایتی حتی زیر بار.

جمع‌بندی

ترکیب Go و Fiber، سرعت و کارایی یک زبان کامپایلی را با سادگی و تجربه‌ی آشنای Express ارائه می‌دهد. اگر پروژه‌ی بعدی شما یک API با ترافیک بالاست، یا صرفاً می‌خواهید زبان تازه‌ای یاد بگیرید، ساخت همین سرویس یادداشت نقطه‌ی شروع خوبی است.

دیدگاه‌ها

برای ثبت دیدگاه باید شماره موبایل خود را تأیید کنید.

هنوز دیدگاهی ثبت نشده است. اولین نفر باشید!