Saat ini Santekno akan membahas tentang penanganan Error pada bahasa Golang. Kita akan mempelajari dari penanganan yang mudah sampai beberapa implementasi yang begitu kompleks. Golang sudah menyediakan penanganan Error
dengan mudah, kita bisa juga melakukan modifikasi sedikit agar Error
tersebut bisa lebih mudah dipahami oleh kita sendiri dan orang yang nantinya akan berkolaborasi dengan kita. Hal yang pertama yang akan kita lakukan yaitu dengan mengkostumisasi Error
bawaan dari golang.
Golang menyediakan interface
sederhana untuk penanganan Error
, setiap ada Error
yang akan dikembalikan oleh golang mengikuti definisi interface
teserbut.
type error interface{
Error() string
}
Membuat Kustom (Custom) Error
Golang
package main
import(
"errors"
"fmt"
)
func hitungArea(radius int)(int, error){
if radius < 0 {
return 0, errors.New("Tidak boleh kurang dari nol")
}
return radius * radius, nil
}
func main() {
area, err := hitungArea(-1);
if err != nil {
fmt.Println("Terdapat kesalahan...")
return
}
fmt.Println(area)
}
Kode diatas, kita akan mengikuti skenario untuk menghitung area dalam sebuah lingkaran, kita perlu memastikan bahwa radius
itu tidak boleh nilai-nya negatif atau bisa kita bilang kurang dari nol. Jika radius
yang dikirimkan nilainya negatif maka akan nilai yang dikembalikan adalah “0” dan pesan Error
yang sudah didefinisikan.
Pada fungsi hitungArea()
terdapat jika dipanggil di fungsi main
maka akan mengembalikan 2 nilai yaitu, pertama nilai perhitungannya dan kedua objek Error
. Untuk melakukan kustomisasi Error
pada fungsi hitungArea()
tersebut perlu ditambahkan pengecekan, jika objek err
tidak sama dengan nil
maka kita akan menampilkan informasi kesalahan yang bisa kita pahami. Terbayang jika kita memiliki Error
yang tidak dikustomisasi kadang kita tidak tahu sebelah mana Error
itu terjadi.
Ada sedikit trik dari Santekno juga, biasanya untuk melakukan kostumisasi tersebut kita juga perlu membutuhkan informasi Error
yang terdapat pada fungsi hitungArea()
juga karena bisa jadi jika kita melakukan kustomisasi ini, malah Error
yang aslinya kita tidak tahu maksud kesalahannya seperti apa, maka pada fungsi main
kita lakukan penambahan informasi Error
tersebut dengan cara seperti dibawah ini:
func main() {
area, err := hitungArea(-1);
if err != nil {
fmt.Printf("Terdapat kesalahan. Err: %s", err)
return
}
fmt.Println(area)
}
Mengenal “Defer”
Kita akan membahas terlebih dahulu tentang defer
. Lihat contoh kode dibawah ini agar bisa lebih mudah untuk memahaminya
package main
import "fmt"
func balikPesan() {
fmt.Println("Ini contoh simple penggunaan fungsi Defer")
}
func main() {
defer balikPesan()
fmt.Println("Ini baris pertama")
fmt.Println("Ini baris kedua")
fmt.Println("Ini baris ketiga")
}
Kode diatas kita menggunakan defer
untuk memanggil fungsi balikPesan()
yang kita simpan di awal sebelum kita mencetak tiap baris informasi seperti kode diatas. Seperti apakah hasil cetak kode diatas? Coba bisa ada yang bisa tebak?
Seperti inilah ketika kode diatas dijalankan
Meskipun dipanggil di paling atas pada main()
tetapi fungsi balikPesan()
tersebut dijalankan setelah baris-baris pada fungsi main()
selesai. Maka fungsi balikPesan()
tersebut dijalankan diakhir fungsi tersebut. Dan begitulah cara kerja dari defer
pada golang.
Mengenal “Panic”
Panic
biasanya digunakan untuk menghentikan program dengan informasi pesan yang sudah di kustomisasi. Ketika kita memanggil panic
instruksi pada program akan menjalankan seperti berikut ini
- Fungsi yang saat ini sedang berjalan akan diberhentikan (stop)
- Fungsi apapun yang dipanggil dengan
defer
akan dijalankan terlebih dahulu - Eksekusi program akan berhenti
Berikut ini kode sederhana dari penggunaan panic
package main
import "fmt"
func jalankanPanic(){
panic("Ini contoh pesan pada situasi Panic")
fmt.Println("fungsi ini berjalan dengan selesai")
}
func main(){
jalankanPanic()
fmt.Println("fungsi main berjalan sampai selesai")
}
Kode diatas kita memanggil fungsi panic
di dalam fungsi jalankanPanic()
. Setelah program dijalankan, maka akan berhenti secara tiba-tiba terminated
. Bisa dilihat dari hasil program diatas seperti ini
Program keluar pada baris ke-6 ketika menjalankan fungsi panic
berjalan. Fungsi panic
adalah cara lain untuk memberi tahu program tentang terjadi kesalahan dan menginstruksikan untuk mengakhiri dengan pesan kesalahan khusus.
Menambahkan “Defer” ke dalam fungsi “Panic”
Seperti yang telah dijelaskan, setiap kali fungsi panic
dijalankan fungsi yang menggunakan defer
akan dijalankan terlebih dahulu sampai selesai. Mari kita lihat contoh kode programnya dibawah ini
package main
import "fmt"
func lakukanRecovery(){
fmt.Println("Fungsi ini untuk melakukan recovery")
}
func jalankanPanic(){
defer lakukanRecovery()
panic("Ini contoh pesan pada situasi Panic")
fmt.Println("fungsi ini berjalan dengan selesai")
}
func main(){
jalankanPanic()
fmt.Println("fungsi main berjalan sampai selesai")
}
Bagaimanakah hasil program diatas setelah dijalankan? Penasaran? Sesuai informasi yang disinggung diatas, hasilnya adalah fungsi dibawah defer
akan dijalankan terlebih dahulu, mari kita lihat dibawah ini
Pada baris ke-11, panic
berjalan, maka fungsi defer
akan dijalankan terlebih dahulu sebelum diberhentikan. Begitu panic
muncul, maka akan mencari semua fungsi defer
agar dijalankan sebelum diberhentikan.
Menggunakan “Recovery”
Setelah situasi panic
terjadi, maka program akan berhenti. Sejatinya di dunia nyata, aplikasi yang berhenti karena kesalahan itu tidak baik. Maka perlu mekanisme untuk melakukan pemulihan dari kesalahan tersebut. Kita perlu mengkondisikan pemulihan untuk menghindari pemberhentian aplikasi yang tidak diinginkan.
Fungsi defer
selalu dijalankan saat fungsi itu sedang terjadi panic
atau tidak terjadi panic
Maka kita akan membuat skenario pemulihan (recovery) di dalam fungsi defer
.
Mendeteksi situasi panic
Dalam fungsi defer
kita harus melakukan pengecekan apakah eksekusi fungsi mengalami panic
atau tidak. Untuk mendeteksi ini, kita akan menjalankan fungsi recover()
. Setelah kita menjalan kan fungsi tersebut, kita akan mendapatkan informasi pesan kesalahan yang sama dengan nilai parameter yang diteruskan ke fungsi panic
. Pesan tersebut akan dikembalikan sebagai output
fungsi dari recover()
lalu tidak akan mengijinkan untuk di hentikan tetapi akan terkontrol dan fungsi yang memanggil itu akan berjalan secara normal. Kita lihat langsung contoh programnya
package main
import "fmt"
func lakukanRecovery() {
if pesanRecover := recover(); pesanRecover != nil {
fmt.Println(pesanRecover)
}
fmt.Println("Fungsi ini untuk melakukan recovery")
}
func jalankanPanic() {
defer lakukanRecovery()
panic("Ini contoh pesan pada situasi Panic")
fmt.Println("fungsi ini berjalan dengan selesai")
}
func main() {
jalankanPanic()
fmt.Println("fungsi main berjalan sampai selesai")
}
Setelah dijalankan program diatas, maka hasilnya program tersebut akan memberikan pesan informasi panic
tetapi program tetap berjalan sampai akhir tanpa program tersebut berhenti. Bisa dilihat dibawah ini
Kesimpulan
Penanganan kesalahan pada golang memang terlihat berbeda dibandingkan dengan bahasa lain. Maka perlu kita tahu beberapa hal yg harus diperhatikan untuk melakukan penanganan Error
tersebut. Mekanisme untuk recovery
pun harus kita pikirkan bagaimana agar program kita tetap terus berjalan tidak berhenti seketika jika terjadi kesalahan yang mengakibatkan situasi panic
.