Menu

Variabel di Golang: var, :=, Zero Value, dan Shadowing

Cara mendeklarasikan variabel di Go dengan var dan bentuk singkat :=, apa itu zero value, assignment ganda, serta error shadowing dan variabel yang tidak dipakai yang sering menjebak programmer Go pemula.

Halaman ini dilengkapi editor yang bisa dijalankan. Edit, jalankan, dan lihat output-nya seketika.

Go punya dua cara untuk mendeklarasikan variabel: var, yang bisa dipakai di mana saja, dan :=, bentuk singkat yang bisa dipakai di dalam fungsi dan menebak tipenya secara otomatis.

Setiap variabel punya tipe tetap yang ditentukan saat kompilasi. Saat kamu memberi nilai, Go menebak tipenya dari nilai itu, jadi menulis tipenya juga (var city string = "Lisbon") memang sah tetapi berlebihan.

var vs :=

var:=
Tempatlevel package dan di dalam fungsihanya di dalam fungsi
Tipeopsional; wajib kalau tidak ada nilaiselalu ditebak otomatis
Nilai awalopsional (selain itu zero value)wajib
Deklarasi ulangtidak pernahboleh kalau minimal satu variabel di sisi kiri adalah variabel baru

Pilihan yang idiomatis di dalam fungsi:

  • x := value kalau kamu punya nilai awal.
  • var x T kalau kamu menginginkan zero value, yang menandakan "sengaja kosong": var buf bytes.Buffer, var total int.
  • var x T = value kalau tipe hasil tebakan bukan tipe yang kamu inginkan, misalnya var ratio float64 = 1 (ratio := 1 biasa akan bertipe int).

:= di luar fungsi adalah syntax error:

./main.go:5:1: syntax error: non-declaration statement outside function body

Zero value

Variabel yang dideklarasikan tanpa nilai tidak pernah berisi sampah. Variabel itu berisi zero value dari tipenya:

TipeZero value
integer, float0
boolfalse
string""
pointer, slice, map, channel, fungsi, interfacenil
array, structsetiap elemen atau field diisi zero value-nya

API Go yang baik dirancang agar zero value-nya berguna: sync.Mutex yang bernilai nol dalam keadaan tidak terkunci, bytes.Buffer yang bernilai nol kosong dan siap dipakai, dan len, range, serta append semuanya bisa dipakai pada slice nil. Yang perlu diwaspadai adalah map: membaca map nil mengembalikan zero value, tetapi menulis ke map nil akan panic. Buat map dengan make atau literal sebelum menyimpan isinya.

Mendeklarasikan beberapa variabel

Blok var ( ... ) mengelompokkan variabel di level package yang saling terkait. Dalam assignment ganda seperti x, y = y, x, setiap ekspresi di sisi kanan dievaluasi sebelum ada yang di-assign, dan itulah sebabnya pertukaran nilai ini berhasil.

:= dengan beberapa nama tidak mendeklarasikan ulang apa pun selama minimal satu nama di sisi kiri adalah nama baru. Nama yang sudah ada di scope yang sama hanya diberi nilai baru. Inilah yang memungkinkan kamu memakai ulang err:

f, err := os.Open("a.txt")   // declares f and err
g, err := os.Open("b.txt")   // declares g, assigns to the existing err

Kalau tidak ada satu pun nama yang baru, hasilnya error:

./main.go:7:4: no new variables on left side of :=

Pakai = biasa untuk memberi nilai ke variabel yang sudah ada.

Variabel yang tidak dipakai adalah error

Variabel lokal yang dideklarasikan tetapi tidak pernah dibaca akan menghentikan build:

./main.go:9:2: declared and not used: x

Ini bukan peringatan yang bisa kamu matikan. Hapus variabelnya, pakai, atau, saat sedang debugging, bungkam dengan blank identifier: _ = x. Blank identifier juga membuang nilai kembalian yang tidak kamu butuhkan: _, err := fmt.Println("hi").

