Menu
CoddyTech

Gambaran Umum Pembuatan Kode

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

Code generation adalah alternatif untuk reflection yang membuat kode sumber Go saat compile, bukan memeriksa tipe saat runtime. Pendekatan ini memberikan keamanan tipe dan performa yang lebih baik, sekaligus mengurangi kode boilerplate yang berulang.

Go menyediakan perintah go generate untuk mengotomatiskan pembuatan kode. Kamu menempatkan direktif komentar khusus di file sumbermu, lalu menjalankan go generate untuk mengeksekusi alat yang ditentukan:

//go:generate stringer -type=Status

type Status int

const (
    Pending Status = iota
    Active
    Completed
)

Menjalankan go generate ./... memanggil tool stringer, yang membuat file baru berisi method String() untuk tipe Status. Kode yang dihasilkan adalah kode Go biasa yang dikompilasi bersama programmu.

Alat pembuat kode yang umum dalam ekosistem Go mencakup stringer untuk method string enum, mockgen untuk membuat mock pengujian dari interface, dan protoc untuk membuat kode dari definisi Protocol Buffer. Banyak ORM dan framework API juga menggunakan pembuatan kode untuk membuat query database yang aman terhadap tipe atau kode client.

Keunggulan utamanya dibandingkan reflection adalah kode yang dihasilkan diperiksa oleh compiler. Error terdeteksi saat proses build, bukan saat runtime. Kekurangannya adalah adanya langkah build tambahan dan file hasil generasi yang perlu kamu kelola di repositorimu. Untuk pola OOP yang memerlukan implementasi berulang pada banyak tipe, code generation sering memberikan keseimbangan terbaik antara keamanan dan kemudahan.

challenge icon

Tantangan

Mudah

Mari buat generator kode yang membuat method String() untuk tipe mirip enum! Walaupun kita tidak bisa menjalankan go generate sungguhan di lingkungan ini, kamu akan menyimulasikan cara kerja alat pembuat kode: menghasilkan kode sumber Go secara terprogram berdasarkan definisi tipe.

Kamu akan mengatur kodemu dalam dua file:

  • generator.go: Buat logika pembuatan kodemu.

    Buat struct EnumType yang mewakili definisi tipe mirip enum dengan Name (string) dan Values (slice berisi string yang mewakili nama konstanta).

    Buat fungsi GenerateStringMethod(e EnumType) string yang menghasilkan kode sumber Go untuk method String(). Kode yang dihasilkan harus mengikuti pola ini:

    func (e TypeName) String() string {
        switch e {
        case Value1:
            return "Value1"
        case Value2:
            return "Value2"
        default:
            return "Unknown"
        }
    }

    Buat juga fungsi GenerateConstants(e EnumType) string yang menghasilkan deklarasi konstanta menggunakan iota:

    const (
        Value1 TypeName = iota
        Value2
        Value3
    )

    Terakhir, buat GenerateFullCode(e EnumType) string yang menggabungkan kedua output dengan komentar header yang menunjukkan bahwa ini adalah kode yang dihasilkan:

    // Code generated by enum generator. DO NOT EDIT.
    
    [constants]
    
    [string method]
  • main.go: Gunakan generator-mu untuk menghasilkan kode bagi berbagai tipe enum.

    Baca nama tipe enum, lalu baca jumlah nilai yang diikuti setiap nama nilai. Berikan informasi ini kepada generator-mu, lalu cetak kode lengkap yang dihasilkan.

Input berikut akan diberikan:

  • Baris 1: Nama tipe enum
  • Baris 2: Jumlah nilai
  • Baris-baris berikutnya: Setiap nama nilai

Contohnya, jika diberikan:

Status
3
Pending
Active
Completed

Output-mu seharusnya:

// Code generated by enum generator. DO NOT EDIT.

const (
    Pending Status = iota
    Active
    Completed
)

func (e Status) String() string {
    switch e {
    case Pending:
        return "Pending"
    case Active:
        return "Active"
    case Completed:
        return "Completed"
    default:
        return "Unknown"
    }
}

Dan jika diberikan:

Priority
2
Low
High

Output-mu seharusnya:

// Code generated by enum generator. DO NOT EDIT.

const (
    Low Priority = iota
    High
)

func (e Priority) String() string {
    switch e {
    case Low:
        return "Low"
    case High:
        return "High"
    default:
        return "Unknown"
    }
}

Latihan ini menunjukkan konsep inti di balik alat seperti stringer: menghasilkan kode yang berulang tetapi aman terhadap tipe saat compile, alih-alih menggunakan reflection saat runtime. Generator-mu menghasilkan kode Go yang valid, yang dapat disimpan ke file dan di-compile bersama bagian lain dari proyek.

Coba sendiri

package main

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

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

	// Baca nama tipe enum
	typeName, _ := reader.ReadString('\n')
	typeName = strings.TrimSpace(typeName)

	// Baca jumlah nilai
	countStr, _ := reader.ReadString('\n')
	count, _ := strconv.Atoi(strings.TrimSpace(countStr))

	// Baca nama setiap nilai
	values := make([]string, count)
	for i := 0; i < count; i++ {
		value, _ := reader.ReadString('\n')
		values[i] = strings.TrimSpace(value)
	}

	// TODO: Buat EnumType dengan data yang telah dibaca

	// TODO: Hasilkan dan cetak kode lengkap menggunakan GenerateFullCode
}
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