unisbadri.com » Python Java Golang Typescript Kotlin Ruby Rust Dart PHP

Keyword #

Go hanya punya 25 keyword — salah satu jumlah tersedikit di antara bahasa pemrograman modern. Python punya 35, Java punya 67, C++ punya lebih dari 90. Ini bukan kebetulan. Desainer Go percaya bahwa bahasa yang sederhana menghasilkan kode yang konsisten, mudah dibaca, dan lebih mudah dipelajari. Setiap keyword yang ada di Go punya alasan keberadaannya yang kuat; setiap keyword yang tidak ada juga punya alasan ketiadaannya yang sama kuatnya. Memahami semua 25 keyword Go berarti memahami fondasi dari bahasa itu sendiri.

Semua 25 Keyword Go #

break        default      func         interface    select
case         defer        go           map          struct
chan         else         goto         package      switch
const        fallthrough  if           range        type
continue     for          import       return       var

Dari 25 keyword ini, sebagian besar sudah dibahas di artikel-artikel sebelumnya dalam konteksnya masing-masing. Artikel ini mengumpulkan semuanya dalam satu tempat, mengelompokkannya berdasarkan fungsi, dan membahas nuansa yang mungkin terlewat.


Kelompok 1: Deklarasi #

Keyword yang digunakan untuk mendeklarasikan identitas baru.

package #

Setiap file Go harus dimulai dengan deklarasi package. Ini menentukan package mana file ini termasuk. Package main adalah satu-satunya yang menghasilkan executable:

package main    // executable
package config  // library
package utils   // library

import #

Menyertakan package lain untuk digunakan dalam file ini. Import yang tidak dipakai menyebabkan compile error — Go tidak mengizinkan dead import:

import "fmt"  // single import

import (      // grouped import — idiomatic
    "fmt"
    "os"
    "strings"

    "github.com/gin-gonic/gin"

    "myapp/config"
)

var #

Mendeklarasikan variabel. Bisa di level package maupun di dalam fungsi:

var x int                    // zero value: 0
var name string = "Budi"     // dengan nilai eksplisit
var active = true            // type inference
var (                        // blok var
    host = "localhost"
    port = 5432
)

const #

Mendeklarasikan konstanta yang dievaluasi saat kompilasi. Tidak bisa diisi dengan hasil fungsi runtime:

const pi = 3.14159
const maxRetry = 3
const (
    StatusOK  = 200
    StatusErr = 500
)
const (
    Read  = 1 << iota  // iota hanya valid di dalam blok const
    Write              // 2
    Admin              // 4
)

type #

Mendefinisikan tipe baru. Bisa berbasis tipe yang sudah ada atau mendefinisikan struct dan interface:

type Celsius float64               // type definition
type UserID int64                  // membuat tipe bermakna
type Handler func(http.ResponseWriter, *http.Request)  // function type

type User struct {                 // struct type
    ID   UserID
    Name string
}

type Stringer interface {          // interface type
    String() string
}

type StringMap = map[string]string // type alias (= berarti alias, bukan definisi baru)

func #

Mendefinisikan fungsi atau method:

func greet(name string) string {           // fungsi biasa
    return "Halo, " + name
}

func (u User) String() string {            // method dengan value receiver
    return u.Name
}

func (u *User) SetName(name string) {      // method dengan pointer receiver
    u.Name = name
}

func divide(a, b float64) (float64, error) { // multiple return values
    if b == 0 {
        return 0, errors.New("division by zero")
    }
    return a / b, nil
}

Kelompok 2: Kontrol Aliran #

Keyword yang mengendalikan urutan eksekusi program.

if dan else #

Percabangan kondisional. Tidak butuh kurung di sekitar kondisi, tapi kurung kurawal wajib:

if x > 0 {
    fmt.Println("positif")
} else if x < 0 {
    fmt.Println("negatif")
} else {
    fmt.Println("nol")
}

// if dengan initializer — sangat idiomatik di Go
if err := doSomething(); err != nil {
    return err
}

for #

Satu-satunya keyword perulangan di Go. Menggantikan while, do-while, dan foreach:

for i := 0; i < 10; i++ { }       // classic three-component
for condition { }                   // while-style
for { }                             // infinite loop
for i, v := range slice { }        // range over collection
for k, v := range mapData { }      // range over map
for v := range channel { }         // range over channel

switch, case, dan default #

Percabangan multi-nilai. Tidak ada fallthrough otomatis — setiap case berhenti sendiri:

