Python

Go (Golang) untuk Pemula: Panduan Lengkap

Tutorial lengkap belajar Go (Golang) dari nol β€” instalasi, variabel, tipe data, fungsi, struct, interface, dan quiz interaktif dengan contoh kode praktis

1. πŸ”΅ Pengenalan Go (Golang)

Go (atau Golang) adalah bahasa pemrograman open source yang dikembangkan oleh Google pada tahun 2007 dan dirilis secara publik pada tahun 2009. Go dirancang oleh Robert Griesemer, Rob Pike, dan Ken Thompson β€” tiga tokoh legendaris di dunia pemrograman.

Go dirancang untuk menjadi bahasa yang sederhana, cepat, dan efisien. Go sangat populer untuk pengembangan backend, microservices, DevOps tools, cloud computing, dan infrastruktur jaringan. Banyak perusahaan besar seperti Google, Docker, Kubernetes, dan Netflix menggunakan Go.

Mengapa Memilih Go?

Keunggulan Penjelasan
Sintaks SederhanaHanya ~25 keyword, mudah dipelajari dan dibaca
Kompilasi CepatCompile ke binary native, sangat cepat dieksekusi
Concurrency Built-inGoroutines dan channels untuk paralelisme mudah
Garbage CollectionManajemen memori otomatis, tidak perlu manual free
Cross-PlatformBisa compile ke berbagai OS dan arsitektur
Standar Library KuatHTTP, JSON, file I/O, crypto β€” semua built-in
Statically TypedType safety saat compile, mengurangi bug runtime
Gratis & Open SourceDikembangkan secara terbuka oleh komunitas global

Go vs Bahasa Lain

Aspek Go Python Java
TipeCompiledInterpretedCompiled + Interpreted
TypingStaticDynamicStatic
Sintaks🟒 Sangat Sederhana🟒 MudahπŸ”΄ Verbose
Kecepatan🟒 Sangat Cepat🟑 Lambat🟒 Cepat
Concurrency🟒 Goroutines🟑 GIL Limitasi🟑 Threads
Cocok untukBackend, Cloud, DevOpsAI, Data, OtomasiEnterprise, Android
Diagram: Ekosistem Go
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                   EKOSISTEM GO                        β”‚
β”‚                                                       β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
β”‚  β”‚ Backend  β”‚  β”‚ Cloud &  β”‚  β”‚  DevOps &        β”‚    β”‚
β”‚  β”‚ API      β”‚  β”‚ Infra    β”‚  β”‚  Tools           β”‚    β”‚
β”‚  β”‚ Gin      β”‚  β”‚ Docker   β”‚  β”‚  Terraform       β”‚    β”‚
β”‚  β”‚ Echo     β”‚  β”‚ K8s      β”‚  β”‚  Prometheus      β”‚    β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
β”‚                                                       β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
β”‚  β”‚ CLI      β”‚  β”‚Network   β”‚  β”‚  Database        β”‚    β”‚
β”‚  β”‚ Cobra    β”‚  β”‚ gRPC     β”‚  β”‚  CockroachDB     β”‚    β”‚
β”‚  β”‚ Bubbleteaβ”‚  β”‚ Protobuf β”‚  β”‚  InfluxDB        β”‚    β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

2. Instalasi Go

Go bisa diinstal di Windows, macOS, dan Linux. Berikut panduan instalasi untuk masing-masing platform.

Instalasi di Windows

Windows
# 1. Kunjungi https://go.dev/dl/
# 2. Download installer Windows (.msi) terbaru
# 3. Jalankan installer dan ikuti wizard
# 4. Go akan otomatis ditambahkan ke PATH

# Verifikasi instalasi di Command Prompt / PowerShell:
go version
# Output: go version go1.22.4 windows/amd64

# Atau gunakan winget:
winget install GoLang.Go

# Atau gunakan Chocolatey:
choco install golang

Instalasi di macOS

macOS
# Gunakan Homebrew (recommended):
brew install go

# Atau download dari https://go.dev/dl/
# Pilih file .pkg untuk macOS dan jalankan installer

# Verifikasi:
go version
# Output: go version go1.22.4 darwin/arm64

# Set GOPATH (opsional, modern Go pakai modules):
echo 'export GOPATH=$HOME/go' >> ~/.zshrc
echo 'export PATH=$PATH:$GOPATH/bin' >> ~/.zshrc
source ~/.zshrc

