Golang REST API ve CRUD İşlemleri
#Golang, #REST API, #CRUD, #GofiberBugün Golang ile Gofiber kullanarak yüksek performanslı bir REST API nasıl geliştirilir bunun üzerine konuşacağız.
Gofiber framework kullanmamızın sebebini şu şekilde listeleyebiliriz:
- Yüksek performans ve düşük bellek kullanımı
- Hızlı server-side programlama
- Kütüphane tarafından sağlanan middlewarelar
- Kolay rotalama
Proje Oluşturma
Genel olarak konuya giriş yaptığımıza göre Go projemizi oluşturarak devam edebiliriz. Boş bir Go projesi oluşturmak için şu işlemleri yapalım.
$ mkdir restapi
$ go mod init github.com/USERNAME/REPO_NAME
Bu işlemleri yaptıktan sonra gerekli klasörler ve dosyalar oluşacaktır. Şimdi proje dizinimizde main.go dosyamızı oluşturalım, ardından gofiber kütüphanesini projemize aşağıdaki komut ile ekleyelim.
$ go get github.com/gofiber/fiber/v2
Klasör Yapısı
/app
Bu klasör bizim genel Fiber uygulamamıza dair fonksiyonları barındırmalıdır. Şu şekilde kapsamlandırabiliriz.
- controllers
Rotalarda kullanılacak controllerları burada tanımlarız. - models
Uygulamamızdaki modelleri bu klasör altında oluşturmalıyız.
/pkg
- configs
Bu klasörde uygulamamıza ait konfigürasyon dosyalarını tutabiliriz. - middleware
Bu klasörde fiber uygulamamız için gerekli middlewareları oluşturabiliriz. - routes
Bu klasör içerisinde projemize ait rotaları tutabiliriz. - utils
Bu klasörde sunucumuzu başlatan, hataları kontrol eden veya uygun gördüğümüz dosyaları oluşturabiliriz.
/platform
- cache
Bu klasörde kullanacağımız önbellekleme çözümünü implemente edebiliriz. - database
Veritabanı bağlantılarını ve diğer işlemleri yapacağımız kısım. - migrations
Migrationları oluşturacağımız klasör
Fiber Sunucusu
Bunun için öncelikle pkg/utils
altında server.go
dosyamızı oluşturalım ve içeriğini aşağıdaki şekilde ekleyelim.
package utils
import (
"fmt"
"log"
"github.com/gofiber/fiber/v2"
)
func CreateServer(port int) {
// Create Fiber App
app := fiber.New()
// Start server
log.Fatal(app.Listen(fmt.Sprintf(":%d", port)))
}
Ardından bu fonksiyona bir port değişkeni vererek main.go
içerisinde şu şekilde çağırabiliriz.
Bu fonksiyon içerisinde middlewarelarımızı ve rotalarımızı kaydedeceğiz.
Örnek main.go
içeriği:
package main
import "github.com/dogukanoksuz/go-rest-api-example/pkg/utils"
func main() {
utils.CreateServer(3000)
}
Model Oluşturmak
Genel olarak projemizin klasör yapısından bahsettiğimize göre bu tarz bir yapıyı oluşturalım.
Ardından models
klasörümizin içerisinde ilk modelimizi oluşturalım. Ben post yani gönderi isminde bir model oluşturacağım. Dosya içeriğini aşağıdaki gibi tanımlayabiliriz.
package models
import (
"github.com/google/uuid"
"gorm.io/gorm"
)
type Post struct {
ID string `gorm:"primary_key"`
Title string
Content string `gorm:"type:text"`
}
func (post *Post) BeforeCreate(tx *gorm.DB) error {
post.ID = uuid.NewString()
return nil
}
Oluşturduktan sonra ilk modelimiz hazır. Genel olarak detaylarından bahsetmek gerekirse ID alanı için UUID oluşturuyoruz. Bunun için de GORM’un pre-hooklarından faydalanarak bir UUID tanımlıyoruz.
Veritabanı Bağlantısı
Öncelikle kendi ortamınızda bir veritabanı sunucusuna sahip olmanız gerekmektedir. Ben devilbox kullanarak bir MariaDB instanceı oluşturdum. Siz de benzer programlarla veritabanınızı oluşturun.
Bu işlemin ardından platform/database
klasörü altında mysql.go
isminde bir dosya oluşturun.
package database
import (
"fmt"
"os"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
var Conn *gorm.DB
func Init() error {
var err error
dsn := fmt.Sprintf(
"%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&parseTime=True&loc=Local",
"DB_USER",
"DB_PASS",
"DB_HOST",
"DB_PORT",
"DB_NAME",
)
Conn, err = gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
return err
}
return nil
}
Yukarıdaki şekilde tanımlama yaptıktan sonra DB_USER
gibi boşlukları kendi veritabanı bilgileriniz ile değiştirin. Ardından database.Init()
şeklinde server.go
dosyanız içerisinde çağırımı yaparak sunucu başlamadan önce veritabanı bağlantınızı açabilirsiniz.
Migrationlar
Migration işlemi oluşturduğumuz modellerin otomatik şekilde veritabanında tablolarının eklenmesi işlemidir. Bunun için platform/migrations
altında migrate.go
isminde bir dosya oluşturalım ve içeriğini aşağıdaki şekilde girelim.
package migrations
import (
"github.com/dogukanoksuz/go-rest-api-example/app/models"
"github.com/dogukanoksuz/go-rest-api-example/platform/database"
)
func Migrate() {
database.Conn.AutoMigrate(&models.Post{})
}
Bu kısımdaki AutoMigrate
fonksiyonu GORM’un içerisinde gelen bir fonksiyondur. Diğer oluşturduğunuz modeller (varsa) bu kısımda tanımlayarak uygulama başlangıcında tablolarının oluşturulmasını sağlayabilirsiniz. Bu fonksiyonu CreateServer
fonksiyonu altında database.Init
fonksiyonundan hemen sonra çağırabiliriz.
Kontrolcü Oluşturmak
Kontrolcüler projemizin önemli bir ayağını oluşturmaktadır. Fiber tarafında ismi Handler olarak geçmektedir ve rotalarımızın ucunu bağladığımız Go fonksiyonlarına kontrolcü demekteyiz. Kontrolcüler bizim için postlarımızı listeleme, oluşturma, güncelleme ve silme işlemlerini yapabilir.
GORM ve Fiber kullanarak listeleme ve oluşturma işlemlerini örnek olarak inceleyelim.
Oluşturma (Create)
package post
import (
"github.com/dogukanoksuz/go-rest-api-example/app/models"
"github.com/dogukanoksuz/go-rest-api-example/platform/database"
"github.com/gofiber/fiber/v2"
)
func Create(ctx *fiber.Ctx) error {
post := models.Post{}
if err := ctx.BodyParser(&post); err != nil {
return ctx.Status(503).JSON(err)
}
if err := database.Conn.Create(&post).Error; err != nil {
return ctx.Status(503).JSON(err)
}
return ctx.JSON(post)
}
Bu dosyayı app/controllers/post/create.go
olarak oluşturalım ve inceleyelim. Öncelikle Fiber’ın BodyParser
fonksiyonunu kullanarak bodyden gelen JSON’u parse edelim. Ardından database.Conn.Create
diyerek girdimizi veritabanına ekleyelim. İşlemlerin sonunda da kullanıcıya JSON olarak oluşturulan gönderimizi gönderebiliriz.
Listeleme (Index/List)
package post
import (
"github.com/dogukanoksuz/go-rest-api-example/app/models"
"github.com/dogukanoksuz/go-rest-api-example/platform/database"
"github.com/gofiber/fiber/v2"
)
func Index(ctx *fiber.Ctx) error {
posts := []models.Post{}
database.Conn.Find(&posts)
return ctx.JSON(posts)
}
GORM ile bir modelin girdilerini listelemek istediğimizde yukarıdaki yola başvurabiliriz. Find
fonksiyonu bizim için tüm postları getirecektir ve bunu da kullanıcılara JSON olarak döndürebiliriz.
Rota Tanımlamak
Rotalar REST sunucumuzda hangi uçların hangi fonksiyonları çağıracağını, alacağı parametreleri vb. tanımladığımız yerdir. Gelin örnek olarak yukarıdaki iki fonksiyonun rotalarını tanımlayalım.
Bunun pkg/routes
altında post.go
dosyamızı oluşturabiliriz. Bu dosyanın içeriği aşağıdaki gibi olmalıdır.
package routes
import (
"github.com/dogukanoksuz/go-rest-api-example/app/controllers/post"
"github.com/gofiber/fiber/v2"
)
func PostRoutes(app *fiber.App) {
// List All Posts
app.Get("/posts", post.Index)
// Create Post
app.Post("/post", post.Create)
}
Bu PostRoutes
fonksiyonumuzu da CreateServer
altında fiber app oluşturduktan hemen sonra çağırabiliriz. routes.PostRoutes(app)
şeklinde tanımlamayı yaptığımızda rotalarımız kullanıma hazır olacaktır.
Derleme ve Denemeler
Projeyi çalıştırmak için go run main.go
şeklinde başlatabilir ya da go build
diyerek oluşan executable’ı çalıştırabiliriz.
Temel olarak oluşturduğunuz REST API’ı derleyip denemeler yapın. Bunun için Postman programını veya sevdiğiniz bir REST clienti kullanabilirsiniz.
Rotalarınıza 127.0.0.1:3000/posts
şeklinde erişebilirsiniz. Eğer veritabanında girdi oluşturulmuş ise başarılı şekilde dönüşümüzü alacağız.
Tamamlanmış Proje
dogukanoksuz/go-rest-api-boilerplate: Golang REST API Boilerplate with Gofiber (github.com) altından projenin tamamlanmış haline ulaşabilirsiniz. Post modeli için tüm CRUD işlemlerinin tamamlandığı örnek bu şekilde incelenebilir.
Okuduğunuz için teşekkür ederim. Problemler için GitHub reposu içerisinde issue oluşturabilir veya aşağıdaki yorumlar bölümünü kullanabilirsiniz.