switch day {
case "Saturday", "Sunday":
    fmt.Println("weekend")
default:
    fmt.Println("weekday")
}

// switch tanpa ekspresi — pengganti if-else if
switch {
case score >= 90:
    grade = "A"
case score >= 80:
    grade = "B"
default:
    grade = "C"
}

// type switch
switch v := i.(type) {
case int:
    fmt.Println("integer:", v)
case string:
    fmt.Println("string:", v)
}

break #

Menghentikan loop atau switch terdekat. Dengan label, bisa menghentikan loop luar:

for i := 0; i < 10; i++ {
    if i == 5 {
        break  // keluar dari loop
    }
}

// break dengan label
outer:
for i := 0; i < 3; i++ {
    for j := 0; j < 3; j++ {
        if i == 1 && j == 1 {
            break outer  // keluar dari loop luar
        }
    }
}

continue #

Melewatkan iterasi saat ini dan lanjut ke iterasi berikutnya. Juga bisa pakai label:

for i := 0; i < 10; i++ {
    if i%2 == 0 {
        continue  // lewati bilangan genap
    }
    fmt.Println(i)
}

fallthrough #

Melanjutkan eksekusi ke case berikutnya dalam switch — harus eksplisit, tidak ada fallthrough otomatis:

switch n {
case 1:
    fmt.Println("satu")
    fallthrough  // lanjut ke case 2
case 2:
    fmt.Println("dua atau lebih")
}

goto #

Melompat ke label yang ditandai. Sangat jarang digunakan dalam Go modern — hampir selalu ada alternatif yang lebih bersih:

func contohGoto() {
    i := 0
loop:
    if i < 5 {
        fmt.Println(i)
        i++
        goto loop  // lompat kembali ke label "loop"
    }
}

goto di Go punya batasan: tidak bisa melompat ke tempat yang menyebabkan variabel yang sudah dideklarasikan menjadi “terlewat” (untuk menjaga keamanan). Dalam praktik nyata di kode produksi, goto hampir tidak pernah dipakai — for selalu lebih ekspresif dan lebih mudah dibaca.


Kelompok 3: Fungsi dan Goroutine #

return #

Mengembalikan nilai dari fungsi. Go mendukung multiple return values:

func getUser(id int) (*User, error) {
    if id <= 0 {
        return nil, errors.New("invalid id")  // early return
    }
    // ...
    return user, nil  // happy path
}

// Naked return — hanya untuk fungsi pendek dengan named returns
func minMax(nums []int) (min, max int) {
    min, max = nums[0], nums[0]
    for _, n := range nums[1:] {
        if n < min { min = n }
        if n > max { max = n }
    }
    return  // mengembalikan min dan max
}

defer #

Menunda eksekusi statement sampai fungsi yang mengandungnya selesai. Berguna untuk resource cleanup. Beberapa defer dieksekusi LIFO (last in, first out):

func readFile(path string) error {
    f, err := os.Open(path)
    if err != nil {
        return err
    }
    defer f.Close()  // dijamin dipanggil saat readFile() selesai

    // proses file...
    return nil
}

func main() {
    defer fmt.Println("ketiga")   // dieksekusi paling akhir
    defer fmt.Println("kedua")
    defer fmt.Println("pertama")  // dieksekusi paling awal
    fmt.Println("berjalan")
}
// Output: berjalan, pertama, kedua, ketiga

go #

Memulai goroutine — fungsi yang berjalan secara concurrent dengan goroutine pemanggil. Goroutine sangat ringan (mulai ~2KB stack) dibanding OS thread:

go func() {
    fmt.Println("berjalan di goroutine baru")
}()

go processRequest(req)  // jalankan fungsi bernama sebagai goroutine

// Goroutine dengan komunikasi via channel
results := make(chan int)
go func() {
    results <- compute()
}()
fmt.Println(<-results)

Kelompok 4: Tipe Komposit #

struct #

Mendefinisikan tipe data yang mengelompokkan beberapa field. Pengganti class di Go:

type Point struct {
    X, Y float64
}

type Person struct {
    Name    string
    Age     int
    Address struct {   // anonymous nested struct
        Street string
        City   string
    }
}

// Embedding struct
type Employee struct {
    Person        // embedded — field dan method Person tersedia langsung
    Department string
    Salary    float64
}

interface #

Mendefinisikan kontrak perilaku — kumpulan method signature. Implementasi bersifat implisit (tidak perlu deklarasi implements):