Instalasi di Linux (Ubuntu/Debian)

Linux
# Cara 1: Install dari repository
sudo apt update && sudo apt install golang -y

# Cara 2: Install dari source (versi terbaru)
wget https://go.dev/dl/go1.22.4.linux-amd64.tar.gz
sudo rm -rf /usr/local/go
sudo tar -C /usr/local -xzf go1.22.4.linux-amd64.tar.gz

# Tambahkan ke PATH
echo 'export PATH=$PATH:/usr/local/go/bin' >> ~/.bashrc
source ~/.bashrc

# Verifikasi:
go version
# Output: go version go1.22.4 linux/amd64

go env GOPATH
# Output: /home/user/go

Program Go Pertama: Hello World

Go β€” hello.go
package main

import "fmt"

func main() {
    fmt.Println("Halo, dunia!")
    fmt.Println("Selamat datang di Go! 🐝")
    fmt.Println("Nama saya: BeebaneLabs")
}

// Menjalankan dari terminal:
// go run hello.go
//
// Output:
// Halo, dunia!
// Selamat datang di Go! 🐝
// Nama saya: BeebaneLabs
//
// Compile ke binary:
// go build hello.go
// ./hello (Linux/Mac) atau hello.exe (Windows)

Struktur Proyek Go

Terminal
# Inisialisasi module baru
mkdir my-project
cd my-project
go mod init my-project

# Struktur folder:
my-project/
β”œβ”€β”€ go.mod          # Module definition & dependencies
β”œβ”€β”€ go.sum          # Checksum dependencies
β”œβ”€β”€ main.go         # Entry point program
β”œβ”€β”€ helpers/        # Package helpers
β”‚   └── utils.go
└── models/         # Package models
    └── user.go

# Menjalankan project:
go run .

# Build binary:
go build -o myapp .
πŸ’‘ Tips

Gunakan Go Playground di go.dev/play untuk mencoba kode Go langsung di browser tanpa perlu install apa pun. Sangat berguna untuk eksperimen cepat dan berbagi kode.

3. Variabel dan Tipe Data

Go adalah bahasa statically typed, artinya tipe data harus ditentukan saat deklarasi. Namun, Go memiliki fitur type inference dengan := sehingga tidak perlu selalu menulis tipe secara eksplisit.

Deklarasi Variabel

Go β€” Variabel
package main

import "fmt"

func main() {
    // Deklarasi eksplisit dengan var
    var nama string = "Budi Santoso"
    var umur int = 25
    var tinggi float64 = 175.5
    var isAktif bool = true

    fmt.Println(nama, umur, tinggi, isAktif)

    // Type inference β€” Go mendeteksi tipe otomatis
    var kota = "Jakarta"     // string
    var ipk = 3.85           // float64
    var lulusan = true       // bool
    fmt.Println(kota, ipk, lulusan)

    // Short declaration (hanya di dalam fungsi)
    pesan := "Hello, Go!"
    angka := 42
    desimal := 3.14
    fmt.Println(pesan, angka, desimal)

    // Deklarasi multiple
    x, y, z := 1, 2, 3
    fmt.Println(x, y, z) // 1 2 3

    // Zero values β€” nilai default jika tidak diinisialisasi
    var a int       // 0
    var b float64   // 0
    var c string    // "" (string kosong)
    var d bool      // false
    fmt.Println(a, b, c, d)

    // Aturan penamaan:
    // βœ… namaLengkap, umurPengguna, _private
    // ❌ 2angka, nama-lengkap, func, var (reserved words)
    // Eksported (kapital awal): NamaPublic
    // Unexported (huruf kecil awal): namaPrivate
}

Tipe Data Dasar

Tipe Contoh Penjelasan
int42, -10, 0Bilangan bulat (platform-dependent: 32/64 bit)
int8, int16, int32, int64int64(100)Bilangan bulat dengan ukuran spesifik
uint42, 0Unsigned integer (hanya positif)
float32, float643.14, -0.5Bilangan desimal
string"hello"String / teks (immutable)
booltrue, falseBoolean / logika benar-salah
bytebyte('A')Alias untuk uint8
runerune('ε­—')Alias untuk int32 (Unicode code point)

String dan Konversi Tipe

Go β€” String & Konversi
package main

import (
    "fmt"
    "strconv"
)

