BAB 15: Membuat Program Modular dengan Function di Golang - Abd. Asis

BAB 15: Membuat Program Modular dengan Function di Golang

Setelah kamu paham cara menyimpan data dengan map, sekarang waktunya belajar function—blok kode yang bisa dipakai berulang kali. Dengan function, program kamu jadi lebih terstruktur dan gampang dikembangkan.

Apa Itu Function?

Function adalah kumpulan kode yang diberi nama, bisa dipanggil berkali-kali, dan biasanya menerima input (parameter) serta menghasilkan output (return value). Analogi sederhananya: function itu seperti resep masakan—ada bahan (parameter), ada proses, dan ada hasil akhir (output).

Kenapa Perlu Function?

Tanpa function, kode akan berulang dan susah dipelihara. Dengan function, kamu bisa:

  • Menghindari duplikasi kode
  • Membuat program lebih rapi dan modular
  • Memudahkan debugging dan pengembangan

Cara Membuat Function di Golang

Deklarasi Function Sederhana

func sapa(nama string) {
    fmt.Printf("Halo %s!\n", nama)
}

Memanggil Function

sapa("Budi")
sapa("Sari")

Output:

Halo Budi!
Halo Sari!

Function dengan Return Value

Function bisa mengembalikan nilai, misal menghitung jumlah dua angka.

func tambah(a int, b int) int {
    return a + b
}

hasil := tambah(5, 3)
fmt.Println("Hasil penjumlahan:", hasil)

Output:

Hasil penjumlahan: 8

Function dengan Multiple Parameter

Kamu bisa membuat function dengan banyak parameter sesuai kebutuhan.

func biodata(nama string, umur int) {
    fmt.Printf("Nama: %s, Umur: %d tahun\n", nama, umur)
}

biodata("Andi", 17)

Output:

Nama: Andi, Umur: 17 tahun

Function dengan Multiple Return Value

Golang mendukung function yang mengembalikan lebih dari satu nilai.

func hitung(a, b int) (int, int) {
    jumlah := a + b
    selisih := a - b
    return jumlah, selisih
}

j, s := hitung(10, 4)
fmt.Println("Jumlah:", j)
fmt.Println("Selisih:", s)

Output:

Jumlah: 14
Selisih: 6

Function Tanpa Parameter dan Return

Kadang kamu butuh function yang hanya menjalankan aksi tanpa input/output.

func salam() {
    fmt.Println("Selamat belajar Golang!")
}

salam()

Output:

Selamat belajar Golang!

Latihan: Program Modular dengan Function

Buat program yang memisahkan logika ke dalam beberapa function.

package main

import "fmt"

func sapa(nama string) {
    fmt.Printf("Halo %s!\n", nama)
}

func hitungNilai(uts, uas int) int {
    return (uts + uas) / 2
}

func main() {
    sapa("Rina")
    nilaiAkhir := hitungNilai(80, 90)
    fmt.Println("Nilai akhir Rina:", nilaiAkhir)
}

Output:

Halo Rina!
Nilai akhir Rina: 85

Fungsi Variadic

Fungsi variadic adalah function yang bisa menerima parameter dalam jumlah tak terbatas, selama tipe datanya sama. Cocok untuk kasus seperti penjumlahan banyak angka sekaligus.

func calculate(numbers ...int) float64 {
    var total int = 0
    for _, number := range numbers {
        total += number
    }
    var avg = float64(total) / float64(len(numbers))
    return avg
}

func main() {
    var avg = calculate(2, 4, 3, 5, 4, 3, 3, 5, 5, 3)
    fmt.Printf("Rata-rata : %.2f\n", avg)
}

Kamu juga bisa mengirimkan slice sebagai parameter variadic:

var numbers = []int{2, 4, 3, 5, 4, 3, 3, 5, 5, 3}
var avg = calculate(numbers...)

Parameter variadic harus selalu di posisi terakhir pada deklarasi function.

