Menu
CoddyTech

Pola Opsi Fungsional

Termasuk bagian Pemrograman Berorientasi Objek dalam perjalanan GO di Coddy. Pelajaran 79 dari 107.

Saat membuat struct dengan banyak field konfigurasi opsional, fungsi konstruktor bisa menjadi sulit dikelola. Pola Opsi Fungsional mengatasi masalah ini dengan elegan menggunakan fungsi untuk mengonfigurasi object.

Pertimbangkan struct server dengan beberapa pengaturan opsional. Alih-alih menggunakan konstruktor dengan banyak parameter, kita mendefinisikan tipe opsi dan fungsi yang mengembalikan opsi:

type Server struct {
    host    string
    port    int
    timeout int
}

type Option func(*Server)

func WithPort(port int) Option {
    return func(s *Server) {
        s.port = port
    }
}

func WithTimeout(timeout int) Option {
    return func(s *Server) {
        s.timeout = timeout
    }
}

Konstruktor menerima list opsi variadik dan menerapkan setiap opsi:

func NewServer(host string, opts ...Option) *Server {
    s := &Server{
        host:    host,
        port:    8080,    // bawaan
        timeout: 30,      // bawaan
    }
    for _, opt := range opts {
        opt(s)
    }
    return s
}

Sekarang, membuat server menjadi lebih mudah dibaca dan fleksibel:

// Gunakan pengaturan bawaan
s1 := NewServer("localhost")

// Sesuaikan opsi tertentu
s2 := NewServer("localhost", WithPort(3000), WithTimeout(60))

Pola ini unggul karena pemanggil hanya menentukan yang mereka butuhkan, nilai default terlihat jelas di satu tempat, dan penambahan opsi baru tidak merusak kode yang sudah ada. Pola ini banyak digunakan di library Go seperti grpc dan zap.

challenge icon

Tantangan

Mudah

Mari buat koneksi database yang dapat dikonfigurasi dengan Functional Options Pattern! Pola ini sangat cocok saat kamu memiliki banyak pengaturan opsional dengan nilai default yang masuk akal, persis seperti yang dibutuhkan koneksi database.

Kamu akan mengatur kodemu dalam dua file:

  • database.go: Definisikan tipe koneksi database dan fungsi opsi.

    Buat struct DBConnection dengan field yang tidak diekspor berikut:

    • host (string)
    • port (int)
    • username (string)
    • password (string)
    • maxConnections (int)
    • timeout (int), dalam detik

    Definisikan tipe Option sebagai fungsi yang memodifikasi *DBConnection.

    Buat fungsi opsi berikut yang mengembalikan Option:

    • WithPort(port int)
    • WithCredentials(username, password string)
    • WithMaxConnections(max int)
    • WithTimeout(seconds int)

    Buat constructor NewDBConnection(host string, opts ...Option) yang mengembalikan *DBConnection. Tetapkan nilai default berikut: port 5432, username "admin", password "secret", maxConnections 10, timeout 30. Terapkan semua opsi yang diberikan setelah menetapkan nilai default.

    Tambahkan method ConnectionString() yang mengembalikan info koneksi dalam format ini:

    [username]:[password]@[host]:[port] (max:[maxConnections], timeout:[timeout]s)
  • main.go: Buat koneksi database dengan berbagai konfigurasi.

    Baca host, lalu baca jumlah opsi yang akan diterapkan. Untuk setiap opsi, baca tipe opsi dan nilainya:

    • port diikuti nomor port
    • credentials diikuti username dan password (dua baris)
    • maxconn diikuti jumlah koneksi maksimum
    • timeout diikuti batas waktu dalam detik

    Buat DBConnection dengan opsi yang ditentukan dan cetak string koneksinya.

Input berikut akan diberikan:

  • Baris 1: Nama host
  • Baris 2: Jumlah opsi
  • Baris berikutnya: Tipe opsi dan nilainya

Contohnya, jika diberikan:

localhost
0

Output kamu seharusnya:

admin:secret@localhost:5432 (max:10, timeout:30s)

Dan jika diberikan:

db.example.com
2
port
3306
credentials
root
mypassword

Output kamu seharusnya:

root:mypassword@db.example.com:3306 (max:10, timeout:30s)

Dan jika diberikan:

production.server
4
port
5433
credentials
dbuser
securepass123
maxconn
50
timeout
60

Output kamu seharusnya:

dbuser:securepass123@production.server:5433 (max:50, timeout:60s)

Perhatikan bahwa pemanggil hanya menentukan opsi yang dibutuhkan: pengaturan yang tidak ditentukan akan menggunakan nilai default yang masuk akal. Inilah keunggulan Functional Options Pattern!

Coba sendiri

package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"
)

func main() {
	reader := bufio.NewReader(os.Stdin)

	// Baca host
	host, _ := reader.ReadString('\n')
	host = strings.TrimSpace(host)

	// Baca jumlah opsi
	numOptionsStr, _ := reader.ReadString('\n')
	numOptions, _ := strconv.Atoi(strings.TrimSpace(numOptionsStr))

	// Kumpulkan opsi
	var opts []Option

	for i := 0; i < numOptions; i++ {
		optionType, _ := reader.ReadString('\n')
		optionType = strings.TrimSpace(optionType)

		switch optionType {
		case "port":
			portStr, _ := reader.ReadString('\n')
			port, _ := strconv.Atoi(strings.TrimSpace(portStr))
			// TODO: Tambahkan opsi WithPort ke opts
			_ = port // Hapus baris ini saat kamu mengimplementasikannya

		case "credentials":
			username, _ := reader.ReadString('\n')
			username = strings.TrimSpace(username)
			password, _ := reader.ReadString('\n')
			password = strings.TrimSpace(password)
			// TODO: Tambahkan opsi WithCredentials ke opts
			_, _ = username, password // Hapus baris ini saat kamu mengimplementasikannya

		case "maxconn":
			maxStr, _ := reader.ReadString('\n')
			maxConn, _ := strconv.Atoi(strings.TrimSpace(maxStr))
			// TODO: Tambahkan opsi WithMaxConnections ke opts
			_ = maxConn // Hapus baris ini saat kamu mengimplementasikannya

		case "timeout":
			timeoutStr, _ := reader.ReadString('\n')
			timeout, _ := strconv.Atoi(strings.TrimSpace(timeoutStr))
			// TODO: Tambahkan opsi WithTimeout ke opts
			_ = timeout // Hapus baris ini saat kamu mengimplementasikannya
		}
	}

	// TODO: Buat DBConnection menggunakan NewDBConnection dengan host dan opts
	// TODO: Cetak string koneksi menggunakan method ConnectionString()

	_ = opts // Hapus baris ini saat kamu mengimplementasikannya
	fmt.Println("TODO: Print connection string here")
}
quiz iconUji dirimu

Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.

Semua pelajaran di Pemrograman Berorientasi Objek

Latihan sendiri: Compiler Go online