func main() {
    // String operations
    nama := "BeebaneLabs"
    sapa := "Halo, " + nama + "!"   // Concatenation
    fmt.Println(sapa)
    fmt.Println(len(nama))           // 11 (panjang byte)
    fmt.Println(nama[0])             // 66 (ASCII 'B')

    // String formatting
    umur := 25
    fmt.Sprintf("Umur: %d tahun", umur)
    fmt.Sprintf("Nama: %s, Umur: %d", nama, umur)

    // Konversi tipe data
    // Int β†’ String
    angka := 42
    angkaStr := strconv.Itoa(angka)
    fmt.Println(angkaStr) // "42"

    // String β†’ Int
    str := "100"
    hasil, err := strconv.Atoi(str)
    if err == nil {
        fmt.Println(hasil) // 100
    }

    // Float β†’ String
    pi := 3.14159
    piStr := strconv.FormatFloat(pi, 'f', 2, 64)
    fmt.Println(piStr) // "3.14"

    // String β†’ Float
    f, _ := strconv.ParseFloat("2.718", 64)
    fmt.Println(f) // 2.718

    // Type conversion (eksplisit)
    var x int = 42
    var y float64 = float64(x)   // int β†’ float64
    var z int = int(y)            // float64 β†’ int
    fmt.Println(x, y, z)

    // iota β€” auto-increment constant
    const (
        Minggu = iota  // 0
        Senin           // 1
        Selasa          // 2
        Rabu            // 3
    )
    fmt.Println(Minggu, Senin, Selasa, Rabu) // 0 1 2 3
}

4. Konstanta dan Operator

Konstanta adalah nilai yang tidak bisa diubah setelah didefinisikan. Go mendukung konstanta dengan const dan iota untuk enumerasi.

Konstanta

Go β€” Konstanta
package main

import "fmt"

// Konstanta di package level
const Pi = 3.14159
const AppName = "BeebaneLabs"

func main() {
    // Konstanta di fungsi
    const MaxUsers = 100
    const Greeting = "Selamat datang!"

    fmt.Println(Pi, AppName, MaxUsers, Greeting)

    // Multiple konstanta
    const (
        StatusOK       = 200
        StatusNotFound = 404
        StatusError    = 500
    )

    // Konstanta typed
    const pi float64 = 3.14159
    const e float64 = 2.71828

    // Konstanta untyped (lebih fleksibel)
    const x = 42        // bisa dipakai sebagai int atau float
    var y float64 = x   // OK! Tidak perlu casting
    fmt.Println(y)      // 42

    // iota β€” auto-increment untuk enumerasi
    const (
        Merah  = iota  // 0
        Kuning          // 1
        Hijau           // 2
    )
    fmt.Println(Merah, Kuning, Hijau) // 0 1 2

    // iota dengan ekspresi
    const (
        _  = iota             // 0 (skip)
        KB = 1 << (10 * iota) // 1 << 10 = 1024
        MB = 1 << (10 * iota) // 1 << 20 = 1048576
        GB = 1 << (10 * iota) // 1 << 30 = 1073741824
    )
    fmt.Println(KB, MB, GB)
}

Operator

Go β€” Operator
package main

import "fmt"

func main() {
    // Operator aritmatika
    a, b := 15, 4
    fmt.Println(a + b)  // 19 (penjumlahan)
    fmt.Println(a - b)  // 11 (pengurangan)
    fmt.Println(a * b)  // 60 (perkalian)
    fmt.Println(a / b)  // 3  (pembagian integer)
    fmt.Println(a % b)  // 3  (modulus/sisa bagi)

    // Catatan: pembagian integer!
    // 15 / 4 = 3 (bukan 3.75)
    fmt.Println(float64(a) / float64(b)) // 3.75

    // Increment/Decrement (hanya postfix!)
    x := 10
    x++    // x = x + 1 β†’ 11
    x--    // x = x - 1 β†’ 10
    // ❌ ++x tidak ada di Go!

    // Shortcut assignment
    y := 20
    y += 5   // 25
    y -= 3   // 22
    y *= 2   // 44
    y /= 4   // 11
    fmt.Println(y)

    // Operator perbandingan
    fmt.Println(10 == 10)  // true
    fmt.Println(10 != 5)   // true
    fmt.Println(10 > 5)    // true
    fmt.Println(10 < 5)    // false
    fmt.Println(10 >= 10)  // true
    fmt.Println(10 <= 5)   // false

    // Operator logika
    umur := 25
    punyaSIM := true
    bisaKemudi := umur >= 17 && punyaSIM
    fmt.Println(bisaKemudi) // true

    fmt.Println(umur < 18 || punyaSIM) // true
    fmt.Println(!punyaSIM)             // false

    // Bitwise operators
    fmt.Println(0b1010 & 0b1100)  // AND: 8 (0b1000)
    fmt.Println(0b1010 | 0b1100)  // OR:  14 (0b1110)
    fmt.Println(0b1010 ^ 0b1100)  // XOR: 6 (0b0110)
    fmt.Println(1 << 3)           // Shift left: 8
    fmt.Println(16 >> 2)          // Shift right: 4
}

