01. Pengenalan Golang
Sejarah, latar belakang pembuatan Go oleh Google, serta keunggulannya dibanding bahasa lain.
Apa itu Go (Golang)?
Go (atau sering disebut Golang) adalah bahasa pemrograman open source yang dikembangkan di Google oleh Robert Griesemer, Rob Pike, dan Ken Thompson pada tahun 2007 dan dirilis ke publik pada tahun 2009.
Go diciptakan untuk menyelesaikan permasalahan skalabilitas dan kompleksitas pengembangan software skala besar di Google yang sebelumnya didominasi oleh C++ dan Java.
- Compiled Language: Kompilasi langsung ke kode mesin (*native machine code*), sangat cepat tanpa butuh VM.
- Statically Typed: Pengecekan tipe data terjadi pada saat kompilasi (*compile-time*).
- Garbage Collected: Manajemen memori otomatis yang sangat cepat dan efisien.
- Built-in Concurrency: Dukungan Concurrency kelas satu menggunakan Goroutines & Channels.
- Simplicity & Cleanliness: Sintaks yang ringkas, konsisten, dan mudah dipelajari (hanya ~25 keyword).
Mengapa Belajar Golang?
| Kriteria | Bahasa Lain (Java / Python) | Golang |
|---|---|---|
| Kecepatan Eksekusi | Sedang / Lambat (Interpreted / JVM) | Sangat Cepat (Native Binary) |
| Penggunaan Memori | Relatif Besar | Sangat Ringat (Memory footprint kecil) |
| Ukuran Binary | Membutuhkan Runtime (JRE/Python interpreter) | Single Self-Contained Binary |
| Concurrency | Thread berat (OS Thread) | Goroutine ultra-ringan (~2KB per goroutine) |
Contoh program
package main
import "fmt"
func main() {
fmt.Println("Selamat Datang di Kelas Golang Kodeloka!")
fmt.Println("Go diciptakan oleh Robert Griesemer, Rob Pike, dan Ken Thompson di Google.")
}
02. Menginstall Golang & Setup Environment
Langkah-langkah instalasi compiler Go, pemeriksaan environment variables, dan konfigurasi VS Code.
Instalasi Compiler Go
Untuk menjalankan program Go di komputer lokal, Anda perlu mengunduh installer resmi dari situs web https://go.dev/dl/.
Setelah instalasi, jalankan perintah berikut di terminal/command prompt untuk memverifikasi:
# Memeriksa versi Go yang terinstall go version # Memeriksa environment variables Go (GOROOT, GOPATH, dll) go env
Struktur Environment Go:
GOROOT: Lokasi di mana runtime & SDK Golang terinstall di sistem operasi.GOPATH: Workspace utama proyek Go lokal Anda (pada Go versi modern dengan Go Modules, lokasi direktori bebas).
Contoh program
package main
import (
"fmt"
"runtime"
)
func main() {
fmt.Println("Versi Go Runtime:", runtime.Version())
fmt.Println("Jumlah CPU Core:", runtime.NumCPU())
fmt.Println("Sistem Operasi:", runtime.GOOS)
fmt.Println("Arsitektur CPU:", runtime.GOARCH)
}
03. Membuat Project Go
Inisialisasi Go Modules dengan 'go mod init' dan memahami struktur folder proyek Go modern.
Go Modules (Dependency Management)
Sejak Go versi 1.11+, pengelolaan proyek dan package Go menggunakan Go Modules. Dengan Go Modules, Anda tidak wajib menaruh kode proyek di dalam folder GOPATH.
# 1. Buat folder proyek baru mkdir belajar-golang-dasar cd belajar-golang-dasar # 2. Inisialisasi modul proyek Go go mod init belajar-golang-dasar
Perintah go mod init akan menghasilkan file go.mod yang mencatat nama modul dan versi Go yang digunakan.
Contoh program
package main
import "fmt"
func main() {
fmt.Println("Proyek Go Modules Berhasil Dibuat!")
fmt.Println("File go.mod berfungsi sebagai pengelola dependency & nama module proyek.")
}
04. Program Hello World
Membedah struktur file utama Go: package main, import fmt, dan fungsi main().
Struktur Anatomi Kode Go
Setiap file kode Go terdiri dari 3 bagian utama:
package main: Deklarasi package. Packagemainadalah penanda bahwa file ini adalah entry point aplikasi executable.import "fmt": Mengimpor package bawaan Go (Formated I/O) untuk mencetak output.func main(): Fungsi utama yang pertama kali dieksekusi oleh runtime Go.
- Go sensitif terhadap Case Sensitivity (Huruf besar & kecil berpengaruh).
- Tidak memerlukan titik koma (
;) di akhir setiap baris kode! - Kurung kurawal buka
{HARUS berada di baris yang sama dengan deklarasifunc main()!
Contoh program
package main
import "fmt"
func main() {
fmt.Println("Hello World!")
fmt.Println("Belajar Golang Dasar bersama Kodeloka")
}
05. Multiple Main Function
Aturan pembuatan file dalam package main dan cara mengeksekusi file tertentu.
Aturan Multiple Main Function
Dalam satu folder package yang sama, Go tidak mengizinkan adanya lebih dari satu fungsi main() jika Anda mengompilasi seluruh direktori secara bersamaan (misal: go run .).
Jika ingin menjalankan file tertentu yang memiliki main function tersendiri:
# Menjalankan spesifik satu file saja: go run helper.go # Menjalankan main.go saja: go run main.go
Contoh program
package main
import "fmt"
func main() {
fmt.Println("File ini memiliki main function tersendiri.")
fmt.Println("Gunakan 'go run namafile.go' jika dalam 1 folder ada beberapa file berketerangan main.")
}
06. Tipe Data Number
Klasifikasi Integer (int8 - int64, uint), Floating Point (float32, float64), dan Tipe Alias (byte, rune).
1. Integer (Bilangan Bulat)
| Tipe Data Signed (+/-) | Tipe Data Unsigned (+) | Rentang Nilai |
|---|---|---|
int8 | uint8 | -128 s/d 127 (int8) / 0 s/d 255 (uint8) |
int16 | uint16 | -32,768 s/d 32,767 |
int32 | uint32 | -2,147,483,648 s/d 2,147,483,647 |
int64 | uint64 | -9,223,372,036,854,775,808 s/d 9... |
int | uint | Sesuai arsitektur OS (32-bit / 64-bit) |
2. Floating Point (Bilangan Desimal)
float32: Presisi 32-bit desimal.float64: Presisi 64-bit desimal (Default rekomendasi).
3. Alias Tipe Data Number
byte= Alias untukuint8rune= Alias untukint32(representasi Karakter Unicode)
Contoh program
package main
import "fmt"
func main() {
var nilaiInt8 int8 = 100
var nilaiUint uint = 250
var IPK float32 = 3.85
var desimal float64 = 100.99
var hurufA byte = 'A' // uint8 ascii value
fmt.Println("int8:", nilaiInt8)
fmt.Println("uint:", nilaiUint)
fmt.Println("IPK (float32):", IPK)
fmt.Println("desimal (float64):", desimal)
fmt.Println("byte 'A' (ASCII Code):", hurufA)
}
07. Tipe Data Boolean
Representasi nilai kebenaran logika boolean: true dan false.
Tipe Data Boolean (bool)
Tipe data boolean di Go dipresentasikan dengan keyword bool. Tipe data ini hanya memiliki dua nilai yang mungkin:
true(Benar)false(Salah)
Nilai awal/default dari variabel berjenis bool jika tidak diinisialisasi adalah false.
Contoh program
package main
import "fmt"
func main() {
var benar bool = true
var salah bool = false
fmt.Println("Benar =", benar)
fmt.Println("Salah =", salah)
}
08. Tipe Data String
Memahami string di Go, fungsi len(), dan pengaksesan karakter berdasarkan byte index.
String di Golang
String adalah kumpulan karakter yang diapit oleh tanda petik dua ("...") atau backtick (`...`).
Fungsi Penting untuk String:
len("string"): Mengembalikan jumlah byte dalam string."string"[index]: Mengambil byte/karakter pada indeks tertentu (mengembalikan kode ASCII / uint8).
Mengakses "Eko"[0] tidak menghasilkan karakter "E", melainkan kode ASCII dari huruf E yaitu 69!
Contoh program
package main
import "fmt"
func main() {
var nama string = "Eko Kurniawan"
fmt.Println("Nama:", nama)
fmt.Println("Panjang String (len):", len(nama))
fmt.Println("Karakter pertama (byte ASCII):", nama[0])
fmt.Println("Karakter pertama (String):", string(nama[0]))
}
09. Variable
Cara deklarasi variabel dengan var, tipe implisit, sintaks := (short declaration), serta deklarasi multiple variable.
Cara Deklarasi Variabel di Go
Ada beberapa sintaks fleksibel untuk mendefinisikan variabel di Go:
- Deklarasi Eksplisit dengan
var:
var name string = "Eko" - Deklarasi Implisit (Type Inference):
var age = 30(Go otomatis mendeteksi bahwa age adalah int). - Short Declaration dengan kata kunci
:=:
country := "Indonesia"(Kata kuncivartidak diperlukan lagi saat pertama kali deklarasi). - Multiple Variable Declaration:
var ( firstName = "Eko"; lastName = "Khannedy" )
Setiap variabel local yang sudah dideklarasikan HARUS DUGUNAKAN. Jika ada variabel nganggur/tidak terpakai, Go akan menghasilkan error kompilasi!
Contoh program
package main
import "fmt"
func main() {
// Deklarasi var eksplisit
var name string = "Eko Kurniawan"
fmt.Println("Nama:", name)
// Short declaration :=
age := 30
fmt.Println("Umur:", age)
// Multiple Variable
var (
firstName = "Eko"
lastName = "Khannedy"
)
fmt.Println("Full Name:", firstName, lastName)
}
10. Constant
Mengenal konstan (const), sifat immutabilitas, serta deklarasi multiple constant.
Constant (Konstanta)
Constant adalah variabel yang nilainya tetap dan tidak dapat diubah kembali setelah pertama kali dideklarasikan.
Konstanta dideklarasikan menggunakan kata kunci const.
Berbeda dari variabel biasa, jika Anda membuat constant tetapi tidak menggunakannya di dalam kode, Go TIDAK akan komplain/error!
Contoh program
package main
import "fmt"
func main() {
const firstName string = "Eko"
const lastName = "Khannedy"
const value = 1000
// Multiple const
const (
pi = 3.14
application = "Belajar Golang"
)
fmt.Println(firstName, lastName)
fmt.Println("App:", application, "PI:", pi)
// firstName = "Budi" // ERROR! Cannot assign to constant
}
11. Konversi Tipe Data
Teknik kasting/konversi tipe data number (integer overflow) dan konversi byte ke string.
Konversi Tipe Data (Type Casting)
Di Go, kita bisa mengonversi satu tipe data ke tipe data lainnya dengan cara memanggil nama tipe tujuannya sebagai fungsi: TipeTujuan(nilai).
Jika Anda mengonversi tipe data angka berkapasitas besar (misal int32(300)) ke tipe data angka berkapasitas lebih kecil (misal int8 yang batas maksnya 127), nilai akan memutar mutar balik (overflow) ke angka minus!
Contoh program
package main
import "fmt"
func main() {
var nilai32 int32 = 32768
var nilai64 int64 = int64(nilai32)
var nilai8 int8 = int8(nilai32) // Terjadi Integer Overflow!
fmt.Println("int32:", nilai32)
fmt.Println("int64:", nilai64)
fmt.Println("int8 (Overflow):", nilai8)
// Konversi Byte ke String
var name = "Eko"
var eByte byte = name[0]
var eString string = string(eByte)
fmt.Println("String dari byte index 0:", eString)
}
12. Type Declarations
Membuat alias tipe data kustom untuk meningkatkan kejelasan dan keterbacaan kode.
Type Declarations (Custom Type)
Type Declarations adalah kemampuan membuat alias untuk tipe data yang sudah ada di Go. Ini berguna untuk memperjelas maksud/domain data.
Sintaks: type NamaTipeBaru TipeLama
Contoh program
package main
import "fmt"
func main() {
type NoKTP string
type Married bool
var ktpEko NoKTP = "1111111111111111"
var statusNikah Married = true
fmt.Println("No KTP:", ktpEko)
fmt.Println("Status Menikah:", statusNikah)
}
13. Operasi Matematika
Operator aritmatika dasar (+, -, *, /, %), augmented assignments (+=, -=), dan unary operators (++).
Operator Aritmatika Dasar
+(Penjumlahan)-(Pengurangan)*(Perkalian)/(Pembagian)%(Sisa Bagi / Modulo)
Augmented Assignments & Unary
| Operator Augmented | Singkatan Dari | Unary Operator | Keterangan |
|---|---|---|---|
a += 10 | a = a + 10 | a++ | a = a + 1 |
a -= 5 | a = a - 5 | a-- | a = a - 1 |
a *= 2 | a = a * 2 | -a | Negative number |
Contoh program
package main
import "fmt"
func main() {
a := 10
b := 3
fmt.Println("10 + 3 =", a+b)
fmt.Println("10 - 3 =", a-b)
fmt.Println("10 * 3 =", a*b)
fmt.Println("10 / 3 =", a/b) // Pembagian integer menghasilkan integer!
fmt.Println("10 % 3 =", a%b)
// Augmented & Unary
i := 5
i += 10 // i = 15
fmt.Println("Augmented i += 10:", i)
i++ // i = 16
fmt.Println("Unary i++:", i)
}
14. Operasi Perbandingan
Membandingkan dua nilai dengan operator >, <, >=, <=, ==, != yang menghasilkan nilai boolean.
Operator Perbandingan
Operator perbandingan digunakan untuk membandingkan dua buah nilai dan selalu mengembalikan hasil bertipe bool (true/false).
>(Lebih besar dari)<(Lebih kecil dari)>=(Lebih besar atau sama dengan)<=(Lebih kecil atau sama dengan)==(Sama dengan)!=(Tidak sama dengan)
Contoh program
package main
import "fmt"
func main() {
name1 := "Eko"
name2 := "Eko"
var resultEqual bool = name1 == name2
fmt.Println("name1 == name2:", resultEqual)
val1 := 100
val2 := 200
fmt.Println("100 > 200:", val1 > val2)
fmt.Println("100 != 200:", val1 != val2)
}
15. Operasi Boolean
Logika Boolean dengan operator AND (&&), OR (||), dan NOT (!).
Operator Logika Boolean
| Operator | Nama | Keterangan Rule |
|---|---|---|
&& | AND | Mengembalikan true HANYA JIKA kedua kondisi bernilai true. |
|| | OR | Mengembalikan true JIKA SALAH SATU kondisi bernilai true. |
! | NOT | Membalikkan nilai boolean (!true menjadi false). |
Contoh program
package main
import "fmt"
func main() {
nilaiUjian := 80
nilaiAbsensi := 75
lulusUjian := nilaiUjian >= 75
lulusAbsensi := nilaiAbsensi >= 75
lulusFinal := lulusUjian && lulusAbsensi
fmt.Println("Apakah Lulus Kelulusan Akhir (AND):", lulusFinal)
fmt.Println("Pembalikan Logika (!lulusFinal):", !lulusFinal)
}
16. Tipe Data Array
Struktur data Array dengan panjang tetap (fixed length), inisialisasi array, dan fungsi len().
Tipe Data Array
Array adalah kumpulan data sekumpulan tipe data yang sama dengan kapasitas/panjang yang FIXED (tetap) dan tidak bisa diubah setelah dibuat.
Ukuran array merupakan bagian dari tipe data array itu sendiri. [3]int dan [5]int adalah 2 tipe data yang berbeda di Go!
Contoh program
package main
import "fmt"
func main() {
// Deklarasi Array Manual
var names [3]string
names[0] = "Eko"
names[1] = "Kurniawan"
names[2] = "Khannedy"
fmt.Println(names[0], names[1], names[2])
// Array Literal dengan Deklarasi Langsung
values := [...]int{90, 85, 95, 100}
fmt.Println("Array values:", values)
fmt.Println("Panjang Array values:", len(values))
}
17. Tipe Data Slice
Potongan array berukuran dinamis. Konsep Pointer, Length, Capacity, fungsi make(), append(), dan copy().
Tipe Data Slice (Sangat Penting!)
Slice adalah potongan dari Array. Berbeda dari Array, ukuran Slice dinamis dan merupakan tipe data paling sering digunakan di Go.
3 Komponen Penyusun Slice:
- Pointer: Penunjuk ke data elemen pertama di array underlying.
- Length (len): Panjang dari slice saat ini.
- Capacity (cap): Kapasitas maksimum slice sebelum array underlying diperbesar.
| Fungsi Slice | Keterangan |
|---|---|
array[low:high] | Membuat slice dari index low sampai sebelum high. |
make([]T, len, cap) | Membuat slice baru dari awal dengan menentukan length & capacity. |
append(slice, elem) | Menambah elemen baru ke slice (otomatis memperbesar array underlying jika cap penuh). |
copy(dest, src) | Menyalin data dari slice sumber ke slice tujuan. |
Contoh program
package main
import "fmt"
func main() {
months := [...]string{
"Januari", "Februari", "Maret", "April",
"Mei", "Juni", "Juli", "Agustus",
"September", "Oktober", "November", "Desember",
}
slice1 := months[4:7] // Mei, Juni, Juli
fmt.Println("Slice1:", slice1)
fmt.Println("Len:", len(slice1), "Cap:", cap(slice1))
// Slice dibuat dengan make()
newSlice := make([]string, 2, 5)
newSlice[0] = "Eko"
newSlice[1] = "Kurniawan"
fmt.Println("newSlice:", newSlice)
// Append
newSlice2 := append(newSlice, "Khannedy")
fmt.Println("after append:", newSlice2)
}
18. Tipe Data Map
Koleksi key-value pair dengan tipe data yang ditentukan, fungsi delete(), dan inisialisasi map.
Tipe Data Map
Map adalah tipe data kumpulan key-value pair (pasangan kunci dan nilai). Kata kunci di map harus unik.
Sintaks: map[TipeKey]TipeValue
Fungsi Penting untuk Map:
make(map[TipeKey]TipeValue): Membuat map baru yang siap diisi.len(map): Mengambil jumlah key-value di map.delete(map, key): Menghapus data key dari map.
Contoh program
package main
import "fmt"
func main() {
person := map[string]string{
"name": "Eko",
"address": "Subang",
}
person["title"] = "Programmer"
fmt.Println("Person Map:", person)
fmt.Println("Name:", person["name"])
// Menghapus key dari map
delete(person, "title")
fmt.Println("Setelah delete title:", person)
}
19. If Expression
Percabangan kondisi dengan if, else if, else, serta fitur unik If Short Statement.
If Expression
Percabangan if digunakan untuk mengeksekusi blok kode tertentu berdasarkan pengujian kondisi boolean.
If Short Statement (Fitur Unik Go)
Go mendukung pembuatan variabel singkat yang langsung diuji dalam baris if sebelum kondisi dievaluasi:
if length := len(name); length > 5 {
fmt.Println("Nama terlalu panjang")
} else {
fmt.Println("Nama sudah pas")
}
Contoh program
package main
import "fmt"
func main() {
name := "Khannedy"
if name == "Eko" {
fmt.Println("Hello Eko")
} else if name == "Khannedy" {
fmt.Println("Hello Khannedy")
} else {
fmt.Println("Hi, Boleh Kenalan?")
}
// If Short Statement
if length := len(name); length > 5 {
fmt.Println("Terlalu Panjang! Karakter:", length)
}
}
20. Switch Expression
Percabangan switch, short statement pada switch, serta switch tanpa kondisi.
Switch Expression
switch adalah bentuk alternatif percabangan kondisi yang lebih rapi dibanding banyak if-else bertingkat.
Go TIDAK membutuhkan kata kunci break di setiap akhir blok case! Go secara otomatis tidak akan terus jatuh (*no automatic fallthrough*).
Switch Tanpa Kondisi
Switch bisa digunakan tanpa variabel ekspresi di awal, membuat case bertindak seperti pengujian if-else biasa.
Contoh program
package main
import "fmt"
func main() {
name := "Eko"
switch name {
case "Eko":
fmt.Println("Hello Eko")
case "Joko":
fmt.Println("Hello Joko")
default:
fmt.Println("Boleh Kenalan?")
}
// Switch Tanpa Kondisi
length := len(name)
switch {
case length > 10:
fmt.Println("Nama sangat panjang")
case length > 5:
fmt.Println("Nama cukup panjang")
default:
fmt.Println("Nama sudah pas")
}
}
21. For Loop
Satu-satunya kata kunci perulangan di Go: For kondisional, init & post statement, serta For Range.
For Loop (Satu-satunya Loop di Go!)
Golang TIDAK memiliki perulangan while atau do-while. Semua bentuk perulangan dilakukan menggunakan kata kunci for.
Bentuk Perulangan For:
for kondisi {}(Seperti while loop)for init; kondisi; post {}(Standard for loop)for index, value := range collection {}(Iterasi Array, Slice, Map, String)
Contoh program
package main
import "fmt"
func main() {
// Standard For Loop
for counter := 1; counter <= 5; counter++ {
fmt.Println("Perulangan ke-", counter)
}
// For Range pada Slice
names := []string{"Eko", "Kurniawan", "Khannedy"}
for index, name := range names {
fmt.Println("Index:", index, "=", name)
}
}
22. Break dan Continue
Mengontrol alur perulangan: menghentikan paksa (break) atau melompati iterasi (continue).
Break & Continue
break: Digunakan untuk menghentikan seluruh proses perulangan seketika itu juga.continue: Digunakan untuk menghentikan iterasi saat ini dan langsung melompat ke iterasi berikutnya.
Contoh program
package main
import "fmt"
func main() {
// Continue (Cetak hanya angka ganjil)
fmt.Println("--- Continue Example ---")
for i := 1; i <= 10; i++ {
if i%2 == 0 {
continue // Lewati angka genap
}
fmt.Println("Angka Ganjil:", i)
}
// Break
fmt.Println("--- Break Example ---")
for i := 1; i <= 10; i++ {
if i == 5 {
break // Berhenti total jika i == 5
}
fmt.Println("Iterasi ke-", i)
}
}
23. Function
Mendefinisikan fungsi (func) sederhana untuk membungkus blok kode re-usable.
Function (Fungsi)
Function adalah blok kode yang dibuat untuk melakukan tugas tertentu dan dapat dipanggil berulang kali.
Sintaks: func namaFungsi() { ... }
Contoh program
package main
import "fmt"
func sayHello() {
fmt.Println("Hello World dari Function sayHello!")
}
func main() {
sayHello()
sayHello()
}
24. Function Parameter
Mengirimkan data ke dalam fungsi melalui parameter.
Function Parameter
Fungsi dapat menerima data input berupa parameter. Parameter ditulis di dalam tanda kurung fungsi beserta tipe datanya.
Contoh program
package main
import "fmt"
func sayHelloTo(firstName string, lastName string) {
fmt.Println("Hello", firstName, lastName)
}
func main() {
sayHelloTo("Eko", "Khannedy")
sayHelloTo("Budi", "Nugraha")
}
25. Function Return Value
Mengembalikan hasil olahan fungsi menggunakan kata kunci return.
Function Return Value
Fungsi dapat mengembalikan nilai hasil eksekusinya menggunakan kata kunci return. Tipe data kembalian harus dideklarasikan setelah tanda kurung parameter.
Contoh program
package main
import "fmt"
func getHello(name string) string {
return "Hello " + name
}
func main() {
result := getHello("Eko")
fmt.Println(result)
}
26. Returning Multiple Values
Fitur hebat Go: Mengembalikan banyak nilai sekaligus dari sebuah fungsi dan mengabaikan nilai dengan '_'.
Returning Multiple Values
Go mendukung pengembalian **lebih dari satu nilai** (multiple values) secara native dari sebuah fungsi!
Jika kita tidak membutuhkan salah satu nilai kembalian, kita bisa mengabaikannya menggunakan karakter garis bawah _ (blank identifier).
Contoh program
package main
import "fmt"
func getFullName() (string, string) {
return "Eko", "Khannedy"
}
func main() {
firstName, lastName := getFullName()
fmt.Println("Full:", firstName, lastName)
// Mengabaikan kembalian kedua dengan _
fName, _ := getFullName()
fmt.Println("First Name Only:", fName)
}
27. Named Return Values
Mendefinisikan nama variabel untuk nilai kembalian fungsi sejak awal deklarasi header.
Named Return Values
Kita dapat memberikan nama pada variabel yang akan dikembalikan oleh fungsi di bagian header fungsi.
Contoh program
package main
import "fmt"
func getCompleteName() (firstName, middleName, lastName string) {
firstName = "Eko"
middleName = "Kurniawan"
lastName = "Khannedy"
return // Otomatis mengembalikan firstName, middleName, lastName
}
func main() {
a, b, c := getCompleteName()
fmt.Println(a, b, c)
}
28. Variadic Function
Fungsi yang mampu menerima jumlah parameter dinamis (Varargs) dengan sintaks '...T'.
Variadic Function (Varargs)
Parameter variadic memungkinkan sebuah fungsi menerima masukan data dinamis dengan tipe sama dalam jumlah berapa saja (atau 0 argumen).
Sintaks: numbers ...int (Varargs harus berada di posisi parameter paling akhir).
Contoh program
package main
import "fmt"
func sumAll(numbers ...int) int {
total := 0
for _, number := range numbers {
total += number
}
return total
}
func main() {
total := sumAll(10, 20, 30, 40, 50)
fmt.Println("Total Sum:", total)
// Passing slice ke variadic parameter dengan ...
slice := []int{10, 10, 10}
fmt.Println("Total Slice Sum:", sumAll(slice...))
}
29. Function as Value
Fungsi di Go adalah First-Class Citizen yang dapat disimpan dalam variabel layaknya data biasa.
Function as Value
Di Golang, fungsi adalah First-Class Citizen. Artinya, fungsi dapat disimpan ke dalam variabel seperti halnya data angka atau string!
Contoh program
package main
import "fmt"
func getGoodBye(name string) string {
return "Good Bye " + name
}
func main() {
// Menyimpan fungsi getGoodBye ke dalam variabel contoh
contoh := getGoodBye
// Memanggil fungsi dari dalam variabel
result := contoh("Eko")
fmt.Println(result)
}
30. Function as Parameter
Meneruskan fungsi sebagai argumen ke fungsi lain (Higher-Order Function) dan Type Alias untuk Function.
Function as Parameter (Higher-Order Function)
Karena fungsi adalah data, kita bisa mengirimkan fungsi sebagai parameter ke fungsi lainnya (misalnya untuk filter atau callback).
Agar deklarasi parameter fungsi tidak terlalu panjang, disarankan membuat Type Declaration untuk tipe fungsinya.
Contoh program
package main
import "fmt"
// Type alias untuk fungsi filter
type Filter func(string) string
func sayHelloWithFilter(name string, filter Filter) {
nameFiltered := filter(name)
fmt.Println("Hello", nameFiltered)
}
func spamFilter(name string) string {
if name == "Anjing" {
return "***"
}
return name
}
func main() {
sayHelloWithFilter("Eko", spamFilter)
sayHelloWithFilter("Anjing", spamFilter)
}
31. Anonymous Function
Fungsi tanpa nama yang dibuat secara langsung di tempat (inline function).
Anonymous Function
Anonymous Function adalah fungsi yang dibuat tanpa memiliki nama secara langsung saat deklarasi.
Contoh program
package main
import "fmt"
type Blacklist func(string) bool
func registerUser(name string, blacklist Blacklist) {
if blacklist(name) {
fmt.Println("You are blocked:", name)
} else {
fmt.Println("Welcome", name)
}
}
func main() {
// Anonymous Function disimpan di variabel
blacklist := func(name string) bool {
return name == "admin"
}
registerUser("admin", blacklist)
// Anonymous Function langsung dimasukkan ke parameter
registerUser("eko", func(name string) bool {
return name == "root"
})
}
32. Recursive Function
Fungsi yang memanggil dirinya sendiri (contoh: perhitungan Faktorial).
Recursive Function (Rekursif)
Fungsi rekursif adalah fungsi yang memanggil dirinya sendiri secara berulang sampai mencapai kondisi berhenti (*base case*).
Jika rekursif tidak memiliki kondisi berhenti (base case) yang tepat, pemanggilan fungsi akan menumpuk di memori stack hingga memicu crash Stack Overflow!
Contoh program
package main
import "fmt"
func factorialRecursive(value int) int {
if value == 1 {
return 1
}
return value * factorialRecursive(value-1)
}
func main() {
result := factorialRecursive(5) // 5 * 4 * 3 * 2 * 1 = 120
fmt.Println("Faktorial 5! =", result)
}
33. Closure
Kemampuan fungsi mengakses variabel di scope atasnya dan potensi side-effect efektivitas variabel.
Closure
Closure adalah kemampuan sebuah fungsi berinteraksi dengan variabel-variabel di sekitar scope tempat fungsi tersebut diciptakan.
Hati-hati saat mengubah variabel di luar scope fungsi closure karena dapat mengubah state data yang tidak sengaja!
Contoh program
package main
import "fmt"
func main() {
counter := 0
name := "Eko"
increment := func() {
name := "Budi" // Terjadi shadowing jika pakai :=
counter++ // Mengubah variabel counter di scope luar!
fmt.Println("Inner Name:", name)
}
increment()
increment()
fmt.Println("Outer Counter:", counter)
fmt.Println("Outer Name:", name)
}
34. Defer, Panic, dan Recover
Mekanisme penanganan eksekusi: Defer (cleanup execution), Panic (trigger runtime error), dan Recover (menangkap error panic).
1. Defer
defer digunakan untuk menunda eksekusi sebuah fungsi sampai fungsi utama tempat defer berada selesai dieksekusi (selalu dijalankan walaupun terjadi error).
2. Panic
panic() dipanggil untuk menghentikan jalan program saat terjadi kesalahan fatal (runtime error).
3. Recover
recover() digunakan untuk menangkap data pesan panic sehingga program tidak jadi crash (wajib dipanggil di dalam fungsi defer!).
Contoh program
package main
import "fmt"
func endApp() {
message := recover()
if message != nil {
fmt.Println("Error Terjadi (Recovered):", message)
}
fmt.Println("Aplikasi Selesai Dijalankan (Defer Output)")
}
func runApp(errorOccurred bool) {
defer endApp() // Selalu dieksekusi di akhir!
if errorOccurred {
panic("APLIKASI ERROR FATAL!")
}
fmt.Println("Aplikasi Berjalan Normal...")
}
func main() {
runApp(true) // Coba ubah ke false
}
35. Komentar
Penggunaan komentar single-line (//) dan multi-line (/* */) untuk dokumentasi kode.
Komentar di Golang
Komentar digunakan untuk memberikan dokumentasi atau penjelasan baris kode yang diabaikan oleh compiler Go.
// Single line comment/* Multi line comment */
Contoh program
package main
import "fmt"
/**
* Fungsi main adalah entry point utama aplikasi.
* Komentar multi line cocok untuk dokumentasi.
*/
func main() {
// Ini adalah komentar single line
fmt.Println("Komentar diabaikan oleh compiler Go!")
}
36. Struct
Membuat tipe data kustom berstruktur (struct), definisi field, dan pengisian struct literal.
Struct
Struct adalah kumpulan dari berbagai field/properti tipe data yang dibungkus menjadi satu kesatuan objek kustom.
Contoh program
package main
import "fmt"
type Customer struct {
Name, Address string
Age int
}
func main() {
// Pengisian Field Struct 1
var eko Customer
eko.Name = "Eko Kurniawan"
eko.Address = "Indonesia"
eko.Age = 30
fmt.Println(eko)
// Struct Literal 2
joko := Customer{
Name: "Joko",
Address: "Jakarta",
Age: 35,
}
fmt.Println(joko)
}
37. Struct Method
Menempelkan fungsi ke dalam struct sehingga struct bertindak seperti objek ber-behavior.
Struct Method
Fungsi yang menempel pada tipe Struct dinamakan Struct Method.
Sintaks: func (c Customer) sayHi(name string) { ... }
Contoh program
package main
import "fmt"
type Customer struct {
Name string
}
// Method menempel ke Customer struct
func (customer Customer) sayHi(name string) {
fmt.Println("Hi", name, "My Name is", customer.Name)
}
func main() {
eko := Customer{Name: "Eko"}
eko.sayHi("Budi")
}
38. Interface
Kontrak kumpulan method abstrak dan implementasi secara implisit (tanpa kata kunci implements).
Interface
Interface adalah tipe data abstrak yang mendefinisikan kontrak kumpulan method tanpa implementasi body.
Di Go, sebuah struct TIDAK PERLU menulis implements InterfaceName. Selama struct tersebut memiliki seluruh method yang disyaratkan interface, Go otomatis menganggap struct tersebut telah mengimplementasikan interface!
Contoh program
package main
import "fmt"
type HasName interface {
GetName() string
}
func SayHelloName(hasName HasName) {
fmt.Println("Hello", hasName.GetName())
}
type Person struct {
Name string
}
// Struct Person mengimplementasikan method GetName()
func (person Person) GetName() string {
return person.Name
}
func main() {
eko := Person{Name: "Eko"}
SayHelloName(eko)
}
39. Interface Kosong
Mengenal interface{} atau alias 'any' sebagai penampung semua jenis tipe data.
Interface Kosong (interface{} / any)
Interface Kosong adalah interface yang tidak memiliki deklarasi method sama sekali. Karena tidak ada syarat method, semua tipe data di Go otomatis memenuhi kriteria interface kosong ini.
Pada Go versi 1.18+, interface{} memiliki alias resmi kata kunci any.
Contoh program
package main
import "fmt"
func Ups(i int) any { // atau interface{}
if i == 1 {
return 1
} else if i == 2 {
return "Dua"
} else {
return true
}
}
func main() {
var data any = Ups(2)
fmt.Println("Data Dynamic:", data)
}
40. Nil
Mengenal zero value Nil untuk pointer, interface, map, slice, channel, dan function.
Nil
nil adalah nilai kosong (zero value) pada Go untuk tipe data khusus seperti: Pointer, Interface, Map, Slice, Channel, dan Function.
Tipe data dasar seperti int, string, dan bool TIDAK BISA bernilai nil! Nilai default int adalah 0, string adalah "", bool adalah false.
Contoh program
package main
import "fmt"
func NewMap(name string) map[string]string {
if name == "" {
return nil
} else {
return map[string]string{
"name": name,
}
}
}
func main() {
data := NewMap("")
if data == nil {
fmt.Println("Data Map Masih Nil!")
} else {
fmt.Println(data)
}
}
41. Type Assertions
Mengonversi tipe data dari interface kosong (any) kembali ke tipe data aslinya.
Type Assertions
Type Assertions digunakan untuk mengubah tipe data interface{} menjadi tipe data asli yang diinginkan.
Sintaks: value.(TipeAsli) atau menggunakan switch value.(type).
Contoh program
package main
import "fmt"
func random() any {
return "OK"
}
func main() {
result := random()
// Type Assertion
resultString := result.(string)
fmt.Println("String result:", resultString)
// Safe Type Assertion dengan Switch
switch value := result.(type) {
case string:
fmt.Println("Value is String:", value)
case int:
fmt.Println("Value is Int:", value)
default:
fmt.Println("Unknown Type")
}
}
42. Pointer & Memory Address
Konsep Pass by Value vs Pass by Reference di memori dan penggunaan operator ampersand (&).
Pass by Value vs Pass by Reference
Secara default di Go, semua variabel dikirim secara Pass by Value (nilainya diduplikasi/diduplikat ke lokasi memori baru).
Pointer adalah kemampuan untuk mereferensikan lokasi alamat memori variabel original menggunakan operator ampersand & (Pass by Reference).
Contoh program
package main
import "fmt"
type Address struct {
City, Province, Country string
}
func main() {
address1 := Address{"Subang", "Jawa Barat", "Indonesia"}
address2 := &address1 // Pointer ke address1
address2.City = "Bandung" // Mengubah address2 ikut mengubah address1!
fmt.Println("Address 1 (Original):", address1)
fmt.Println("Address 2 (Pointer):", address2)
}
43. Asterisk Operator (*)
Menggunakan operator '*' untuk mendereference pointer dan mengarahkan memori ke objek baru.
Asterisk Operator (*)
Saat kita mengubah variabel pointer dengan operator *, seluruh variabel lain yang mengacu ke alamat memori yang sama akan ikut berpindah mengikuti nilai baru tersebut.
Contoh program
package main
import "fmt"
type Address struct {
City, Province, Country string
}
func main() {
address1 := Address{"Subang", "Jawa Barat", "Indonesia"}
address2 := &address1
// Mengganti objek referensi pointer dengan operator *
*address2 = Address{"Jakarta", "DKI Jakarta", "Indonesia"}
fmt.Println("Address 1 Ikut Berubah:", address1)
fmt.Println("Address 2:", address2)
}
44. Operator New
Fungsi new() bawaan Go untuk mengalokasikan memori pointer baru ber-zero value.
Operator New
Go memiliki fungsi bawaan new() untuk membuat pointer kosong yang menunjuk ke memori ber-zero value dari tipe data tersebut.
Contoh program
package main
import "fmt"
type Address struct {
City, Province, Country string
}
func main() {
var alamat1 *Address = new(Address)
alamat1.City = "Jakarta"
fmt.Println("Pointer via new():", alamat1)
}
45. Pointer di Function
Mengirimkan pointer sebagai argumen fungsi untuk mengizinkan fungsi memodifikasi data original.
Pointer di Function Parameter
Secara default, parameter yang dikirim ke fungsi adalah pass-by-value. Jika ingin fungsi dapat mengubah data variabel asli di luar, tambahkan tanda * pada parameter fungsi.
Contoh program
package main
import "fmt"
type Address struct {
City, Province, Country string
}
// Parameter menggunakan pointer *Address
func ChangeCountryToIndonesia(address *Address) {
address.Country = "Indonesia"
}
func main() {
address := Address{"Subang", "Jawa Barat", ""}
ChangeCountryToIndonesia(&address) // Kirim alamat memori dengan &
fmt.Println("Hasil Asli Berubah:", address)
}
46. Pointer di Method
Sangat Rekomendasi: Menggunakan Pointer Receiver (*Struct) pada Method untuk efisiensi memori & pengubahan state.
Pointer Receiver di Method
Sangat direkomendasikan menggunakan pointer receiver (*Man) pada Struct Method agar:
- Method bisa mengubah data aktual struct asli.
- Menghemat konsumsi memori karena tidak menguji duplikasi objek struct yang besar setiap kali method dipanggil.
Contoh program
package main
import "fmt"
type Man struct {
Name string
}
// Receiver menggunakan pointer *Man
func (man *Man) Married() {
man.Name = "Mr. " + man.Name
}
func main() {
eko := Man{"Eko"}
eko.Married() // Otomatis dipanggil sebagai pointer
fmt.Println("Nama Eko Berubah:", eko.Name)
}
47. Package dan Import
Modularisasi kode Go dengan memecah file ke dalam folder package dan mengimpornya.
Package & Import
Go mengorganisir kode ke dalam direktori bernama Package. Untuk menggunakan fungsi atau struct dari package lain, kita menggunakan sintaks import "nama-module/nama-package".
Contoh program
package main
import (
"fmt"
"math"
)
func main() {
fmt.Println("Akar Kuadrat 16 (math.Sqrt):", math.Sqrt(16))
fmt.Println("Nilai Pi (math.Pi):", math.Pi)
}
48. Access Modifier (Public vs Private)
Aturan visibilitas simpul Go: Exported (Huruf Besar di Awal) vs Unexported (Huruf Kecil di Awal).
Access Modifier di Go
Di Go, tidak ada kata kunci seperti public, private, atau protected.
- Exported (Public): Diawali dengan Huruf KAPITAL / Huruf Besar (misal:
SayHello,User). BISA diakses dari luar package! - Unexported (Private): Diawali dengan Huruf KECIL (misal:
sayHello,version). HANYA BISA diakses dari dalam package yang sama!
Contoh program
package main
import "fmt"
// Exported (Public) - Huruf Besar
func SayHello(name string) string {
return "Hello " + name
}
// Unexported (Private) - Huruf Kecil
func logInternal() {
fmt.Println("Log internal package")
}
func main() {
fmt.Println(SayHello("Eko"))
logInternal()
}
49. Package Initialization
Fungsi init() yang otomatis berjalan saat package di-load, dan Blank Identifier import (_).
Package Initialization
Jika kita membuat fungsi bernama init() di dalam package, fungsi tersebut akan **otomatis dieksekusi pertama kali** ketika package tersebut di-import.
Jika ingin mengeksekusi init() tanpa memanggil fungsi di dalamnya, gunakan **Blank Identifier Import**: import _ "nama-package".
Contoh program
package main
import "fmt"
var connection string
func init() {
connection = "Database Connected Successfully!"
fmt.Println("[INIT] Executing package initialization...")
}
func main() {
fmt.Println("Main Function Running...")
fmt.Println("Connection Status:", connection)
}
50. Error Interface
Pendekatan penanganan kesalahan di Go menggunakan built-in interface 'error' dan errors.New().
Error Handling di Go
Go tidak menggunakan mekanisme try-catch-finally seperti Java/C#. Sebagai gantinya, kesalahan direpresentasikan sebagai nilai biasa menggunakan interface bawaan error.
Sintaks umum: errors.New("pesan error").
Contoh program
package main
import (
"errors"
"fmt"
)
func Pembagian(nilai int, pembagi int) (int, error) {
if pembagi == 0 {
return 0, errors.New("Pembagian dengan angka Nol tidak diizinkan!")
}
return nilai / pembagi, nil
}
func main() {
hasil, err := Pembagian(100, 0)
if err != nil {
fmt.Println("Terjadi Error:", err.Error())
} else {
fmt.Println("Hasil Pembagian:", hasil)
}
}
51. Membuat Custom Error
Membuat struct error kustom sendiri dengan mengimplementasikan method Error() string.
Custom Error
Kita dapat membuat jenis error sendiri yang kaya informasi dengan membuat struct yang memiliki method Error() string.
Contoh program
package main
import "fmt"
type validationError struct {
Message string
}
func (v *validationError) Error() string {
return v.Message
}
func SaveData(id string) error {
if id == "" {
return &validationError{"ID tidak boleh kosong!"}
}
return nil
}
func main() {
err := SaveData("")
if err != nil {
// Type assertion untuk custom error
if valErr, ok := err.(*validationError); ok {
fmt.Println("Custom Validation Error:", valErr.Message)
} else {
fmt.Println("Unknown Error:", err)
}
}
}
52. Rangkuman Modul Dasar
Kesimpulan materi Golang Dasar dan jembatan menuju materi Golang Standard Library.
Selamat! Modul Golang Dasar Selesai 🎉
Anda telah mempelajari seluruh fondasi dasar bahasa pemrograman Go. Selanjutnya, mari kita pelajari pustaka bawaan resmi Go di Modul 2: Golang Standard Library!
Contoh program
package main
import "fmt"
func main() {
fmt.Println("Modul 1 Golang Dasar Selesai!")
fmt.Println("Lanjutkan ke Bab 53 untuk mempelajari Golang Standard Library!")
}