Variabel di level package dan parameter fungsi dikecualikan dari aturan ini.

Scope dan shadowing

Sebuah variabel ada sejak deklarasinya sampai akhir blok yang membungkusnya ({ ... }). := di dalam blok yang lebih dalam membuat variabel baru, walaupun ada variabel dengan nama yang sama di luar. Variabel di luar itu tertutupi (shadowed), bukan diubah:

Program ini mencetak inside: 42 lalu outside: 0. := di dalam if mendeklarasikan count dan err sebagai variabel baru di blok dalam, karena keduanya belum ada di sana. Kode ini bisa dikompilasi tanpa masalah dan menjadi sumber klasik bug "nilaiku hilang".

Cara memperbaikinya adalah mendeklarasikan err lebih dulu dan memberi nilai dengan =:

var err error
count, err = strconv.Atoi(input)

go vet tidak melaporkan shadowing secara default. Analyzer shadow yang terpisah bisa melakukannya, dan linter seperti golangci-lint bisa mengaktifkannya.

Penamaan

  • Pakai camelCase: maxRetries, userID. Bukan max_retries.
  • Tulis akronim dalam satu jenis huruf: userID, httpClient, parseURL, bukan userId.
  • Nama pendek untuk scope yang pendek: i di perulangan, r untuk reader, err untuk error. Nama yang lebih panjang dan deskriptif untuk variabel di level package.
  • Nama yang diawali huruf besar di level package (var Timeout) diekspor ke package lain. Lihat halaman package dan import.

Variabel di level package

Variabel yang dideklarasikan di luar fungsi hidup selama program berjalan dan diinisialisasi sebelum main dijalankan, sesuai urutan ketergantungannya. Variabel ini praktis untuk konfigurasi dan cache, dan dipakai bersama oleh semua goroutine. Kalau lebih dari satu goroutine menulis ke variabel seperti itu, lindungi dengan mutex atau pakai sync/atomic, karena kalau tidak, akan terjadi data race.

Pakai konstanta untuk nilai yang tidak pernah berubah. const tidak bisa diubah secara tidak sengaja dan tidak ada biayanya saat program berjalan.

Pertanyaan yang sering diajukan

Apa bedanya var dan := di Go?

:= mendeklarasikan dan menginisialisasi variabel dengan tipe yang ditebak otomatis, dan hanya bisa dipakai di dalam fungsi: count := 10. var bisa dipakai di mana saja (termasuk di level package), memungkinkan kamu menyebut tipenya, dan boleh tanpa nilai awal untuk mendapatkan zero value: var count int. Di dalam fungsi, Go yang idiomatis memakai := kalau ada nilai awal dan var kalau kamu menginginkan zero value.

Apa itu zero value di Go?

Setiap variabel yang dideklarasikan tanpa nilai mendapat zero value dari tipenya: 0 untuk angka, false untuk bool, "" untuk string, dan nil untuk pointer, slice, map, channel, fungsi, dan interface. Struct mendapat zero value untuk setiap field-nya. Go tidak punya variabel yang belum terinisialisasi.

Bagaimana cara memperbaiki error "declared and not used" di Go?

Go menolak variabel lokal yang diberi nilai tetapi tidak pernah dibaca. Pakai variabel itu, hapus, atau, saat sedang debugging, berikan ke blank identifier dengan _ = x. Variabel di level package dan parameter fungsi dikecualikan.

Bagaimana cara mendeklarasikan variabel global di Go?

Pakai var di level package, di luar fungsi mana pun: var counter int. Bentuk singkat := tidak diizinkan di sana. Nama yang diawali huruf besar (var Counter int) terlihat oleh package lain; nama yang diawali huruf kecil hanya terlihat di package-nya sendiri. Lindungi variabel di level package dengan mutex kalau ada goroutine yang menulis ke sana.

Ilustrasi bahasa pemrograman di Coddy

Belajar coding dengan Coddy

Mulai