5. Kontrol Alur

Go memiliki kontrol alur yang sederhana. Tidak ada while loop, tidak ada ternary operator, dan kurung kurawal {} wajib digunakan untuk blok kode.

If-Else

Go β€” If-Else
package main

import "fmt"

func main() {
    umur := 20

    // If-else dasar
    if umur >= 18 {
        fmt.Println("Kamu sudah dewasa")
    } else if umur >= 13 {
        fmt.Println("Kamu remaja")
    } else {
        fmt.Println("Kamu masih anak-anak")
    }

    // If dengan inisialisasi (short statement)
    // Variabel 'nilai' hanya bisa diakses di dalam blok if
    if nilai := 85; nilai >= 60 {
        fmt.Printf("Nilai %d: Lulus!\n", nilai)
    } else {
        fmt.Printf("Nilai %d: Tidak lulus\n", nilai)
    }

    // Switch
    hari := "Senin"
    switch hari {
    case "Senin":
        fmt.Println("Hari kerja πŸ’ͺ")
    case "Selasa", "Rabu", "Kamis":
        fmt.Println("Hari kerja biasa")
    case "Jumat":
        fmt.Println("Jumat barokah 🀲")
    case "Sabtu", "Minggu":
        fmt.Println("Weekend! πŸŽ‰")
    default:
        fmt.Println("Hari tidak valid")
    }

    // Switch tanpa kondisi (pengganti if-else chain)
    skor := 85
    switch {
    case skor >= 90:
        fmt.Println("Grade: A")
    case skor >= 80:
        fmt.Println("Grade: B")
    case skor >= 70:
        fmt.Println("Grade: C")
    default:
        fmt.Println("Grade: D")
    }

    // Type switch
    var x interface{} = "hello"
    switch v := x.(type) {
    case int:
        fmt.Printf("Integer: %d\n", v)
    case string:
        fmt.Printf("String: %s\n", v)
    case bool:
        fmt.Printf("Boolean: %t\n", v)
    default:
        fmt.Printf("Tipe lain: %T\n", v)
    }
}

For Loop (Satu-satunya Loop di Go!)

Go β€” For Loop
package main

import "fmt"

func main() {
    // For loop klasik
    for i := 0; i < 5; i++ {
        fmt.Printf("Iterasi ke-%d\n", i)
    }

    // For sebagai while
    hitungan := 0
    for hitungan < 5 {
        fmt.Printf("Hitungan: %d\n", hitungan)
        hitungan++
    }

    // Infinite loop
    counter := 0
    for {
        if counter >= 3 {
            break
        }
        fmt.Printf("Loop ke-%d\n", counter)
        counter++
    }

    // For range β€” iterasi collection
    buah := []string{"apel", "mangga", "jeruk", "pisang"}
    for index, item := range buah {
        fmt.Printf("%d. %s\n", index+1, item)
    }

    // Hanya index
    for i := range buah {
        fmt.Println(i)
    }

    // Hanya value (pakai _ untuk skip index)
    for _, item := range buah {
        fmt.Println(item)
    }

    // For range dengan string (iterasi rune)
    for i, ch := range "Go 🐝" {
        fmt.Printf("Index %d: %c (%d)\n", i, ch, ch)
    }

    // Continue β€” skip iterasi tertentu
    for i := 0; i < 10; i++ {
        if i%3 == 0 {
            continue // Lewati kelipatan 3
        }
        fmt.Print(i, " ") // 1 2 4 5 7 8
    }
    fmt.Println()
}
⚠️ Go Hanya Punya For Loop!

