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 Sederhana | Hanya ~25 keyword, mudah dipelajari dan dibaca |
| Kompilasi Cepat | Compile ke binary native, sangat cepat dieksekusi |
| Concurrency Built-in | Goroutines dan channels untuk paralelisme mudah |
| Garbage Collection | Manajemen memori otomatis, tidak perlu manual free |
| Cross-Platform | Bisa compile ke berbagai OS dan arsitektur |
| Standar Library Kuat | HTTP, JSON, file I/O, crypto β semua built-in |
| Statically Typed | Type safety saat compile, mengurangi bug runtime |
| Gratis & Open Source | Dikembangkan secara terbuka oleh komunitas global |
Go vs Bahasa Lain
| Aspek | Go | Python | Java |
|---|---|---|---|
| Tipe | Compiled | Interpreted | Compiled + Interpreted |
| Typing | Static | Dynamic | Static |
| Sintaks | π’ Sangat Sederhana | π’ Mudah | π΄ Verbose |
| Kecepatan | π’ Sangat Cepat | π‘ Lambat | π’ Cepat |
| Concurrency | π’ Goroutines | π‘ GIL Limitasi | π‘ Threads |
| Cocok untuk | Backend, Cloud, DevOps | AI, Data, Otomasi | Enterprise, Android |
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β 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
# 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
# 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)
# 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
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
# 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 .
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
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 |
|---|---|---|
int | 42, -10, 0 | Bilangan bulat (platform-dependent: 32/64 bit) |
int8, int16, int32, int64 | int64(100) | Bilangan bulat dengan ukuran spesifik |
uint | 42, 0 | Unsigned integer (hanya positif) |
float32, float64 | 3.14, -0.5 | Bilangan desimal |
string | "hello" | String / teks (immutable) |
bool | true, false | Boolean / logika benar-salah |
byte | byte('A') | Alias untuk uint8 |
rune | rune('ε') | Alias untuk int32 (Unicode code point) |
String dan Konversi Tipe
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
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
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
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!)
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()
}
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
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
}
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
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
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.
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.
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")
}
}
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.
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.
# 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
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: