For the complete documentation index, see llms.txt. This page is also available as Markdown.

CRUD

Setelah memiliki routing yang rapi, kini saatnya melengkapi operasi CRUD (Create, Read, Update, Delete) untuk resource User. Bab ini akan membangun kelima endpoint REST API yang umum:

Method
Endpoint
Deskripsi

GET

/users`

Mendaftar semua user

POST

/users

Membuat user baru

GET

/users/{id}

Membaca detail user

PUT

/users/{id}

Mengupdate user

DELETE

/users/{id}

Menghapus user (soft delete)

๐Ÿ“‚ Kode Lengkap Bab Ini: Seluruh kode yang dibahas di bab ini tersedia di GitHub:

๐Ÿ”— github.com/jacky-htg/workshop/tree/main/11-crud

11.1 Create User

Operasi Create adalah yang paling kompleks karena melibatkan:

  1. Hashing password โ€“ menggunakan bcrypt (tidak boleh disimpan plain text)

  2. Generate ID โ€“ menggunakan UUID v7 (terurut berdasarkan waktu)

  3. Validasi input โ€“ akan dibahas di bab terpisah

11.1.1 Repository Layer โ€“ Create

Tambahkan method Create ke UserRepository interface dan implementasinya:

// internal/repository/user_repository.go
type UserRepository interface {
    List() ([]model.User, error)
    Create(*model.User) error  // โ† tambahan
    // ... method lainnya
}

func (u *userRepository) Create(user *model.User) error {
    query := `INSERT INTO users (id, name, username, password, email, is_active) 
              VALUES ($1, $2, $3, $4, $5, $6)`
    _, err := u.db.Exec(query, user.ID, user.Name, user.Username, 
                        user.Password, user.Email, user.IsActive)
    if err != nil {
        u.log.Error(context.Background(), "error: inserting user", slog.Any("error", err))
        return err
    }
    return nil
}

11.1.2 Service Layer โ€“ Create dengan Business Logic

Service layer bertanggung jawab untuk hashing password dan generate ID:

Catatan: bcrypt.DefaultCost adalah nilai 10. Untuk keamanan lebih tinggi, bisa ditingkatkan (dengan konsekuensi performa lebih lambat).

11.1.3 DTO โ€“ UserRequest (Input)

Buat DTO khusus untuk menerima input dari client. Ini memisahkan struktur request dari model database:

11.1.4 Handler Layer โ€“ Create

Handler bertugas menerima request, memparsing JSON, memanggil service, dan mengembalikan response:

Status code: 201 Created adalah status yang tepat untuk operasi Create.

11.2 Read (Get by ID)

11.2.1 Repository โ€“ FindById

11.2.2 Service โ€“ FindById

11.2.3 Handler โ€“ FindById dengan Path Parameter

Go 1.22+ menyediakan r.PathValue("id") untuk mengambil parameter dari URL:

  • Ubah file internal/handler/user_handler.go untuk menambhakan method FindById

11.3 Update

11.3.1 DTO โ€“ UserUpdateRequest

Untuk update, kita hanya mengizinkan field tertentu yang bisa diubah:

11.3.2 Repository โ€“ Update dengan RETURNING

RETURNING clause: Mengambil field yang tidak diubah (username, email) untuk mempertahankan nilainya di struct user.

11.3.3 Service โ€“ Update dengan Validasi Keberadaan

11.3.4 Handler โ€“ Update

11.4 Delete (Soft Delete)

11.4.1 Konsep Soft Delete

Soft delete berarti data tidak dihapus secara fisik, hanya ditandai sebagai terhapus dengan mengisi field deleted_at. Keuntungan:

  • Data bisa dipulihkan

  • Audit trail (kapan dihapus)

  • Referensi integritas tetap terjaga

Perubahan pada query List dan FindById (hanya menampilkan data yang belum terhapus):

11.4.2 Repository โ€“ Delete (Soft)

11.4.3 Service โ€“ Delete

11.4.4 Handler โ€“ Delete (No Content)

Status code: 204 No Content adalah response yang tepat untuk DELETE karena tidak ada data yang dikembalikan.

11.5 Routing Lengkap

Update internal/router/api.go dengan semua endpoint:

11.6 Testing CRUD dengan cURL

Create User

Response: 201 Created + data user (tanpa password)

List Users

Get User by ID

Update User

Delete User

Ringkasan Bab 11

Di bab ini kita telah melengkapi semua operasi CRUD:

Operasi
Method
Endpoint
Status Code

Create

POST

/users

201 Created

List

GET

/users

200 OK

Read

GET

/users/{id}

200 OK / 404 Not Found

Update

PUT

/users/{id}

200 OK / 404 Not Found

Delete

DELETE

/users/{id}

204 No Content / 404 Not Found

Penting yang dipelajari:

  • โœ… Hashing password dengan bcrypt

  • โœ… Generate UUID v7 untuk ID terurut

  • โœ… Soft delete pattern dengan deleted_at

  • โœ… Path parameter dengan r.PathValue()

  • โœ… RETURNING clause untuk mengambil data setelah update

  • โœ… DTO terpisah untuk Create (full) vs Update (partial)

Yang akan datang:

  • Saat ini error handling masih sederhana (http.Error)

  • Bab selanjutnya: Standard Response โ€“ membangun format response JSON yang konsisten di seluruh API

Last updated