Tidak ada while, do-while, atau foreach di Go. Semua bisa dilakukan dengan for. Ini adalah desain yang disengaja untuk menjaga kesederhanaan bahasa. Gunakan for dengan berbagai variasi: klasik, tanpa kondisi (while), infinite, dan range.

6. Fungsi

Fungsi di Go didefinisikan dengan keyword func. Go mendukung multiple return values, variadic arguments, dan anonymous functions (closure).

Fungsi Dasar

Go β€” Fungsi
package main

import "fmt"

// Fungsi dengan parameter dan return value
func tambah(a int, b int) int {
    return a + b
}

// Multiple return values
func hitungLuasKeliling(p, l float64) (float64, float64) {
    luas := p * l
    keliling := 2 * (p + l)
    return luas, keliling
}

// Named return values
func bagi(a, b float64) (hasil float64, err error) {
    if b == 0 {
        err = fmt.Errorf("tidak bisa dibagi nol")
        return
    }
    hasil = a / b
    return // naked return β€” mengembalikan named values
}

// Variadic function
func jumlahkan(angka ...int) int {
    total := 0
    for _, n := range angka {
        total += n
    }
    return total
}

// Fungsi sebagai parameter (callback)
func proses(data []int, fn func(int) int) []int {
    hasil := make([]int, len(data))
    for i, v := range data {
        hasil[i] = fn(v)
    }
    return hasil
}

func main() {
    // Fungsi dasar
    fmt.Println(tambah(5, 3)) // 8

    // Multiple return
    luas, keliling := hitungLuasKeliling(10, 5)
    fmt.Printf("Luas: %.0f, Keliling: %.0f\n", luas, keliling)

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

    // Variadic
    fmt.Println(jumlahkan(1, 2, 3, 4, 5)) // 15
    angka := []int{10, 20, 30}
    fmt.Println(jumlahkan(angka...)) // 60 (unpack slice)

    // Anonymous function / closure
    kuadrat := func(x int) int {
        return x * x
    }
    fmt.Println(kuadrat(5)) // 25

    // Fungsi sebagai parameter
    data := []int{1, 2, 3, 4, 5}
    hasil2 := proses(data, func(x int) int {
        return x * 2
    })
    fmt.Println(hasil2) // [2 4 6 8 10]

    // Deferred function β€” dieksekusi saat fungsi selesai
    fmt.Println("Mulai")
    defer fmt.Println("Ini dijalankan terakhir")
    fmt.Println("Selesai")
    // Output: Mulai β†’ Selesai β†’ Ini dijalankan terakhir
}
πŸ’‘ Tips: Defer

defer sangat berguna untuk membersihkan resource (menutup file, database connection, dll). Deferred calls dijalankan dalam urutan LIFO (Last In, First Out) saat fungsi selesai, bahkan jika terjadi panic.

7. Array, Slice, dan Map

Go memiliki tiga tipe collection utama: Array (fixed size), Slice (dynamic size), dan Map (key-value pairs).

Array dan Slice

Go β€” Array & Slice
package main

import "fmt"

func main() {
    // Array β€” ukuran tetap, bagian dari tipe
    var angka [5]int = [5]int{10, 20, 30, 40, 50}
    fmt.Println(angka)     // [10 20 30 40 50]
    fmt.Println(angka[0])  // 10
    fmt.Println(len(angka)) // 5

    // Array dengan auto-length
    buah := [...]string{"apel", "mangga", "jeruk"}
    fmt.Println(len(buah)) // 3

    // Slice β€” array dinamis (paling sering dipakai!)
    warna := []string{"merah", "hijau", "biru"}
    fmt.Println(warna)           // [merah hijau biru]
    fmt.Println(len(warna))      // 3
    fmt.Println(cap(warna))      // 3

    // Tambah elemen dengan append
    warna = append(warna, "kuning")
    warna = append(warna, "ungu", "pink")
    fmt.Println(warna) // [merah hijau biru kuning ungu pink]

    // Gabung dua slice
    a := []int{1, 2, 3}
    b := []int{4, 5, 6}
    c := append(a, b...)
    fmt.Println(c) // [1 2 3 4 5 6]

    // Slicing
    fmt.Println(c[1:4])  // [2 3 4]
    fmt.Println(c[:3])   // [1 2 3]
    fmt.Println(c[3:])   // [4 5 6]

    // Make β€” buat slice dengan kapasitas awal
    data := make([]int, 0, 10) // len=0, cap=10
    for i := 0; i < 5; i++ {
        data = append(data, i*10)
    }
    fmt.Println(data)        // [0 10 20 30 40]
    fmt.Println(len(data))   // 5
    fmt.Println(cap(data))   // 10

    // Copy slice
    src := []int{1, 2, 3, 4, 5}
    dst := make([]int, len(src))
    copied := copy(dst, src)
    fmt.Println(dst, copied) // [1 2 3 4 5] 5

    // 2D Slice (matrix)
    matrix := [][]int{
        {1, 2, 3},
        {4, 5, 6},
        {7, 8, 9},
    }
    for _, row := range matrix {
        fmt.Println(row)
    }
}