type Writer interface {
    Write(p []byte) (n int, err error)
}

type ReadWriter interface {
    Reader              // komposisi interface
    Writer
}

// Empty interface — bisa menampung tipe apapun
var anything interface{} = 42
var anything2 any = "hello"  // any adalah alias interface{} sejak Go 1.18

map #

Tipe data hash map built-in. Key harus comparable:

m := map[string]int{"satu": 1, "dua": 2}
m2 := make(map[string][]string)

// map sebagai set
seen := map[string]struct{}{}

chan #

Mendefinisikan tipe channel — saluran komunikasi antar goroutine:

ch := make(chan int)         // unbuffered channel
bch := make(chan int, 10)    // buffered channel kapasitas 10
rch := make(<-chan int)      // receive-only channel
sch := make(chan<- int)      // send-only channel

// Kirim dan terima
ch <- 42        // send
v := <-ch       // receive
v, ok := <-ch   // receive dengan cek apakah channel masih terbuka

Kelompok 5: Alokasi Memory #

new #

Mengalokasikan memory untuk tipe T, menginisialisasi dengan zero value, mengembalikan *T:

p := new(int)        // *int yang menunjuk ke 0
s := new(string)     // *string yang menunjuk ke ""
u := new(User)       // *User dengan semua field zero value

// Setara dengan:
var x int
p2 := &x

Dalam praktiknya, new jarang dipakai untuk struct — &User{} lebih umum karena bisa langsung mengisi field.

make #

Membuat dan menginisialisasi slice, map, atau channel. Tidak sama dengan newmake mengembalikan nilai (bukan pointer) yang sudah siap dipakai:

s := make([]int, 5)         // slice len=5, cap=5
s2 := make([]int, 0, 100)   // slice len=0, cap=100
m := make(map[string]int)   // map siap digunakan
m2 := make(map[string]int, 50)  // map dengan hint kapasitas 50
ch := make(chan int)         // unbuffered channel
ch2 := make(chan int, 10)    // buffered channel
Perbedaan new vs make:

  new(T)  → alokasi T, return *T (pointer ke zero value)
            berlaku untuk SEMUA tipe

  make(T) → buat dan inisialisasi T, return T (bukan pointer)
            HANYA untuk slice, map, dan channel
            Hasil sudah siap dipakai (internal state terinisialisasi)

Kelompok 6: Concurrency #

select #

Seperti switch tapi untuk operasi channel. Menunggu salah satu dari beberapa operasi channel selesai, mengeksekusi case yang pertama siap:

select {
case msg := <-ch1:
    fmt.Println("dari ch1:", msg)
case msg := <-ch2:
    fmt.Println("dari ch2:", msg)
case ch3 <- "pesan":
    fmt.Println("berhasil kirim ke ch3")
case <-time.After(5 * time.Second):
    fmt.Println("timeout!")
default:
    // non-blocking: jika tidak ada channel yang siap
    fmt.Println("tidak ada yang siap")
}

select dengan semua case non-blocking (ada default) tidak akan block — langsung ke default jika tidak ada channel yang siap. Tanpa default, select block sampai minimal satu case siap.

range #

Mengiterasi slice, array, string, map, atau channel. Mengembalikan dua nilai (index/key dan value):

for i, v := range []int{1, 2, 3} { }         // slice/array
for k, v := range map[string]int{} { }        // map
for i, r := range "Hello, 世界" { }            // string (per rune)
for v := range channel { }                     // channel (sampai ditutup)
for i := range slice { }                       // hanya index

// Blank identifier untuk mengabaikan salah satu
for _, v := range slice { }   // abaikan index
for i := range slice { }      // abaikan value (shorthand)

Keyword yang Sengaja Tidak Ada di Go #

Ini sama pentingnya dengan memahami keyword yang ada. Go secara eksplisit menghilangkan beberapa keyword yang umum di bahasa lain:

TIDAK ADA di Go          | Mengapa?
─────────────────────────┼──────────────────────────────────────────────────
class                    | Digantikan struct + method. Lebih eksplisit,
                         | tidak perlu hierarki inheritance.

extends / implements     | Interface satisfaction bersifat implisit.
                         | Tidak perlu deklarasi formal.

public / private /       | Visibilitas ditentukan huruf besar/kecil:
protected                | Exported vs unexported. Lebih ringkas.

abstract / virtual       | Go tidak punya inheritance, jadi tidak perlu.
                         | Polimorfisme via interface.

