📚 Series: Belajar Golang dari Nol sampai Deploy
← Part 2 Part 3: Fungsi, Struct, Slice & Map Part 4: Interface & Error →

Fungsi di Go

Fungsi di Go sangat powerful — bisa return lebih dari satu nilai, fitur yang jarang ada di bahasa lain.

// Fungsi dasar
func sapa(nama string) string {
    return "Halo, " + nama + "!"
}

// Fungsi dengan multiple return value
func bagi(a, b float64) (float64, error) {
    if b == 0 {
        return 0, fmt.Errorf("tidak bisa dibagi nol")
    }
    return a / b, nil
}

// Named return values
func hitungLuasKeliling(r float64) (luas, keliling float64) {
    luas = 3.14 * r * r
    keliling = 2 * 3.14 * r
    return // naked return
}

func main() {
    fmt.Println(sapa("Andi")) // Halo, Andi!

    hasil, err := bagi(10, 3)
    if err != nil {
        fmt.Println("Error:", err)
    } else {
        fmt.Printf("%.2f\n", hasil) // 3.33
    }

    l, k := hitungLuasKeliling(7)
    fmt.Println(l, k)
}

Variadic Function

// Menerima jumlah argumen yang tidak terbatas
func jumlah(angka ...int) int {
    total := 0
    for _, n := range angka {
        total += n
    }
    return total
}

fmt.Println(jumlah(1, 2, 3))           // 6
fmt.Println(jumlah(10, 20, 30, 40, 50)) // 150

// Spread slice ke variadic function
nums := []int{1, 2, 3, 4, 5}
fmt.Println(jumlah(nums...)) // 15

Slice

Slice seperti array tapi ukurannya dinamis — ini yang paling sering kamu pakai!

// Deklarasi slice
buah := []string{"apel", "mangga", "jeruk"}
angka := []int{1, 2, 3, 4, 5}

// Append (tambah elemen)
buah = append(buah, "pisang")
buah = append(buah, "melon", "pepaya") // bisa append banyak sekaligus
fmt.Println(buah) // [apel mangga jeruk pisang melon pepaya]

// Slicing (ambil sebagian)
fmt.Println(angka[1:3])  // [2 3] (index 1 sampai 2)
fmt.Println(angka[:3])   // [1 2 3] (dari awal sampai index 2)
fmt.Println(angka[2:])   // [3 4 5] (dari index 2 sampai akhir)

// Panjang dan kapasitas
fmt.Println(len(buah), cap(buah))

// make() untuk buat slice dengan panjang tertentu
kosong := make([]int, 5)       // [0 0 0 0 0]
berkapasitas := make([]int, 3, 10) // len=3, cap=10

// Hapus elemen (Go tidak punya built-in delete untuk slice)
i := 2
buah = append(buah[:i], buah[i+1:]...) // hapus index 2

Map

Map adalah pasangan key-value, seperti dictionary di Python atau object di JavaScript.

// Deklarasi map
nilai := map[string]int{
    "Andi": 90,
    "Budi": 75,
    "Cici": 85,
}

// Akses nilai
fmt.Println(nilai["Andi"]) // 90

// Cek apakah key ada
skor, ada := nilai["Dedi"]
if ada {
    fmt.Println("Dedi:", skor)
} else {
    fmt.Println("Dedi tidak ditemukan")
}

// Tambah / update
nilai["Dedi"] = 88
nilai["Andi"] = 95 // update

// Hapus
delete(nilai, "Budi")

// Iterasi
for nama, skor := range nilai {
    fmt.Printf("%s: %d\n", nama, skor)
}

// make() untuk map kosong
cache := make(map[string]string)

Struct

Go tidak punya class, tapi punya struct yang lebih simpel dan powerful.

// Definisi struct
type Task struct {
    ID        int
    Title     string
    Completed bool
    CreatedAt string
}

// Membuat instance
t1 := Task{
    ID:        1,
    Title:     "Belajar Go",
    Completed: false,
    CreatedAt: "2026-01-01",
}

// Short notation (urutan sesuai field)
t2 := Task{2, "Deploy API", true, "2026-01-02"}

// Akses dan modifikasi field
fmt.Println(t1.Title)
t1.Completed = true

// Pointer ke struct
t3 := &Task{ID: 3, Title: "Buat Unit Test"}
t3.Title = "Update Unit Test" // Go otomatis dereference

Method pada Struct

type Task struct {
    ID        int
    Title     string
    Completed bool
}

// Method dengan value receiver
func (t Task) String() string {
    status := "[ ]"
    if t.Completed {
        status = "[✓]"
    }
    return fmt.Sprintf("%s #%d: %s", status, t.ID, t.Title)
}

// Method dengan pointer receiver (bisa modifikasi struct)
func (t *Task) Complete() {
    t.Completed = true
}

func main() {
    task := Task{ID: 1, Title: "Belajar Go"}
    fmt.Println(task)     // [ ] #1: Belajar Go
    task.Complete()
    fmt.Println(task)     // [✓] #1: Belajar Go
}

Anonymous Struct & Struct Embedding

// Anonymous struct (untuk data sementara)
config := struct {
    Host string
    Port int
}{
    Host: "localhost",
    Port: 8080,
}

// Embedding (komposisi, bukan inheritance)
type User struct {
    ID   int
    Name string
}

type AdminUser struct {
    User             // embed User
    Permissions []string
}

admin := AdminUser{
    User:        User{ID: 1, Name: "Adam"},
    Permissions: []string{"create", "delete"},
}

fmt.Println(admin.Name) // Akses langsung field dari User

Checklist Progress

← Part 2 Part 4: Interface & Error →