Map

Go β€” Map
package main

import "fmt"

func main() {
    // Membuat map
    mahasiswa := map[string]int{
        "Budi": 85,
        "Ani":  92,
        "Dimas": 78,
    }
    fmt.Println(mahasiswa)

    // Mengakses nilai
    fmt.Println(mahasiswa["Budi"]) // 85

    // Cek apakah key ada
    nilai, ok := mahasiswa["Sari"]
    if ok {
        fmt.Println("Nilai Sari:", nilai)
    } else {
        fmt.Println("Sari tidak ditemukan")
    }

    // Menambah/mengubah
    mahasiswa["Sari"] = 88    // Tambah baru
    mahasiswa["Budi"] = 90    // Ubah yang sudah ada

    // Menghapus
    delete(mahasiswa, "Dimas")

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

    // Map dengan make
    data := make(map[string][]string)
    data["buah"] = []string{"apel", "mangga"}
    data["sayur"] = []string{"bayam", "wortel"}
    fmt.Println(data)

    // Nested map
    sekolah := map[string]map[string]int{
        "TI": {"Matematika": 85, "Algoritma": 90},
        "SI": {"Ekonomi": 80, "Manajemen": 88},
    }
    fmt.Println(sekolah["TI"]["Algoritma"]) // 90

    // Hitung panjang
    fmt.Println(len(mahasiswa)) // jumlah key-value pairs
}

8. Struct

Struct adalah kumpulan field yang membentuk satu tipe data baru. Struct di Go mirip dengan class di bahasa OOP, tapi Go tidak memiliki class atau inheritance β€” menggunakan composition.

Go β€” Struct
package main

import "fmt"

// Definisi struct
type Mahasiswa struct {
    Nama    string
    NIM     string
    IPK     float64
    Aktif   bool
}

// Struct dengan embedded struct
type Alamat struct {
    Jalan string
    Kota  string
    KodePos string
}

type Pengguna struct {
    Nama   string
    Email  string
    Alamat Alamat  // composition
}

// Method pada struct (receiver)
func (m Mahasiswa) Info() string {
    return fmt.Sprintf("%s (%s) - IPK: %.2f", m.Nama, m.NIM, m.IPK)
}

// Pointer receiver β€” bisa mengubah nilai struct
func (m *Mahasiswa) SetIPK(ipk float64) {
    if ipk >= 0 && ipk <= 4.0 {
        m.IPK = ipk
    }
}

// Constructor pattern
func NewMahasiswa(nama, nim string, ipk float64) *Mahasiswa {
    return &Mahasiswa{
        Nama:  nama,
        NIM:   nim,
        IPK:   ipk,
        Aktif: true,
    }
}

func main() {
    // Membuat struct instance
    budi := Mahasiswa{
        Nama:  "Budi Santoso",
        NIM:   "2024001",
        IPK:   3.85,
        Aktif: true,
    }
    fmt.Println(budi)
    fmt.Println(budi.Nama) // Akses field

    // Struct literal tanpa nama field
    ani := Mahasiswa{"Ani Widiastuti", "2024002", 3.90, true}
    fmt.Println(ani)

    // Constructor pattern
    dimas := NewMahasiswa("Dimas Pratama", "2024003", 3.50)
    fmt.Println(dimas.Info()) // Dimas Pratama (2024003) - IPK: 3.50

    // Pointer receiver β€” ubah nilai
    dimas.SetIPK(3.75)
    fmt.Println(dimas.Info()) // Dimas Pratama (2024003) - IPK: 3.75

    // Embedded struct
    user := Pengguna{
        Nama:  "Sari",
        Email: "sari@email.com",
        Alamat: Alamat{
            Jalan:   "Jl. Sudirman No. 10",
            Kota:    "Jakarta",
            KodePos: "12190",
        },
    }
    fmt.Printf("%s tinggal di %s, %s\n", user.Nama, user.Alamat.Kota, user.Alamat.Jalan)

    // Slice of structs
    semua := []Mahasiswa{budi, ani, *dimas}
    for _, m := range semua {
        fmt.Println(m.Info())
    }

    // Anonymous struct
    config := struct {
        Host string
        Port int
    }{
        Host: "localhost",
        Port: 8080,
    }
    fmt.Println(config)
}