try / catch / finally    | Error adalah nilai return biasa.
throw                    | Tidak ada exception mechanism tersembunyi.

while / do-while /       | Semua digantikan oleh for yang fleksibel.
foreach                  | Satu keyword untuk semua pola perulangan.

static                   | Package-level functions/variables sudah "static"
                         | dalam arti tidak perlu instance.

null / nil-keyword       | Go punya nil tapi bukan keyword — ia adalah
                         | nilai zero untuk pointer, interface, slice, dll.

async / await            | Concurrency via goroutine + channel, bukan
                         | promise/future model.

this / self              | Receiver diberi nama eksplisit oleh developer:
                         | func (u *User) Save() {}

**  (operator pangkat)   | Bukan keyword tapi operator — gunakan math.Pow()

?:  (ternary operator)   | Tidak ada. Gunakan if-else yang lebih jelas.

Ringkasan Visual Semua 25 Keyword #

DEKLARASI (6):
  package   → deklarasi package file ini
  import    → menyertakan package lain
  var       → deklarasi variabel
  const     → deklarasi konstanta (compile-time)
  type      → mendefinisikan tipe baru
  func      → mendefinisikan fungsi atau method

KONTROL ALIRAN (10):
  if        → percabangan kondisional
  else      → cabang alternatif dari if
  for       → perulangan (satu-satunya di Go)
  switch    → percabangan multi-nilai
  case      → case dalam switch atau select
  default   → case default dalam switch/select
  break     → hentikan loop atau switch
  continue  → lewati iterasi saat ini
  fallthrough → lanjut ke case berikutnya (switch)
  goto      → lompat ke label (jarang dipakai)

FUNGSI & GOROUTINE (3):
  return    → kembalikan nilai dari fungsi
  defer     → tunda eksekusi hingga fungsi selesai
  go        → mulai goroutine baru

TIPE KOMPOSIT (4):
  struct    → tipe dengan kumpulan field
  interface → kontrak perilaku (kumpulan method)
  map       → tipe hash map key-value
  chan      → tipe channel untuk komunikasi goroutine

ALOKASI (2):
  new       → alokasi zero value, return pointer
  make      → buat & inisialisasi slice/map/chan

CONCURRENCY (2):
  select    → tunggu operasi channel
  range     → iterasi koleksi

Contoh Program Lengkap #

Program berikut menggunakan hampir semua keyword Go dalam satu konteks yang kohesif — sebuah sistem antrian task concurrent sederhana:

package main  // keyword: package

import (      // keyword: import
    "fmt"
    "sync"
    "time"
)

// keyword: type, struct
type TaskStatus int

const ( // keyword: const
    StatusPending TaskStatus = iota
    StatusRunning
    StatusDone
    StatusFailed
)

func (s TaskStatus) String() string { // keyword: func
    switch s { // keyword: switch
    case StatusPending:  // keyword: case
        return "Pending"
    case StatusRunning:
        return "Running"
    case StatusDone:
        return "Done"
    default: // keyword: default
        return "Failed"
    }
}

// keyword: type, struct
type Task struct {
    ID      int
    Name    string
    Status  TaskStatus
    Result  string
    fn      func() (string, error)
}

// keyword: type, interface
type Queue interface {
    Submit(name string, fn func() (string, error)) int
    Wait()
    Results() []Task
}

// keyword: type, struct
type WorkerPool struct {
    tasks    []Task      // keyword: var tidak eksplisit (field struct)
    taskCh   chan Task   // keyword: chan
    resultCh chan Task
    wg       sync.WaitGroup
    mu       sync.Mutex
    nextID   int
}

// keyword: func
func NewWorkerPool(workers int) *WorkerPool {
    // keyword: var
    var p = &WorkerPool{
        taskCh:   make(chan Task, 100), // keyword: make
        resultCh: make(chan Task, 100),
    }

    // Jalankan workers — keyword: for, go
    for i := 0; i < workers; i++ {
        p.wg.Add(1)
        go func() { // keyword: go
            defer p.wg.Done() // keyword: defer
            for task := range p.taskCh { // keyword: for, range
                task.Status = StatusRunning

                result, err := task.fn()
                if err != nil { // keyword: if
                    task.Status = StatusFailed
                    task.Result = err.Error()
                } else { // keyword: else
                    task.Status = StatusDone
                    task.Result = result
                }

                p.resultCh <- task
            }
        }()
    }

    // Kumpulkan results di goroutine terpisah
    go func() {
        p.wg.Wait()
        close(p.resultCh)
    }()

    return p // keyword: return
}