Fungsi Anonymous dan Closure

Fungsi anonymous adalah function tanpa nama, biasanya digunakan untuk logika sederhana atau sebagai closure.

f := func(x, y int) int { return x + y }
fmt.Println(f(2, 3)) // Output: 5

func(msg string) {
    fmt.Println(msg)
}("Hello dari function anonymous!")

Closure adalah function yang bisa mengakses variabel di sekitarnya:

func buatCounter() func() int {
    hitung := 0
    return func() int {
        hitung++
        return hitung
    }
}

counter := buatCounter()
fmt.Println(counter()) // Output: 1
fmt.Println(counter()) // Output: 2

Fungsi Generic (Go 1.18+)

Mulai Go 1.18, kamu bisa membuat function generic yang menerima tipe data berbeda:

func sum[T int | float64](a, b T) T {
    return a + b
}

fmt.Println(sum(2, 3))       // Output: 5
fmt.Println(sum(2.5, 3.1))   // Output: 5.6

Praktik Terbaik Function di Golang

  • Gunakan nama function yang jelas dan deskriptif
  • Pisahkan logika ke function kecil agar mudah diuji
  • Hindari terlalu banyak parameter, gunakan struct jika perlu
  • Tambahkan komentar singkat untuk menjelaskan fungsi

Studi Kasus: Modularisasi Program

Contoh program kalkulator modular:

package main

import "fmt"

func tambah(a, b int) int {
    return a + b
}


func kurang(a, b int) int {
    return a - b
}

func main() {
    fmt.Println("Tambah:", tambah(10, 5))
    fmt.Println("Kurang:", kurang(10, 5))
}

Output:

Tambah: 15
Kurang: 5

Fungsi Sebagai Parameter

Di Go, fungsi bisa dijadikan sebagai parameter pada fungsi lain. Teknik ini sangat berguna untuk membuat kode yang fleksibel dan reusable, misalnya untuk filtering data.

Penerapan Fungsi Sebagai Parameter

Cara membuat parameter fungsi adalah dengan langsung menuliskan skema fungsi sebagai tipe data parameter. Contoh:

func filter(data []string, callback func(string) bool) []string {
    var result []string
    for _, each := range data {
        if filtered := callback(each); filtered {
            result = append(result, each)
        }
    }
    return result
}

func main() {
    var data = []string{"wick", "jason", "ethan"}
    var dataContainsO = filter(data, func(each string) bool {
        return strings.Contains(each, "o")
    })
    var dataLength5 = filter(data, func(each string) bool {
        return len(each) == 5
    })

    fmt.Println("data asli :", data)
    fmt.Println("filter ada huruf 'o' :", dataContainsO)
    fmt.Println("filter jumlah huruf '5' :", dataLength5)
}

Output:

data asli : [wick jason ethan]
filter ada huruf 'o' : [jason]
filter jumlah huruf '5' : [jason ethan]

Pada contoh di atas, parameter kedua fungsi filter adalah closure yang menentukan kondisi filter. Closure ini dipanggil di setiap perulangan untuk menentukan apakah data lolos filter.

Alias Skema Closure

Jika skema closure cukup panjang, lebih baik menggunakan alias dengan keyword type agar kode lebih rapi dan mudah digunakan ulang.

type FilterCallback func(string) bool

func filter(data []string, callback FilterCallback) []string {
    // ...
}

Penjelasan Tambahan

Fungsi strings.Contains() digunakan untuk mendeteksi apakah sebuah substring adalah bagian dari string. Contoh:

var result = strings.Contains("Golang", "ang") // true

Variabel result bernilai true karena “ang” merupakan bagian dari “Golang”.

Ringkasan

Function adalah pondasi utama untuk membuat program Golang yang rapi, modular, dan mudah dikembangkan. Dengan memahami function, kamu siap membangun aplikasi yang scalable dan maintainable.

Di bab berikutnya, kita akan membahas error handling—cara menangani dan memperbaiki error agar program Golang kamu makin tangguh!

Pointer

Pointer adalah reference atau alamat memori. Variabel pointer berarti variabel yang berisi alamat memori suatu nilai. Misal sebuah variabel bertipe integer memiliki nilai 4, maka pointer adalah alamat memori di mana nilai 4 disimpan, bukan nilai 4 itu sendiri.

Variabel-variabel yang memiliki reference atau alamat pointer yang sama, saling berhubungan satu sama lain dan nilainya pasti sama. Ketika ada perubahan nilai, maka akan memberikan efek kepada variabel lain (yang referensi-nya sama) yaitu nilainya ikut berubah.

Penerapan Pointer

Variabel bertipe pointer ditandai dengan adanya tanda asterisk (*) sebelum tipe data saat deklarasi:

var number *int
var name *string

Nilai default variabel pointer adalah nil (kosong). Variabel pointer tidak bisa menampung nilai yang bukan pointer, dan sebaliknya variabel biasa tidak bisa menampung nilai pointer.

Ada dua hal penting tentang pointer:

  • Variabel biasa bisa diambil nilai pointernya dengan tanda ampersand (&) sebelum nama variabel (referencing).
  • Nilai asli variabel pointer bisa diambil dengan tanda asterisk (*) sebelum nama variabel (dereferencing).

Contoh:

var numberA int = 4
var numberB *int = &numberA

fmt.Println("numberA (value)   :", numberA)  // 4
fmt.Println("numberA (address) :", &numberA) // 0xc20800a220

fmt.Println("numberB (value)   :", *numberB) // 4
fmt.Println("numberB (address) :", numberB)  // 0xc20800a220

Variabel numberB dideklarasikan bertipe pointer int dengan nilai awal referensi ke numberA (&numberA). Dengan ini, numberA dan numberB menampung data dengan referensi alamat memori yang sama.

Jika variabel pointer di-print, hasilnya adalah string alamat memori (notasi heksadesimal). Nilai asli variabel pointer bisa didapatkan dengan dereference (*numberB).

Efek Perubahan Nilai Pointer

Jika salah satu variabel pointer diubah nilainya, variabel lain yang memiliki referensi memori sama juga akan berubah.

var numberA int = 4
var numberB *int = &numberA

fmt.Println("numberA (value)   :", numberA)
fmt.Println("numberA (address) :", &numberA)
fmt.Println("numberB (value)   :", *numberB)
fmt.Println("numberB (address) :", numberB)

fmt.Println("")

numberA = 5

fmt.Println("numberA (value)   :", numberA)
fmt.Println("numberA (address) :", &numberA)
fmt.Println("numberB (value)   :", *numberB)
fmt.Println("numberB (address) :", numberB)

Perubahan pada numberA membuat nilai asli numberB ikut berubah menjadi 5 karena referensi memori yang sama.

Parameter Pointer

Parameter fungsi juga bisa dirancang sebagai pointer. Caranya dengan mendeklarasikan parameter sebagai pointer:

package main

import "fmt"

func main() {
    var number = 4
    fmt.Println("before :", number) // 4

    change(&number, 10)
    fmt.Println("after  :", number) // 10
}

func change(original *int, value int) {
    *original = value
}

Fungsi change() memiliki parameter pointer dan mengubah nilai asli variabel yang direferensikan. Perubahan pada pointer di fungsi akan mengubah nilai variabel di luar fungsi.


### Penjelasan Tambahan

Fungsi `strings.Contains()` digunakan untuk mendeteksi apakah sebuah substring adalah bagian dari string. Contoh:

```go
var result = strings.Contains("Golang", "ang") // true

Variabel result bernilai true karena “ang” merupakan bagian dari “Golang”.

Function adalah pondasi utama untuk membuat program Golang yang rapi, modular, dan mudah dikembangkan. Dengan memahami function, kamu siap membangun aplikasi yang scalable dan maintainable.