9. Interface

Interface di Go didefinisikan secara implisit β€” tidak perlu kata kunci implements. Jika suatu struct memiliki semua method yang didefinisikan di interface, maka secara otomatis struct tersebut mengimplementasi interface tersebut.

Go β€” Interface
package main

import (
    "fmt"
    "math"
)

// Interface definition
type Bentuk interface {
    Luas() float64
    Keliling() float64
    Nama() string
}

// Struct Lingkaran
type Lingkaran struct {
    Radius float64
}

func (l Lingkaran) Luas() float64 {
    return math.Pi * l.Radius * l.Radius
}

func (l Lingkaran) Keliling() float64 {
    return 2 * math.Pi * l.Radius
}

func (l Lingkaran) Nama() string {
    return "Lingkaran"
}

// Struct PersegiPanjang
type PersegiPanjang struct {
    Panjang, Lebar float64
}

func (pp PersegiPanjang) Luas() float64 {
    return pp.Panjang * pp.Lebar
}

func (pp PersegiPanjang) Keliling() float64 {
    return 2 * (pp.Panjang + pp.Lebar)
}

func (pp PersegiPanjang) Nama() string {
    return "Persegi Panjang"
}

// Fungsi yang menerima interface
func cetakInfo(b Bentuk) {
    fmt.Printf("%s: Luas=%.2f, Keliling=%.2f\n",
        b.Nama(), b.Luas(), b.Keliling())
}

// Empty interface β€” menerima tipe apapun
func cetakApapun(x interface{}) {
    fmt.Printf("Value: %v, Type: %T\n", x, x)
}

func main() {
    // Implicit implementation β€” tidak perlu "implements"
    lingkaran := Lingkaran{Radius: 7}
    pp := PersegiPanjang{Panjang: 10, Lebar: 5}

    cetakInfo(lingkaran) // Lingkaran: Luas=153.94, Keliling=43.98
    cetakInfo(pp)        // Persegi Panjang: Luas=50.00, Keliling=30.00

    // Slice of interface
    bentuk := []Bentuk{lingkaran, pp}
    for _, b := range bentuk {
        cetakInfo(b)
    }

    // Empty interface (any) β€” tipe data apapun
    cetakApapun(42)
    cetakApapun("hello")
    cetakApapun(true)
    cetakApapun([]int{1, 2, 3})

    // Type assertion
    var x interface{} = "hello"
    s, ok := x.(string)
    if ok {
        fmt.Println("String:", s)
    }

    // Nil interface
    var b Bentuk
    if b == nil {
        fmt.Println("Interface kosong")
    }
}
πŸ“‹ Interface di Go vs OOP

Di Java/C#, Anda harus mendeklarasikan class implements interface secara eksplisit. Di Go, ini terjadi secara implisit β€” jika struct memiliki semua method yang sesuai, otomatis mengimplementasi interface. Ini membuat kode lebih fleksibel dan mengurangi coupling antar package.

10. Error Handling

Go tidak memiliki try-catch. Error handling dilakukan dengan mengembalikan error sebagai return value. Ini memaksa developer untuk selalu menangani error secara eksplisit.

Go β€” Error Handling
package main

import (
    "errors"
    "fmt"
    "strconv"
)

// Membuat custom error
var ErrDivByZero = errors.New("pembagian dengan nol")
var ErrNegativeValue = errors.New("nilai tidak boleh negatif")

// Fungsi yang mengembalikan error
func bagi(a, b float64) (float64, error) {
    if b == 0 {
        return 0, ErrDivByZero
    }
    return a / b, nil
}

// Custom error type
type ValidationError struct {
    Field   string
    Message string
}

func (e *ValidationError) Error() string {
    return fmt.Sprintf("validasi gagal pada '%s': %s", e.Field, e.Message)
}