func (p *WorkerPool) Submit(name string, fn func() (string, error)) int {
    p.mu.Lock()
    defer p.mu.Unlock()

    p.nextID++
    task := Task{
        ID:     p.nextID,
        Name:   name,
        Status: StatusPending,
        fn:     fn,
    }
    p.tasks = append(p.tasks, task)
    p.taskCh <- task
    return task.ID
}

func (p *WorkerPool) Wait() {
    close(p.taskCh)

    // Kumpulkan semua results — keyword: for, range, select
    done := make(chan struct{})
    go func() {
        for result := range p.resultCh {
            p.mu.Lock()
            for i := range p.tasks {
                if p.tasks[i].ID == result.ID {
                    p.tasks[i] = result
                    break // keyword: break
                }
            }
            p.mu.Unlock()
        }
        close(done)
    }()

    // Tunggu dengan timeout — keyword: select
    select {
    case <-done:
        // selesai normal
    case <-time.After(30 * time.Second):
        fmt.Println("Timeout menunggu tasks")
    }
}

func (p *WorkerPool) Results() []Task {
    p.mu.Lock()
    defer p.mu.Unlock()

    // Salin slice dengan new allocation — keyword: new tidak dipakai di sini
    // tapi gunakan make untuk slice baru
    result := make([]Task, len(p.tasks))
    copy(result, p.tasks)
    return result
}

func main() { // keyword: func, juga entry point
    pool := NewWorkerPool(3) // 3 goroutine worker

    // Submit beberapa task
    tasks := []struct {
        name string
        fn   func() (string, error)
    }{
        {"Ambil data user", func() (string, error) {
            time.Sleep(100 * time.Millisecond)
            return "42 users ditemukan", nil
        }},
        {"Proses pembayaran", func() (string, error) {
            time.Sleep(200 * time.Millisecond)
            return "Rp 5.000.000 berhasil diproses", nil
        }},
        {"Kirim email", func() (string, error) {
            time.Sleep(150 * time.Millisecond)
            return "3 email terkirim", nil
        }},
        {"Backup database", func() (string, error) {
            time.Sleep(300 * time.Millisecond)
            return "Backup selesai: 2.3GB", nil
        }},
        {"Generate laporan", func() (string, error) {
            time.Sleep(250 * time.Millisecond)
            return "Laporan Q4 siap", nil
        }},
    }

    // keyword: for, range
    for _, t := range tasks {
        id := pool.Submit(t.name, t.fn)
        fmt.Printf("Task #%d '%s' disubmit\n", id, t.name)
    }

    fmt.Println("\nMenunggu semua task selesai...")
    pool.Wait()

    fmt.Println("\n=== Hasil Task ===")
    // keyword: for, range
    for _, task := range pool.Results() {
        status := "✓"
        // keyword: if
        if task.Status == StatusFailed {
            status = "✗"
        }
        fmt.Printf("[%s] #%d %-25s → %s\n",
            status, task.ID, task.Name, task.Result)
    }

    // keyword: var — deklarasi eksplisit
    var total int = len(pool.Results())
    fmt.Printf("\nSelesai. Total task: %d\n", total)
}

Ringkasan #

  • Go hanya punya 25 keyword — sedikit secara sengaja untuk menjaga bahasa tetap sederhana dan konsisten.
  • 6 keyword deklarasi: package, import, var, const, type, func.
  • 10 keyword kontrol aliran: if, else, for, switch, case, default, break, continue, fallthrough, goto.
  • 3 keyword fungsi & goroutine: return, defer, go.
  • 4 keyword tipe komposit: struct, interface, map, chan.
  • 2 keyword alokasi: new (pointer ke zero value, semua tipe) dan make (siap pakai, khusus slice/map/chan).
  • 2 keyword concurrency: select (tunggu channel) dan range (iterasi koleksi).
  • goto ada tapi hampir tidak pernah dipakaifor selalu lebih ekspresif.
  • Tidak ada: class, extends, implements, try/catch, while, async/await, this, ternary ?: — semua dihilangkan secara sengaja dengan alasan desain yang kuat.
  • Memahami 25 keyword ini berarti memahami seluruh fondasi sintaks Go — tidak ada keyword tersembunyi atau kejutan.

← Sebelumnya: Vendoring   Berikutnya: Goroutine →

About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact