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

راهاندازی پروژه
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 هر درخواست را همراه با زمان پاسخ ثبت میکند.

ساخت مسیرهای 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 از لایهی ذخیرهسازی ثابت میماند.

یک نکتهی مهم دربارهی 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 با ترافیک بالاست، یا صرفاً میخواهید زبان تازهای یاد بگیرید، ساخت همین سرویس یادداشت نقطهی شروع خوبی است.

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