func validateAge(umur int) error {
    if umur < 0 {
        return &ValidationError{
            Field:   "umur",
            Message: "tidak boleh negatif",
        }
    }
    if umur > 150 {
        return &ValidationError{
            Field:   "umur",
            Message: "tidak valid (> 150)",
        }
    }
    return nil
}

func main() {
    // Error handling pattern β€” cek setiap error
    hasil, err := bagi(10, 0)
    if err != nil {
        fmt.Println("Error:", err)
        // Output: Error: pembagian dengan nol
    } else {
        fmt.Printf("Hasil: %.2f\n", hasil)
    }

    // Error dari standard library
    angka, err := strconv.Atoi("abc")
    if err != nil {
        fmt.Println("Parse error:", err)
        // Output: Parse error: strconv.Atoi: parsing "abc": invalid syntax
    } else {
        fmt.Println(angka)
    }

    // Custom error type
    err = validateAge(-5)
    if err != nil {
        // Type assertion untuk mendapatkan detail error
        var ve *ValidationError
        if errors.As(err, &ve) {
            fmt.Printf("Field: %s, Pesan: %s\n", ve.Field, ve.Message)
        }
    }

    // errors.Is β€” cek error tertentu
    _, err = bagi(10, 0)
    if errors.Is(err, ErrDivByZero) {
        fmt.Println("Error: dibagi nol!")
    }

    // Panic dan Recover
    // Panic = error fatal yang menghentikan program
    // Recover = menangkap panic agar program tetap jalan
    func() {
        defer func() {
            if r := recover(); r != nil {
                fmt.Println("Recovered from panic:", r)
            }
        }()
        fmt.Println("Normal execution")
        // panic("Something went wrong!") // Uncomment untuk test
        fmt.Println("Still running")
    }()

    fmt.Println("Program selesai βœ…")
}

11. Go Modules

Go Modules adalah sistem dependency management resmi Go (sejak Go 1.11). Modules memungkinkan Anda mengelola library pihak ketiga dengan mudah.

Terminal β€” Go Modules
# Inisialisasi module baru
mkdir my-api && cd my-api
go mod init github.com/username/my-api

# File go.mod akan dibuat:
# module github.com/username/my-api
# go 1.22

# Install dependency
go get github.com/gin-gonic/gin
go get gorm.io/gorm

# Tambahkan ke source code:
# import "github.com/gin-gonic/gin"

# Download semua dependencies
go mod download

# Tidy β€” hapus unused, tambah missing
go mod tidy

# Lihat semua dependencies
go list -m all

# Update dependency ke versi terbaru
go get -u github.com/gin-gonic/gin

# Vendor dependencies (simpan lokal)
go mod vendor

# Common commands:
go run .               # Jalankan program
go build .             # Compile binary
go test ./...          # Jalankan semua test
go vet ./...           # Cek kesalahan kode
go fmt ./...           # Format kode
go doc fmt.Println     # Lihat dokumentasi
πŸ’‘ Tips

Selalu jalankan go mod tidy setelah mengubah import. Gunakan go vet untuk mendeteksi bug umum, dan golangci-lint untuk analisis kode yang lebih mendalam. Format kode otomatis dengan gofmt atau goimports.

12. Quiz: Uji Pemahamanmu!

Setelah membaca tutorial di atas, jawablah 5 pertanyaan berikut untuk menguji pemahamanmu tentang Go:

Pertanyaan 1: Bagaimana cara mendeklarasikan variabel dengan type inference di Go?

a) var x := 10
b) x := 10
c) let x = 10
d) int x = 10

Pertanyaan 2: Apa satu-satunya looping construct di Go?

a) while
b) for
c) do-while
d) foreach

Pertanyaan 3: Apa perbedaan utama antara Array dan Slice di Go?

a) Array lebih cepat dari Slice
b) Array ukuran tetap, Slice ukuran dinamis
c) Slice hanya bisa menyimpan string
d) Tidak ada perbedaan

Pertanyaan 4: Bagaimana interface di Go berbeda dari bahasa OOP lain?

a) Interface di Go harus di-declare di awal file
b) Interface di Go diimplementasikan secara implisit (tidak perlu implements)
c) Interface di Go tidak bisa berisi method
d) Interface di Go hanya bisa digunakan dengan pointer

Pertanyaan 5: Apa output dari kode ini? fmt.Println(15 / 4)

a) 3.75
b) 3
c) 4
d) Error
πŸ” Zoom
100%
🎨 Tema