- Pengulangan
if err != nil di Go telah lama menjadi keluhan besar dalam survei pengguna selama bertahun-tahun, tetapi tim Go memutuskan untuk sementara tidak mendorong perubahan sintaks penanganan error
- Proposal
check/handle pada 2018, try pada 2019, dan ? pada 2024 semuanya gagal mencapai konsensus yang memadai, dan khususnya try memicu penolakan kuat karena alur kontrol yang tersembunyi
- Dalam prosedur proposal Go, jika tidak ada konsensus umum maka proposal biasanya ditolak, dan bahkan di antara anggota senior tim Go di Google saat ini tidak ada suara bulat mengenai arah terbaik
- Pihak yang mendukung status quo menilai Go sudah memiliki cara penanganan error yang berfungsi, dan sintaks baru akan menimbulkan biaya besar pada gaya kode, debugging, dokumentasi, tooling, dan kode yang sudah ada
- Tim Go akan menutup proposal terbuka dan proposal baru yang terutama menargetkan sintaks penanganan error tanpa penyelidikan tambahan, dan akan fokus pada peluang perbaikan lain sampai ada pemahaman masalah yang lebih jelas
Keluhan lama yang dibuat oleh if err != nil
- Salah satu keluhan paling lama di Go adalah kepanjangan kode penanganan error
- Pola representatifnya berbentuk seperti berikut
x, err := call()
if err != nil {
// handle err
}
- Dalam program dengan banyak pemanggilan API dan error yang hanya dikembalikan begitu saja,
if err != nil dapat mendominasi sisa kode
- Pada fungsi contoh
printSum, dari 10 baris isi fungsi, baris yang tampak sebagai pekerjaan sebenarnya hanya 4 baris termasuk pemanggilan, output, dan return, sedangkan 6 baris sisanya tampak seperti kebisingan
- Dalam survei pengguna tahunan Go, penanganan error selama bertahun-tahun menjadi keluhan teratas; untuk sementara ketiadaan generics mengunggulinya, tetapi setelah Go mendukung generics, penanganan error kembali menjadi keluhan teratas
Tiga proposal sintaks utama
- Upaya eksplisit pertama tim Go dimulai pada 2018 sebagai bagian dari upaya Go 2, ketika Russ Cox merangkum masalahnya secara resmi
- Rancangan desain oleh Marcel van Lohuizen didasarkan pada mekanisme
check dan handle, serta mencakup analisis pendekatan bahasa lain dan alternatif
func printSum(a, b string) error {
handle err { return err }
x := check strconv.Atoi(a)
y := check strconv.Atoi(b)
fmt.Println("result:", x + y)
return nil
}
- Pendekatan
check/handle dinilai terlalu kompleks, dan pada 2019 muncul proposal try yang lebih sederhana
- Kata kunci mirip
check menjadi fungsi bawaan try
- Bagian
handle dihilangkan
- Dibuat alat tryhard untuk mengubah kode penanganan error yang ada ke gaya
try
- Issue GitHub terkait diperdebatkan dengan sengit hingga hampir 900 komentar
func printSum(a, b string) error {
// use a defer statement to augment errors before returning
x := try(strconv.Atoi(a))
y := try(strconv.Atoi(b))
fmt.Println("result:", x + y)
return nil
}
try memengaruhi alur kontrol dengan cara mengembalikan dari fungsi yang melingkupinya saat terjadi error, dan karena return bisa terjadi bahkan di dalam ekspresi yang bersarang dalam, banyak pengguna merasa sulit menerimanya
- Saat itu, memperkenalkan kata kunci baru mungkin akan lebih baik, dan sekarang versi bahasa dapat dikendalikan lebih rinci melalui file
go.mod dan direktif per file
- Proposal terbaru dari Jimmy Frasche mengikuti arah kembali ke desain
check/handle semula sambil menangani sebagian kelemahannya
Refleksi prosedur setelah try dan proposal ?
- Setelah proposal
try, Russ Cox meninjau kembali proses proposal melalui seri “Thinking about the Go Proposal Process”
- “Go Proposal Process: Large Changes” menilai bahwa
try seharusnya menjadi rancangan desain kedua, bukan proposal dengan jadwal implementasi
- Selama beberapa tahun setelah itu, tim Go tidak mendorong perubahan sintaks penanganan error, sementara di komunitas terus masuk proposal yang serupa, menarik, sulit dipahami, atau tidak layak diwujudkan
- Ian Lance Taylor membuat umbrella issue yang merangkum status proposal perbaikan penanganan error, dan Go Wiki juga dibuat untuk mengumpulkan umpan balik dan diskusi terkait
- “go error handling proposals” oleh Sean K. H. Liao melacak banyak proposal penanganan error selama bertahun-tahun
- Karena keluhan terus berlanjut, Ian Lance Taylor pada 2024 mengumumkan proposal untuk mengurangi boilerplate penanganan error dengan
?
- Notasi itu dipinjam dari operator
? di Rust
- Dalam studi pengguna informal skala kecil, sebagian besar peserta menebak dengan benar arti kode Go yang menggunakan
?
- Juga dibuat alat untuk mengubah kode Go umum ke sintaks baru dan prototipe compiler
func printSum(a, b string) error {
x := strconv.Atoi(a) ?
y := strconv.Atoi(b) ?
fmt.Println("result:", x + y)
return nil
}
- Proposal ini juga dengan cepat dibanjiri banyak komentar dan usulan perubahan detail berbasis preferensi, lalu Ian menutup proposal tersebut dan memindahkan isinya ke discussion
- Versi yang sedikit direvisi mendapat reaksi yang agak lebih positif, tetapi tetap tidak memperoleh dukungan luas
Mengapa sekarang ingin berhenti
- Tim Go menilai bahwa untuk masa depan yang dapat diperkirakan, mereka harus berhenti mencoba menyelesaikan masalah sintaks penanganan error
- Proses proposal mendukung keputusan ini
- Tujuan proses proposal adalah mencapai konsensus umum atas hasil secara tepat waktu
- Jika konsensus umum tidak ditemukan dalam diskusi issue tracker, proposal biasanya ditolak
- Jika tidak ditemukan konsensus maupun langkah berikutnya, arsitek Go akan meninjau diskusi dan mencoba mencapai konsensus internal
- Tidak ada proposal penanganan error yang mendekati dukungan berbasis konsensus, dan semuanya ditolak
- Bahkan anggota senior tim Go di Google pun tidak bulat tentang arah terbaik ke depan, dan tanpa konsensus yang kuat mereka tidak dapat melanjutkan secara masuk akal
Argumen untuk status quo dan perubahan
- Di pihak status quo, ada alasan praktis berupa kematangan Go dan biaya ekosistem
- Jika Go sejak awal memperkenalkan sugar sintaks khusus untuk penanganan error, perdebatan sekarang mungkin akan lebih kecil, tetapi Go sudah berusia 15 tahun dan telah memiliki cara penanganan error yang berfungsi
- Bahkan jika solusi sempurna ditemukan sekarang, situasinya bisa berubah dari pendukung perubahan yang tidak puas menjadi pendukung status quo yang tidak puas
- Generics tidak wajib ditulis langsung oleh pengguna, tetapi sintaks baru untuk penanganan error bisa membuat kode terlihat tidak idiomatis jika tidak dipakai, sehingga pada praktiknya hampir semua orang harus menggunakannya
- Menambahkan sintaks baru juga bisa bertentangan dengan aturan desain Go yang tidak menyediakan banyak cara untuk melakukan hal yang sama
- Fitur redeklarasi pada deklarasi variabel singkat
:= diperkenalkan untuk menyelesaikan masalah yang timbul karena penanganan error
- Tanpa redeklarasi, setiap pemeriksaan error berurutan akan memerlukan nama
err yang berbeda atau deklarasi variabel terpisah
- Jika saat itu sudah ada dukungan sintaks yang lebih baik untuk penanganan error, aturan redeklarasi dan kompleksitas terkait mungkin tidak diperlukan
- Jika error diperkaya dan ditangani dengan benar, porsi pengulangan sederhana akan berkurang
- Dalam survei pengguna ada masukan berulang bahwa error tidak memiliki stack trace
- Dimungkinkan memakai fungsi pembantu untuk membuat dan mengembalikan error yang telah diperkaya
- Menambahkan informasi input seperti
fmt.Errorf("invalid integer: %q", a) membuat proporsi relatif boilerplate menjadi lebih kecil
- Fitur pustaka standar juga dapat mengurangi boilerplate penanganan error
- Ini sejalan dengan “Errors are values” oleh Rob Pike
- Dalam beberapa kasus, beberapa error dapat ditangani sekaligus dengan
cmp.Or
- Menulis, membaca, dan debugging adalah aktivitas yang berbeda
- Menulis pemeriksaan error berulang memang membosankan, tetapi penyelesaian kode berbantuan IDE dan LLM dapat dengan mudah menghasilkan pemeriksaan error dasar
- Saat membaca, kepanjangan lebih menonjol, dan IDE dapat menyediakan toggle untuk menyembunyikan kode penanganan error
- Saat debugging, keberadaan pernyataan
if terpisah memudahkan penambahan println atau pemasangan breakpoint
- Jika penanganan error disembunyikan di balik
check, try, atau ?, sering kali perlu dikembalikan ke bentuk if biasa, dan proses ini dapat memperumit debugging atau menimbulkan bug halus
- Perubahan bahasa membawa biaya bukan hanya pada desain dan implementasi, tetapi juga pada perubahan kode yang ada, pembaruan dokumentasi, dan penyesuaian tooling
- Tim Go relatif kecil dan juga memiliki banyak prioritas lain yang harus ditangani
- Prioritas dan ukuran tim bisa berubah
- Sebagian pengguna Go yang ditemui tim Go di Google Cloud Next 2025 menyatakan dengan tegas bahwa bahasa ini tidak boleh diubah demi penanganan error yang lebih baik
- Mereka mengatakan bahwa saat baru pindah dari bahasa lain, ketiadaan sintaks khusus penanganan error di Go memang paling menonjol, tetapi setelah menulis kode Go yang lebih idiomatis hal itu menjadi kurang penting
- Sampel ini tidak cukup besar untuk representatif, tetapi bisa jadi merupakan kelompok yang berbeda dari orang-orang yang terlihat di GitHub
- Argumen yang mendukung perubahan juga tetap berlaku
- Ketiadaan dukungan penanganan error yang lebih baik tetap menjadi keluhan teratas dalam survei pengguna
- Pendekatan yang hanya berfokus mengurangi jumlah karakter mungkin merupakan arah yang keliru
- Jika penanganan error dasar dibuat mencolok secara visual lewat kata kunci sambil menghapus boilerplate
err != nil, akan lebih mudah memeriksa dalam code review apakah error sudah ditangani
- Masih belum cukup diketahui apakah inti masalahnya hanya kepanjangan sintaks, atau justru kepanjangan dari penanganan error yang baik saat menyusun error yang bermakna bagi API, developer, dan pengguna akhir
Keputusan tim Go
- Sampai sekarang, tidak ada upaya untuk menangani penanganan error yang memperoleh momentum yang cukup
- Tim Go menilai ada kekurangan pemahaman bersama atas masalah, dan bahkan tidak semua orang sepakat bahwa memang ada masalah sejak awal
- Untuk masa depan yang dapat diperkirakan, mereka tidak akan mendorong perubahan bahasa tingkat sintaks untuk penanganan error
- Proposal terbuka dan proposal yang akan datang yang terutama menargetkan sintaks penanganan error akan ditutup tanpa penyelidikan tambahan
- Eksplorasi dan diskusi komunitas memang tidak berujung pada perubahan sintaks penanganan error, tetapi telah menghasilkan berbagai perbaikan pada bahasa Go dan prosesnya
1 komentar
Opini Hacker News
Kalau ingin melontarkan usulan ringan seperti “seharusnya tim Go melakukan ini saja”, sebaiknya lihat dulu halaman wiki yang ditautkan di artikel, https://go.dev/wiki/Go2ErrorHandlingFeedback, dan pencarian issue GitHub https://github.com/golang/go/issues?q=+is%3Aissue+label%3Aerror-handling
Usulan yang hendak diajukan hampir pasti bukan yang pertama, dan kemungkinan besar banyak di antaranya sudah ditelaah secara mendalam
Saya menyukai pendekatan terbuka seperti ini dari tim Go, dan sampai sekarang masih senang memakai Go setiap hari untuk pekerjaan
Di beberapa halaman issue GitHub dengan komentar terbanyak pun saya tidak melihat hal serupa, dan rasanya berlebihan menganggap tim Go adalah penyihir desain bahasa sehingga solusi yang dilempar ringan oleh orang-orang di sini pasti sudah mereka pertimbangkan
Tim Go melakukan kesalahan yang sama seperti Java, yaitu bahasa bertipe statis tanpa polimorfisme parameter, dan akar masalah penanganan error ini juga ada di sana, tetapi mereka tampak angkat tangan dan tidak memperbaikinya
Kedengarannya mungkin megah dan mengintimidasi, tetapi itu adalah cara yang elegan dan murni secara fungsional untuk meneruskan error sampai ke tempat yang bisa menanganinya tanpa membuatnya terlupakan
Bagi orang yang menulis kode Haskell, cara ini sudah begitu mengakar, jadi sulit dipahami bahwa tidak ada orang di komunitas Go yang mengetahuinya dan menyukainya
Saya berterima kasih atas halaman itu sendiri dan tautannya, tetapi terasa membingungkan bahwa orang-orang yang begitu peduli pada bahasanya melewatkan solusi yang sudah sangat mapan seperti ini
Hampir semua bahasa punya cara masing-masing yang lebih baik, jadi saya ingin tahu apakah ini sekadar karena tidak bisa mengambil keputusan atau tidak bisa memuaskan semua orang, atau ada alasan konkret mengapa solusi dari bahasa lain tidak cocok untuk bahasa Go itu sendiri
Kenyataannya, hampir selalu para pembuat Go tahu jauh lebih banyak
Amatir secara naif mengira bahasa terbaik adalah yang dijejali fitur paling banyak, apalagi jika fitur itu sesuai selera mereka
Ini mirip seseorang yang baru mulai belajar membuat pisau, lalu melihat pisau koki Jepang dan merasa ada yang kurang, kemudian berpikir pisau itu akan lebih baik jika diberi gagang cetak 3D dengan lekukan jari, kompartemen rahasia, korek api, dan speaker Bluetooth
Buat saja daftar checklist, bahas dan isi tiap butirnya, lalu jangan keluarkan lagi kecuali ditemukan kesalahan semantik fatal atau celah soundness
Setelah semuanya terisi, implementasikan, dan orang-orang yang ribut apakah harus ditulis
.await,/await, atau.await!()akan menghilang lagiRust berjalan seperti ini; beberapa issue memang tertunda lebih dari 10 tahun, tetapi akhirnya butir-butirnya terisi dan distabilkan dari nightly terbaru
Kalau Go tidak bisa menyelesaikan satu masalah yang langsung dihadapi semua orang, padahal ada beberapa proposal matang, hanya karena tidak bisa memilih salah satunya dan menunggu bikeshedding berhenti, maka prosesnya itu komedi
Ia bukan sekadar kumpulan fitur yang ditambahkan begitu memenuhi persyaratan checklist
Apakah Rust akan menjadi berantakan seperti C++? Apakah Go akan tetap menjadi bahasa yang tak lekang oleh waktu seperti saat dirilis?
Dalam survei, persentase yang menyebut penanganan error adalah 13%, dan ada juga orang yang lebih menyukai cara yang sekarang apa adanya
https://go.dev/blog/survey2024-h1-results
Dulu saya pernah menulis fungsi Go yang agak unik, yang mengharapkan fungsi internal mengembalikan error
Jadi kalau fungsi internal tidak mengembalikan error, fungsi luar harus mengembalikan error dan melakukan penanganan lain; kalau fungsi internal mengembalikan error, fungsi luar harus mengembalikan nil
Singkatnya, saya harus menulis
if err == nil { // return an error }, bukanif err != nil { ... }, tetapi karena kebiasaan saya menulis yang pertama, dan butuh cukup lama untuk debugKarena saya sudah terlalu kebal terhadap
if err != nil, otak saya sama sekali tidak mempertimbangkan kemungkinan bahwa konstruksi itu tidak boleh ada di sanaJadi menurut saya ekspresi yang umum memang perlu syntactic sugar. Kalau perbedaan antara
if err != nilyang sangat umum danif err == nilyang jarang itu lebih menonjol, itu benar-benar akan membantuif err == nil, saya menambahkan komentar// invertedagar lebih mencolokAkan bagus kalau ditangani di level bahasa, tetapi setidaknya saya membagikannya sebagai cara untuk membuatnya lebih terlihat
if fruit != "Apple" { ... }juga bisa menciptakan situasi yang samaSaya penasaran apakah ada solusi umum untuk memperbaiki ini, dan melihatnya sebagai masalah khusus penanganan error rasanya agak meleset
Tidak ada yang istimewa atau unik pada error; itu hanya state seperti yang lain
Kalau muncul pola umum
if err == nil { return ... }, kali ini pola itulah yang akan bertebaran di kodeSolusi saat ini sudah baik, dan tampaknya terutama orang yang baru mulai memakai Go atau masih pemula yang tidak menyukainya
Di sekitar saya, orang menyukai penanganan error yang “verbose” karena eksplisit, jelas, dan mudah dibaca
if err != nilseperti satu simbol ligatur kecil, atau merendernya samar sebagai latarDengan begitu, bentuk yang berbeda persis dari string itu, seperti
if err == nil, justru akan lebih menonjolif err … {Saya suka penanganan error eksplisit di Go
Sebuah fungsi selalu berhasil, atau bisa berhasil maupun gagal. Fungsi yang selalu berhasil itu sederhana; jika fungsi yang bisa gagal ternyata gagal, kode di luarnya tidak bisa lanjut dalam keadaan gagal begitu saja, jadi harus menanganinya
Di sini bahasa-bahasa mulai bercabang. Banyak bahasa melempar exception, menaikkannya sampai ada yang secara eksplisit menangkapnya, dan menyediakan semacam stack trace
Di Go, saya suka bahwa saat menulis kode selalu ada pilihan yang harus diambil: mengabaikan error dan lanjut (
foo, _ := doSomething()), mengembalikan lebih awal tanpa informasi bermakna (return nil, err), mengembalikan lebih awal dengan konteks yang berguna, atau menafsirkan error yang diterima lalu bercabangMisalnya, jika baris yang akan diperbarui tidak ditemukan di database, lapisan service bisa mengembalikan error not found dan API menjadi 404, atau fungsi delete yang idempoten bisa menafsirkan not found sebagai sukses
Kalau Go 2 atau bahasa lain, saya ingin ada tipe Result ala Rust/Swift alih-alih tuple yang bisa nil, serta tipe error yang lebih bertipe dan bisa dienumerasi alih-alih selalu memakai
errorsecara langsungNamun jika Result ditambahkan di atas pengembalian tuple idiomatis Go 1, akan ada banyak cara melakukan hal yang sama sehingga menimbulkan kebingungan dan perpecahan; karena itu lebih cocok untuk Go 2 atau bahasa baru
Lapisan rendah dalam stack umumnya tidak tahu apa yang harus dilakukan, jadi tidak semestinya menangani error
Kebijakan “menangani” error pada akhirnya mudah berubah menjadi kebijakan membungkus error lalu mengembalikannya lagi ke atas stack, dan itu menjadi pekerjaan remeh yang cukup banyak
Go memungkinkan error diabaikan sepenuhnya, dan hasilnya bisa berujung pada crash
Agak sulit dimengerti bagaimana bisa seseorang menunjukkan dengan tepat syarat untuk membuat software yang tangguh, tetapi tetap menyukai cara Go menangani error
[1]: https://borgo-lang.github.io/ | https://github.com/borgo-lang/borgo
Semua bahasa fungsional, banyak bahasa modern seperti Rust, bahkan Java dengan checked exception pun menyediakan ini
Dalam bahasa yang punya generics, “penanganan error” ala Go umumnya bisa direplikasi, dan mungkin menghasilkan kode yang lebih baik
Kalau jawabannya JavaScript atau Python, itu memang pola perbandingan yang umum
Untuk Go, ini keputusan yang tepat. Saat pertama kali mengenal Go saya tidak suka penanganan error-nya, tetapi sekarang saya benar-benar menyukainya
Titik baliknya ada dua. Setelah membaca tulisan https://go.dev/blog/errors-are-values, saya benar-benar menerima sudut pandang “error adalah nilai”, dan di atas dasar itu saya juga membuat paket yang cukup populer, https://github.com/stytchauth/sqx
Selain itu, saya perlahan terbiasa memakai
panic(err)untuk state keliru yang benar-benar tidak masuk akalTidak ada alasan memaksa kode induk menangani semua state ngawur yang bahkan tidak punya naluri untuk ditangani; satu atau dua panic yang ditempatkan dengan baik bisa menghapus ratusan pemeriksaan error dari codebase
Misalnya, bayangkan persoalan seperti apakah ada logger default di dalam ctx
Justru besar kemungkinan akan membaik
bash juga punya
-eDulu saat pertama kali memakai C#, saya merasa pintar karena memahami alur try/catch/finally, using, nesting, apa yang terjadi kalau error muncul di catch, apa yang terjadi kalau muncul di finally
Sekarang saya lebih suka tidak memikirkan hal-hal seperti itu
Saya tidak suka cara tulisan ini mengatakan bahwa masalah utama penanganan error di Go adalah sintaksnya terlalu bertele-tele. Itu tidak terlalu saya pedulikan
Yang lebih penting adalah error bisa dibuang diam-diam atau terabaikan tanpa sengaja, hasil pemanggilan fungsi bukan sebuah nilai sehingga tidak mudah disimpan atau diteruskan, dan dibutuhkannya
errors.Is, sebuah mekanisme runtime aneh di mana seluruh error “berlapis” tidak cocok dengan sistem tipeSwitch untuk error juga sulit, standard library memakai nilai sentinel, dan interaksinya dengan generics buruk sehingga paket seperti errgroup jadi diperlukan
Apakah ada lagi yang terlewat?
Dalam bahasa yang punya exception, tidak ada orang yang akan melakukan itu
Mereka memutuskan untuk tidak lagi mencoba mengubah sintaks penanganan error dalam masa depan yang dapat diperkirakan, dan berkat itu ada perhatian untuk melihat masalah lain, baik soal error maupun topik lain
Evolusi Go bergerak selambat gletser, dan bagi banyak orang itu bukan bug, melainkan fitur
Penjelasan seperti “masukan survei bahwa error tidak punya stack trace bisa diselesaikan dengan membuat fungsi pembantu menghasilkan dan mengembalikan error yang diperkaya” terdengar konyol
Lucu bahwa menyediakan stack trace secara manual seperti
if err != nil { return fmt.Errorf("invalid integer: %q", a) }disebut “penanganan error”Kalau menurut definisi tim Go, exception berarti menangani error secara otomatis. Tentu saja di bahasa selain C++
Bisa saja begitu, tapi apakah semua itu benar-benar diperlukan? Bagaimana dengan biaya log?
Menurut saya, error terbungkus satu baris yang memangkas noise dari framework dan runtime jauh lebih baik
Jika dibungkus dengan baik, itu juga sangat mudah dicari, dan biasanya bisa dilacak lebih efektif daripada stack trace
Selama memakai Go penuh waktu lebih dari 10 tahun, saya tidak pernah sekalipun membutuhkan kebisingan panjang-lebar dari fungsi runtime atau call stack
Dari sudut pandang developer Elixir, ini terlihat gila
Di Erlang/Elixir, ini biasanya diselesaikan dengan fungsi mengembalikan tuple
{:ok, result}atau{:error, description_or_struct}Dengan statement
withmilik Elixir, penanganan error bisa dikumpulkan di bagian bawah sehingga jauh lebih mudah dibacaGo juga tinggal menambahkan padanan klausa
with, melanjutkan fungsi-fungsi selama error bernilai nil, lalu menaruh klausa penanganan error di bawahwithMenarik bahwa Go menunda sangat lama struktur-struktur dasar yang jelas bernilai seperti generics, penanganan error, dan manajemen paket karena kurangnya konsensus komunitas
Generics butuh 13 tahun setelah dirilis sebagai open source, 16 tahun kemudian penanganan error masih belum ada, dan manajemen paket memakan waktu sekitar 9 tahun
Pertimbangan matang memang bernilai, tetapi rilis juga bernilai. Orang-orang yang menulis 900 komentar GitHub pada akhirnya tetap akan memakai Go, dan kemungkinan memasukkan sesuatu ke bahasa lebih baik daripada terus menundanya
Fungsi dengan beberapa tipe return tidak bisa melakukan apa-apa selain ditugaskan ke variabel
Namun di Erlang dan Elixir, itu sepenuhnya idiomatis tanpa beban apa pun
Bahkan sebenarnya jauh lebih kuat daripada keluarga ML, karena sum type di sana bersifat terbuka
Saya tidak mengikuti diskusi ini secara mendetail, tetapi saya tidak mengerti kenapa mereka tidak langsung mengadopsi cara ala Rust saja
Setelah Go punya generics, cara itulah yang langsung saya tambahkan
Dalam tulisan yang ditautkan, yang terlihat hanya penjelasan bahwa “di Rust tidak ada padanan untuk handle, dan kemudahan operator
?berpotensi membuat orang melewatkan penanganan yang semestinya”Namun saya tidak paham kenapa sesuatu yang praktis berarti mengabaikan error
Separuh masalah dari cara Go adalah ia tidak memaksa apa pun terhadap hasil, dan hanya memaksa pemeriksaan error secara minimal
x, err := strconv.Atoi("123"); fmt.Println("result:", x)akan menghasilkandeclared and not used: err, tetapi setelah konversi kedua, meskierrtidak diperiksa, karena nilai defaultyadalah 0, program bisa berjalan baik-baik saja tanpa menyadari ada masalahBahkan jika dibiarkan kosong seperti
if err != nil { }, itu tetap dikompilasi dan dijalankan, dan kita tidak bisa tahu bahwa ada sesuatu yang salahJika nilai balik dibuat sebagai Result, maka dipaksa untuk mengambil keputusan. Kalaupun ada orang yang sembarangan memakai
!atau dengan mudah meneruskannya ke atas dengan?tanpa menangani kasus error, apakah berartipanicjuga akan dilarang?Dan karena obsesi aneh bahwa semua tipe harus punya zero value yang ditentukan, sum type pun tidak bisa ditambahkan
?nyaman dipakai, tidak akan ada lagi yang membungkus errorIni logika yang sangat meragukan
Dari awal,
?bisa saja dirancang agar mendorong pembungkusan errorMisalnya, padanan
Fromdi Rust seharusnya seperti apa di Go??visibilitasnya rendah, dan menyembunyikan percabangan alur kontrol di dalam satu statement atau expressionItu juga salah satu alasan Go menghilangkan operator ternary dan memilih statement
ifyang tiap cabangnya berada di baris terpisahMemasang breakpoint juga tidak mudah, dan ini membuat orang cenderung meneruskan error apa adanya ke atas alih-alih memperkaya atau menanganinya
:=adalah deklarasi sekaligus assignment dalam satu statement, tetapi di baris ke-5 contoh itu, bukankaherrdideklarasikan ulang danerrbaru menutupierrlama?Kalau begitu, karena variabel
errbaru tidak digunakan, seharusnya gagal dengandeclared and not used: errAtau kalau variabelnya sudah ada, apakah
:=hanya bertindak seperti assignment biasa?Pernyataan bahwa “tidak adanya stack trace pada error bisa diselesaikan dengan membuat helper function menghasilkan dan mengembalikan error yang sudah diperkaya” terlalu optimistis terhadap kenyataan
Bahasa yang memiliki stack trace memberikannya secara gratis, tetapi di Go kita harus mengimplementasikannya setiap kali
Anda sendiri mungkin developer yang disiplin dan selalu menambahkan detail, tetapi tidak semua anggota tim punya disiplin yang sama
Hal terbaik dari stack trace adalah ia memberi jalur pemanggilan sampai ke error
Jika error terjadi di method yang dipanggil dari banyak tempat, dengan stack trace kita bisa langsung tahu jalur mana yang ditempuh
Selama bertahun-tahun melakukan pekerjaan mirip sysadmin/SRE dan menyelesaikan banyak masalah, masalah yang mudah saat ada stack trace biasanya penyebabnya jelas dan selesai dalam 1–2 menit
Di Go, jika seseorang tidak memperkaya error atau menggunakan ulang pesan error yang sama, masalah yang mudah pun berubah menjadi pekerjaan deduksi dan memakan waktu lebih lama