Membangun REST API dalam Go: Panduan Lengkap
Bangun REST API yang siap diproduksi dengan ekosistem Go yang kuat
Membangun API REST berkinerja tinggi dengan Go telah menjadi pendekatan standar untuk memperkuat sistem di Google, Uber, Dropbox, dan ribuan startup.
Sederhana Go, dukungan konkurensi yang kuat, dan kompilasi yang cepat membuatnya ideal untuk pengembangan mikroservis dan backend.
Gambar hebat ini dihasilkan oleh FLUX.1-Kontext-dev: Model AI Augmentasi Gambar.
Mengapa Go untuk Pengembangan API?
Go membawa beberapa keunggulan yang menarik untuk pengembangan API:
Kinerja dan Efisiensi: Go dikompilasi menjadi kode mesin native, memberikan kinerja hampir seperti C tanpa kompleksitas. Manajemen memori yang efisien dan ukuran biner yang kecil membuatnya sempurna untuk deployment kontainer.
Konkurensi Bawaan: Goroutines dan saluran membuat penanganan ribuan permintaan konkuren menjadi mudah. Anda dapat memproses beberapa panggilan API secara bersamaan tanpa kode threading yang kompleks.
Perpustakaan Standar yang Kuat: Paket net/http menyediakan server HTTP siap produksi secara langsung. Anda dapat membangun API lengkap tanpa ketergantungan eksternal.
Kompilasi Cepat: Kecepatan kompilasi Go memungkinkan iterasi cepat selama pengembangan. Proyek besar dikompilasi dalam detik, bukan menit.
Tipis Tipe dengan Kesederhanaan: Sistem tipe Go menangkap kesalahan pada saat kompilasi sambil mempertahankan kejelasan kode. Bahasa memiliki himpunan fitur kecil yang cepat dipelajari.
Pendekatan Membangun API dalam Go
Menggunakan Perpustakaan Standar
Perpustakaan standar Go menyediakan segala yang dibutuhkan untuk pengembangan API dasar. Berikut contoh minimal:
package main
import (
"encoding/json"
"log"
"net/http"
)
type Response struct {
Message string `json:"message"`
Status int `json:"status"`
}
func healthHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(Response{
Message: "API sehat",
Status: 200,
})
}
func main() {
http.HandleFunc("/health", healthHandler)
log.Println("Server mulai di :8080")
log.Fatal(http.ListenAndServe(":8080", nil))
}
Pendekatan ini menawarkan kontrol penuh dan tanpa ketergantungan. Cocok untuk API sederhana atau ketika Anda ingin memahami penanganan HTTP pada tingkat dasar.
Kerangka Kerja Web Populer Go
Meskipun perpustakaan standar kuat, kerangka kerja dapat mempercepat pengembangan:
Gin: Kerangka web Go paling populer, dikenal dengan performa dan kemudahan penggunaan. Menyediakan routing yang nyaman, dukungan middleware, dan validasi permintaan.
package main
import (
"github.com/gin-gonic/gin"
"net/http"
)
func main() {
r := gin.Default()
r.GET("/users/:id", func(c *gin.Context) {
id := c.Param("id")
c.JSON(http.StatusOK, gin.H{
"user_id": id,
"name": "John Doe",
})
})
r.Run(":8080")
}
Chi: Router ringan, idiomatic yang terasa seperti ekstensi dari perpustakaan standar. Terutama baik untuk membangun layanan REST dengan routing bersarang.
Echo: Kerangka performa tinggi dengan middleware yang luas dan dokumentasi yang luar biasa. Dioptimalkan untuk kecepatan sambil tetap ramah pengembang.
Fiber: Dibuat berdasarkan Express.js, dibangun di atas Fasthttp. Ini adalah pilihan tercepat tetapi menggunakan implementasi HTTP yang berbeda dari perpustakaan standar.
Pola Arsitektur
Ketika bekerja dengan operasi database di Go, Anda perlu mempertimbangkan strategi ORM Anda. Proyek berbeda telah membandingkan pendekatan seperti GORM, Ent, Bun, dan sqlc, masing-masing menawarkan trade-off berbeda antara produktivitas pengembang dan kinerja.
Arsitektur Berlapis
Susun API Anda dengan pemisahan kekhawatiran yang jelas:
// Lapisan Handler - Kekhawatiran HTTP
type UserHandler struct {
service *UserService
}
func (h *UserHandler) GetUser(w http.ResponseWriter, r *http.Request) {
id := chi.URLParam(r, "id")
user, err := h.service.GetByID(r.Context(), id)
if err != nil {
respondError(w, err)
return
}
respondJSON(w, user)
}
// Lapisan Layanan - Logika bisnis
type UserService struct {
repo *UserRepository
}
func (s *UserService) GetByID(ctx context.Context, id string) (*User, error) {
// Validasi, transformasi, terapkan aturan bisnis
return s.repo.FindByID(ctx, id)
}
// Lapisan Repository - Akses data
type UserRepository struct {
db *sql.DB
}
func (r *UserRepository) FindByID(ctx context.Context, id string) (*User, error) {
// Implementasi query database
}
Pemisahan ini membuat pengujian lebih mudah dan menjaga kode tetap dapat dipelihara saat proyek berkembang.
Desain Berbasis Domain
Untuk aplikasi kompleks, pertimbangkan mengorganisasi kode berdasarkan domain daripada lapisan teknis. Setiap paket domain berisi model, layanan, dan repositori miliknya.
Jika Anda membangun aplikasi multi-tenant, memahami pola database untuk multi-tenant menjadi krusial untuk arsitektur API Anda.
Penanganan Permintaan dan Validasi
Validasi Input
Selalu validasi data yang masuk sebelum memprosesnya:
type CreateUserRequest struct {
Email string `json:"email" validate:"required,email"`
Username string `json:"username" validate:"required,min=3,max=50"`
Age int `json:"age" validate:"gte=0,lte=150"`
}
func (h *UserHandler) CreateUser(w http.ResponseWriter, r *http.Request) {
var req CreateUserRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
respondError(w, NewBadRequestError("JSON tidak valid"))
return
}
validate := validator.New()
if err := validate.Struct(req); err != nil {
respondError(w, NewValidationError(err))
return
}
// Proses permintaan yang valid
}
Paket go-playground/validator menyediakan aturan validasi yang luas dan validator kustom.
Konteks Permintaan
Gunakan konteks untuk nilai-nilai berbasis permintaan dan pembatalan:
func authMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
token := r.Header.Get("Authorization")
userID, err := validateToken(token)
if err != nil {
http.Error(w, "Tidak sah", http.StatusUnauthorized)
return
}
ctx := context.WithValue(r.Context(), "userID", userID)
next.ServeHTTP(w, r.WithContext(ctx))
})
}
Otentikasi dan Keamanan
Otentikasi Berbasis JWT
Token Web JSON menyediakan otentikasi tanpa status:
import "github.com/golang-jwt/jwt/v5"
func generateToken(userID string) (string, error) {
claims := jwt.MapClaims{
"user_id": userID,
"exp": time.Now().Add(time.Hour * 24).Unix(),
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
return token.SignedString([]byte(os.Getenv("JWT_SECRET")))
}
func validateToken(tokenString string) (string, error) {
token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
return []byte(os.Getenv("JWT_SECRET")), nil
})
if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
return claims["user_id"].(string), nil
}
return "", err
}
Pola Middleware
Implementasikan kekhawatiran lintas sebagai middleware:
func loggingMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
log.Printf("Dimulai %s %s", r.Method, r.URL.Path)
next.ServeHTTP(w, r)
log.Printf("Selesai dalam %v", time.Since(start))
})
}
func rateLimitMiddleware(next http.Handler) http.Handler {
limiter := rate.NewLimiter(10, 20) // 10 permintaan/detik, burst 20
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if !limiter.Allow() {
http.Error(w, "Melebihi batas permintaan", http.StatusTooManyRequests)
return
}
next.ServeHTTP(w, r)
})
}
Penanganan Kesalahan
Implementasikan respons kesalahan yang konsisten:
type APIError struct {
Code int `json:"code"`
Message string `json:"message"`
Details string `json:"details,omitempty"`
}
func (e *APIError) Error() string {
return e.Message
}
func NewBadRequestError(message string) *APIError {
return &APIError{
Code: http.StatusBadRequest,
Message: message,
}
}
func NewNotFoundError(resource string) *API错误 {
return &APIError{
Code: http.StatusNotFound,
Message: fmt.Sprintf("%s tidak ditemukan", resource),
}
}
func respondError(w http.ResponseWriter, err error) {
apiErr, ok := err.(*APIError)
if !ok {
apiErr = &APIError{
Code: http.StatusInternalServerError,
Message: "Kesalahan server internal",
}
// Log kesalahan aktual untuk debugging
log.Printf("Kesalahan tak terduga: %v", err)
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(apiErr.Code)
json.NewEncoder(w).Encode(apiErr)
}
Integrasi Database
Manajemen Koneksi
Gunakan pooling koneksi untuk akses database yang efisien:
func initDB() (*sql.DB, error) {
db, err := sql.Open("postgres", os.Getenv("DATABASE_URL"))
if err != nil {
return nil, err
}
db.SetMaxOpenConns(25)
db.SetMaxIdleConns(5)
db.SetConnMaxLifetime(5 * time.Minute)
return db, db.Ping()
}
Pola Query
Gunakan pernyataan siap dan konteks untuk operasi database yang aman:
func (r *UserRepository) FindByEmail(ctx context.Context, email string) (*User, error) {
query := `SELECT id, email, username, created_at FROM users WHERE email = $1`
var user User
err := r.db.QueryRowContext(ctx, query, email).Scan(
&user.ID,
&user.Email,
&user.Username,
&user.CreatedAt,
)
if err == sql.ErrNoRows {
return nil, ErrUserNotFound
}
return &user, err
}
Strategi Pengujian
Pengujian Handler
Uji handler HTTP menggunakan httptest:
func TestGetUserHandler(t *testing.T) {
// Setup
mockService := &MockUserService{
GetByIDFunc: func(ctx context.Context, id string) (*User, error) {
return &User{ID: "1", Username: "testuser"}, nil
},
}
handler := &UserHandler{service: mockService}
// Execute
req := httptest.NewRequest("GET", "/users/1", nil)
w := httptest.NewRecorder()
handler.GetUser(w, req)
// Assert
assert.Equal(t, http.StatusOK, w.Code)
var response User
json.Unmarshal(w.Body.Bytes(), &response)
assert.Equal(t, "testuser", response.Username)
}
Pengujian Integrasi
Uji alur kerja lengkap dengan database pengujian:
func TestCreateUserEndToEnd(t *testing.T) {
// Setup database pengujian
db := setupTestDB(t)
defer db.Close()
// Mulai server pengujian
server := setupTestServer(db)
defer server.Close()
// Buat permintaan
body := strings.NewReader(`{"email":"test@example.com","username":"testuser"}`)
resp, err := http.Post(server.URL+"/users", "application/json", body)
require.NoError(t, err)
defer resp.Body.Close()
// Verifikasi respons
assert.Equal(t, http.StatusCreated, resp.StatusCode)
// Verifikasi keadaan database
var count int
db.QueryRow("SELECT COUNT(*) FROM users WHERE email = $1", "test@example.com").Scan(&count)
assert.Equal(t, 1, count)
}
Dokumentasi API
OpenAPI/Swagger
Dokumentasikan API Anda menggunakan spesifikasi OpenAPI:
// @title API Pengguna
// @version 1.0
// @description API untuk mengelola pengguna
// @host localhost:8080
// @BasePath /api/v1
// @Summary Dapatkan pengguna berdasarkan ID
// @Description Mendapatkan informasi pengguna berdasarkan ID-nya
// @Tags pengguna
// @Accept json
// @Produce json
// @Param id path string true "ID Pengguna"
// @Success 200 {object} User
// @Failure 404 {object} APIError
// @Router /users/{id} [get]
func (h *UserHandler) GetUser(w http.ResponseWriter, r *http.Request) {
// Implementasi
}
Gunakan swaggo/swag untuk menghasilkan dokumentasi API interaktif dari komentar ini.
Optimisasi Kinerja
Kompresi Respons
Aktifkan kompresi gzip untuk respons:
import "github.com/NYTimes/gziphandler"
func main() {
r := chi.NewRouter()
r.Use(gziphandler.GzipHandler)
// Sisa pengaturan
}
Penyimpanan Cache
Implementasikan penyimpanan cache untuk data yang sering diakses:
import "github.com/go-redis/redis/v8"
type CachedUserRepository struct {
repo *UserRepository
cache *redis.Client
}
func (r *CachedUserRepository) GetByID(ctx context.Context, id string) (*User, error) {
// Coba cache terlebih dahulu
cached, err := r.cache.Get(ctx, "user:"+id).Result()
if err == nil {
var user User
json.Unmarshal([]byte(cached), &user)
return &user, nil
}
// Cache miss - ambil dari database
user, err := r.repo.FindByID(ctx, id)
if err != nil {
return nil, err
}
// Simpan ke cache
data, _ := json.Marshal(user)
r.cache.Set(ctx, "user:"+id, data, 10*time.Minute)
return user, nil
}
Pooling Koneksi
Ulangi koneksi HTTP untuk panggilan API eksternal:
var httpClient = &http.Client{
Timeout: 10 * time.Second,
Transport: &http.Transport{
MaxIdleConns: 100,
MaxIdleConnsPerHost: 10,
IdleConnTimeout: 90 * time.Second,
},
}
Pertimbangan Deployment
Containerisasi dengan Docker
Buat gambar Docker yang efisien menggunakan build multi-stage:
# Tahap build
FROM golang:1.21-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o api ./cmd/api
# Tahap produksi
FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=builder /app/api .
EXPOSE 8080
CMD ["./api"]
Ini menghasilkan gambar minimal (biasanya kurang dari 20MB) dengan hanya biner Anda dan sertifikat penting.
Manajemen Konfigurasi
Gunakan variabel lingkungan dan file konfigurasi:
type Config struct {
Port string
DatabaseURL string
JWTSecret string
LogLevel string
}
func LoadConfig() (*Config, error) {
return &Config{
Port: getEnv("PORT", "8080"),
DatabaseURL: getEnv("DATABASE_URL", ""),
JWTSecret: getEnv("JWT_SECRET", ""),
LogLevel: getEnv("LOG_LEVEL", "info"),
}, nil
}
func getEnv(key, defaultValue string) string {
if value := os.Getenv(key); value != "" {
return value
}
return defaultValue
}
Penutupan yang Lembut
Tangani sinyal penutupan dengan benar:
func main() {
server := &http.Server{
Addr: ":8080",
Handler: setupRouter(),
}
// Mulai server dalam goroutine
go func() {
if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
log.Fatalf("Kesalahan server: %v", err)
}
}()
// Tunggu sinyal interrupt
quit := make(chan os.Signal, 1)
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
<-quit
log.Println("Menutup server...")
// Beri permintaan yang sedang berjalan 30 detik untuk selesai
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
if err := server.Shutdown(ctx); err != nil {
log.Fatalf("Server dipaksa ditutup: %v", err)
}
log.Println("Server keluar")
}
Monitoring dan Observabilitas
Logging Terstruktur
Gunakan logging terstruktur untuk pencarian yang lebih baik:
import "go.uber.org/zap"
func setupLogger() (*zap.Logger, error) {
config := zap.NewProductionConfig()
config.OutputPaths = []string{"stdout"}
return config.Build()
}
func (h *UserHandler) GetUser(w http.ResponseWriter, r *http.Request) {
logger := h.logger.With(
zap.String("method", r.Method),
zap.String("path", r.URL.Path),
zap.String("user_id", r.Context().Value("userID").(string)),
)
logger.Info("Memproses permintaan")
// Logika handler
}
Pengumpulan Metrik
Ekspor metrik Prometheus:
import "github.com/prometheus/client_golang/prometheus"
var (
requestDuration = prometheus.NewHistogramVec(
prometheus.HistogramOpts{
Name: "http_request_duration_seconds",
Help: "Durasi permintaan HTTP",
},
[]string{"method", "path", "status"},
)
)
func init() {
prometheus.MustRegister(requestDuration)
}
func metricsMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
recorder := &statusRecorder{ResponseWriter: w, status: 200}
next.ServeHTTP(recorder, r)
duration := time.Since(start).Seconds()
requestDuration.WithLabelValues(
r.Method,
r.URL.Path,
strconv.Itoa(recorder.status),
).Observe(duration)
})
}
Pola Lanjutan
Bekerja dengan Output Terstruktur
Ketika membangun API yang terintegrasi dengan LLM, Anda mungkin perlu membatasi respons dengan output terstruktur. Ini sangat berguna untuk fitur AI di API Anda.
Web Scraping untuk Sumber Data API
Jika API Anda perlu menggabungkan data dari situs web lain, memahami alternatif untuk Beautiful Soup dalam Go dapat membantu Anda mengimplementasikan fungsi web scraping yang kuat.
Pembuatan Dokumen
Banyak API perlu menghasilkan dokumen. Untuk pembuatan PDF dalam Go, ada beberapa perpustakaan dan pendekatan yang dapat Anda integrasikan ke dalam endpoint API Anda.
Pencarian Semantik dan Pemeringkatan Ulang
Untuk API yang menangani pencarian teks dan pengambilan kembali, mengimplementasikan pemeringkatan ulang dengan model embedding dapat meningkatkan relevansi hasil pencarian secara signifikan.
Membangun Server MCP
Jika Anda mengimplementasikan API yang mengikuti Model Context Protocol, lihat panduan ini tentang mengimplementasikan server MCP dalam Go, yang mencakup spesifikasi protokol dan implementasi praktis.
Kesalahan Umum dan Solusinya
Tidak Menggunakan Konteks dengan Benar
Selalu kirim dan hormati konteks sepanjang rantai panggilan Anda. Ini memungkinkan penanganan pembatalan dan timeout yang tepat.
Mengabaikan Bocoran Goroutine
Pastikan semua goroutine dapat selesai. Gunakan konteks dengan deadline dan selalu memiliki cara untuk memberi sinyal selesainya.
Pengelolaan Kesalahan yang Buruk
Jangan kembalikan kesalahan database mentah ke klien. Bungkus kesalahan dengan konteks dan kembalikan pesan yang disanitasi dalam respons API.
Validasi Input yang Tidak Memadai
Validasi semua input di titik masuk. Jangan pernah mempercayai data klien, bahkan dari pengguna yang telah diotentikasi.
Pengujian yang Tidak Memadai
Jangan hanya uji jalur yang menyenangkan. Cakup kasus kesalahan, kondisi pinggir, dan skenario akses bersamaan.
Ringkasan Praktik Terbaik
-
Mulai Sederhana: Mulai dengan perpustakaan standar. Tambahkan kerangka kerja ketika kompleksitas membutuhkannya.
-
Lapisan Aplikasi Anda: Pisahkan handler HTTP, logika bisnis, dan akses data untuk keterpeliharaan.
-
Validasi Segala Sesuatu: Periksa input di batas. Gunakan tipe kuat dan perpustakaan validasi.
-
Kelola Kesalahan Secara Konsisten: Kembalikan respons kesalahan terstruktur. Log kesalahan internal tetapi jangan eksposnya.
-
Gunakan Middleware: Implementasikan kekhawatiran lintas (otentikasi, logging, metrik) sebagai middleware.
-
Uji Secara Menyeluruh: Tulis tes unit untuk logika, tes integrasi untuk akses data, dan tes end-to-end untuk alur kerja.
-
Dokumentasikan API Anda: Gunakan OpenAPI/Swagger untuk dokumentasi interaktif.
-
Pantau Produksi: Implementasikan logging terstruktur, pengumpulan metrik, dan pemeriksaan kesehatan.
-
Optimalkan dengan Hati-hati: Profil sebelum mengoptimalkan. Gunakan caching, pooling koneksi, dan kompresi di tempat yang bermanfaat.
-
Rancang untuk Penutupan yang Lembut: Tangani sinyal penutupan dan drainkan koneksi dengan benar.
Daftar Pemeriksaan Awal
Untuk referensi saat bekerja pada proyek Go, memiliki lembar cepat Go yang komprehensif di tangan dapat mempercepat pengembangan dan berfungsi sebagai referensi cepat untuk sintaks dan pola umum.
Siap membangun API Go pertama Anda? Mulai dengan langkah-langkah berikut:
- ✅ Atur lingkungan Go dan struktur proyek Anda
- ✅ Pilih antara perpustakaan standar atau kerangka kerja
- ✅ Implementasikan endpoint CRUD dasar
- ✅ Tambahkan validasi permintaan dan penanganan kesalahan
- ✅ Implementasikan middleware otentikasi
- ✅ Tambahkan integrasi database dengan pooling koneksi
- ✅ Tulis tes unit dan integrasi
- ✅ Tambahkan dokumentasi API
- ✅ Implementasikan logging dan metrik
- ✅ Containerisasi dengan Docker
- ✅ Atur pipeline CI/CD
- ✅ Deploy ke produksi dengan pemantauan
Kesimpulan
Go menyediakan fondasi yang sangat baik untuk membangun REST API, menggabungkan kinerja, kesederhanaan, dan alat bantu yang kuat. Baik Anda sedang membangun microservices, alat internal, atau API publik, ekosistem Go memiliki solusi yang matang untuk setiap kebutuhan.
Kunci keberhasilan adalah memulai dengan pola arsitektur yang solid, menerapkan penanganan kesalahan dan validasi yang tepat sejak awal, serta membangun cakupan pengujian yang komprehensif. Seiring API Anda berkembang, karakteristik kinerja Go dan dukungan konkurensi yang kuat akan sangat membantu Anda.
Ingatlah bahwa pengembangan API adalah proses iteratif. Mulailah dengan implementasi yang minimal dan dapat dioperasikan, kumpulkan umpan balik, dan perbaiki pendekatan Anda berdasarkan pola penggunaan dunia nyata. Kecepatan kompilasi Go dan refaktorisasi yang sederhana membuat siklus iterasi ini lancar dan produktif.
Tautan yang Berguna
- Go Cheat Sheet
- Membandingkan ORM Go untuk PostgreSQL: GORM vs Ent vs Bun vs sqlc
- Polanya Database Multi-Tenant dengan Contoh dalam Go
- Alternatif Beautiful Soup untuk Go
- Membuat PDF dalam GO - Perpustakaan dan contoh
- Membatasi LLM dengan Output Terstruktur: Ollama, Qwen3 & Python atau Go
- Mengurutkan ulang dokumen teks dengan Ollama dan Model Embedding Qwen3 - dalam Go
- Model Context Protocol (MCP), dan catatan tentang implementasi server MCP dalam Go
Sumber Daya Eksternal
Dokumentasi Resmi
- Dokumentasi Resmi Go - Dokumentasi dan tutorial resmi Go
- Paket net/http Go - Dokumentasi paket HTTP standar
- Effective Go - Praktik terbaik dalam menulis kode Go yang jelas dan idiomatic
Framework dan Perpustakaan Populer
- Gin Web Framework - Framework web HTTP cepat dengan fitur yang luas
- Chi Router - Router ringan dan idiomatic untuk membangun layanan HTTP Go
- Echo Framework - Framework web berkinerja tinggi, dapat diperluas, dan minimalis
- Fiber Framework - Framework web yang terinspirasi Express, dibangun di atas Fasthttp
- GORM - Perpustakaan ORM yang luar biasa untuk Golang
- golang-jwt - Implementasi JWT untuk Go
Alat Pengujian dan Pengembangan
- Testify - Toolkit dengan asersi dan mock yang umum
- Paket httptest - Utilitas standar untuk pengujian HTTP
- Swaggo - Menghasilkan dokumentasi API RESTful secara otomatis
- Air - Live reload untuk aplikasi Go selama pengembangan
Praktik Terbaik dan Panduan
- Tata Letak Proyek Go - Tata letak proyek Go standar
- Panduan Gaya Go Uber - Panduan gaya Go komprehensif dari Uber
- Komentar Ulasan Kode Go - Komentar umum selama ulasan kode Go
- Prinsip Desain REST API Terbaik - Prinsip desain REST API umum
Keamanan dan Otentikasi
- OWASP Praktik Pemrograman Go yang Aman - Panduan keamanan untuk aplikasi Go
- OAuth2 untuk Go - Implementasi OAuth 2.0
- Paket bcrypt - Implementasi hashing kata sandi
Kinerja dan Pemantauan
- pprof - Alat profiling bawaan untuk program Go
- Klien Prometheus - Perpustakaan instrumen Prometheus untuk Go
- Zap Logger - Logging yang cepat, terstruktur, dan berlapis