3 poin oleh GN⁺ 2024-11-27 | 2 komentar | Bagikan ke WhatsApp
  • Sanggahan yang berulang dalam kritik terhadap Go—seperti “perusahaan besar juga memakainya”, “Go juga punya sisi baik”, dan “akurasi itu mahal”—dapat mengaburkan masalah bahwa cacat desain bahasa menumpuk menjadi biaya jangka panjang
  • Go kuat dalam runtime asinkron, GC, manajemen paket, refactoring, dan alat cross-compile, tetapi kita juga harus menerima toolchain dan sistem build kustom, calling convention, satu GC, serta ekosistemnya sekaligus
  • Karena tidak ada sum type, kontrol atas mutabilitas lemah, zero value, serta perilaku berbeda pada slice, map, dan channel nil, compiler tidak dapat menjaga banyak invariant
  • Tanpa cgo, sulit berintegrasi dengan bahasa dan alat lain; jika memakai cgo, muncul beban berupa GC dan aturan pointer, penyertaan runtime, serta library statis besar, sehingga batas jaringan menjadi titik integrasi yang paling realistis
  • Harapan bahwa “buat saja prototipe dengan Go lalu tulis ulang nanti” dalam praktiknya dapat memperbesar biaya operasional karena penulisan ulang dihindari, keterikatan dengan kode Go yang sudah ada, serta beban linter, dokumentasi, dan verifikasi manual

Logika pembelaan yang berulang terhadap kritik Go

  • Setelah artikel tahun 2020 I want off Mr Golang’s Wild Ride, reaksi seputar kritik terhadap Go terus berulang
    • Respons bahwa kasus Windows bukan area yang dikuasai Go
    • Respons bahwa sisi baik Go tidak disebutkan
    • Respons bahwa kompromi yang dipilih Go tidak dipahami
    • Respons bahwa karena perusahaan besar memakai Go, Go tidak mungkin seburuk itu
    • Respons bahwa biaya memodelkan masalah secara “benar” itu besar, sehingga pembahasan soal ketepatan menjadi tidak bermakna
    • Respons bahwa Rust juga punya kekurangan, sehingga kritik terhadap Go tidak valid
  • Intinya bukan apakah Go punya kelebihan, melainkan apakah logika pembelaan yang berulang agar Go terus dipakai justru menutupi biaya nyata

Cara menyerang kelayakan pengkritik terlebih dahulu

  • Ketika ada masukan yang tidak ingin didengar, menganggap orang yang menyampaikannya tidak kompeten atau punya motif tersembunyi membuat kita tidak perlu meninjau isinya
  • Menemukan masalah tidak selalu membutuhkan keahlian tinggi; developer senior justru bisa mengabaikan ketidaknyamanan yang sudah telanjur terbiasa
  • Developer junior dapat lebih cepat merasakan dan mempertanyakan hal yang janggal karena mereka belum terbiasa dengannya
  • Nilai masukan harus ditinjau berdasarkan apakah memang ada masalah, bukan berdasarkan siapa yang mengatakannya

Batasan argumen “perusahaan lain juga memakainya”

  • Dalam pemilihan teknologi, melihat apa yang dipakai perusahaan lain berguna untuk penemuan, tetapi tidak cukup sebagai dasar adopsi
  • Blog teknologi perusahaan biasanya sulit menampilkan biaya adopsi secara utuh
    • Sering ditulis setelah keputusan sudah dibuat
    • Bertujuan membuat citra perusahaan terlihat baik dan membantu perekrutan
    • Kritik teknologi yang tajam lebih sering datang dari individu daripada dari perusahaan
  • Penggunaan Go oleh Tailscale lebih dekat dengan contoh tim pakar Go yang mengetahui dan mampu menanggung biayanya
  • Penyebab rasa sakit yang terlihat pada netaddr.IP terkait dengan berbagai batasan Go
    • Karena Go tidak memiliki sum type, merepresentasikan tipe “IPv4 atau IPv6” terasa canggung
    • Slice dipakai sebagai struktur data umum dengan biaya 24 byte pada mesin 64-bit
    • Karena tidak ada operator overloading, muncul pembedaan seperti a == b dan a.equals(b)
    • Karena data immutable tidak didukung, kita harus meneruskan salinan dan berhati-hati terhadap perubahan internal
    • Karena sulit membuat newtype yang opaque, diperlukan paket terpisah dan jalan memutar lewat interface
  • Tim seperti Tailscale dapat menangani perilaku internal dan edge case Go secara mendalam, tetapi tidak semua organisasi memiliki pakar Go dan biaya engineering seperti Google atau Tailscale

Bagian yang memang dikerjakan Go dengan baik

  • Go menyediakan runtime asinkron yang cukup baik, default yang beropini kuat, GC modern dengan dua knob penyetelan, dan toolchain yang baik
  • Karena runtime asinkron berada di pusat bahasa, ada alat yang bisa membuat developer Rust iri
    • Mudah melakukan dump backtrace dari semua goroutine yang sedang berjalan
    • Deteksi deadlock dimungkinkan
    • Memiliki profiler sendiri
    • Membuat kita tidak terlalu memikirkan function coloring
  • Manajemen paket, refactoring, dan alat cross-compile pada awalnya terasa seperti peningkatan dibanding pkg-config, autotools, dan CMake di ekosistem C
  • Namun kita tidak bisa hanya memilih runtime Go yang nyaman saja
    • Toolchain kustom
    • Sistem build
    • Calling convention
    • Satu GC
    • Komponen standar bawaan dan ekosistem
    • Bahkan desain bahasa yang terbentuk secara kebetulan ikut diadopsi

Celah pada type system dan desain bahasa

  • Go menempatkan runtime untuk implementasi TCP, HTTP, TLS, HTTP/2, DNS, dan layanan web di pusatnya, serta mengambil bentuk yang familiar bagi developer Google yang pernah mempelajari Java/C/C++/Python
  • Seperti C, Go tidak banyak menangani error handling itu sendiri, dan banyak state yang mutable harus dikelola langsung oleh developer dengan if dan else
  • Seperti Java, Go mengaburkan perbedaan antara value dan reference, sehingga sulit mengetahui dari lokasi pemanggilan saja apakah suatu nilai akan berubah
    • Bergantung pada apakah method receiver adalah A atau *A, variabel lokal a di main bisa berubah atau tidak
  • Sulit membatasi mutabilitas dan imutabilitas secara jelas dengan tipe, sehingga ketika reference diteruskan, ada risiko nilai internal berubah atau disimpan lama sehingga tidak dibebaskan
  • Go tidak cukup mencegah kelompok error berikut
    • Menyalin mutex secara tidak sengaja sehingga menonaktifkannya
    • Tidak menginisialisasi field struct sehingga zero value masuk
    • nil, zero, atau empty string yang keliru menyebar jauh ke dalam sistem

Batasan zero value dan “asal hati-hati”

  • Meski menambahkan field baru ke struct pada dasarnya mengubah bentuk input fungsi, jika field baru terlewat dalam composite literal, compiler tidak mencegahnya
    • Dalam contoh, b int32 ditambahkan ke Params, tetapi jika call site hanya meneruskan a: 47, program berjalan dengan b=0
    • Sebaliknya, jika argumen fungsi ditambahkan secara langsung, akan muncul error kompilasi karena jumlah argumen kurang
  • Salah satu prinsip Go adalah bahwa zero value berguna, tetapi makna nyatanya berbeda-beda untuk setiap tipe
    • Jika len dipanggil pada slice nil, hasilnya 0 sehingga bertindak seperti slice kosong
    • Jika nilai dimasukkan ke map nil, terjadi panic: assignment to entry in nil map
  • Channel juga memiliki aturan tersendiri
    • Mengirim ke channel nil akan block selamanya
    • Menerima dari channel nil akan block selamanya
    • Mengirim ke channel yang sudah ditutup akan menyebabkan panic
    • Menerima dari channel yang sudah ditutup akan langsung mengembalikan zero value
  • Karena Go tidak memiliki sum type, sulit merepresentasikan input yang “hanya mengizinkan salah satu dari opsi yang diketahui” sebagai tipe, dan pendekatannya lebih mirip C: “pokoknya hati-hati”
  • Sikap bahwa karena tidak semua masalah bisa dicegah maka sebagian masalah pun tidak perlu dicegah adalah dikotomi yang salah, dan membuat masalah yang sebenarnya bisa dibantu type system dialihkan menjadi kehati-hatian manual

Perbandingan dengan Rust bukan debat soal “pengganti sempurna”

  • Posisinya bukan bahwa Rust itu sempurna; Go dan Rust dapat dilihat sebagai kisah sukses dengan cara berbeda
    • Keberhasilan Go sangat bergantung pada komponen bawaan dan default yang beropini
    • Keberhasilan Rust sangat bergantung pada adopsi bertahap dan kemudahan integrasi dengan bahasa lain
  • Kasus adopsi Rust di dunia nyata lebih dekat dengan porting bertahap daripada penggantian total
    • Firefox menyertakan beberapa komponen Rust inti di dalam codebase C++ yang besar
    • Android mengimplementasikan ulang Bluetooth stack dengan Rust
    • Kode kriptografi Rust masuk ke Python, dan kode HTTP Rust masuk sebagai salah satu dari beberapa backend curl
    • Patch Rust untuk Linux kernel terus diperbaiki secara berulang
  • Pengguna Rust juga aktif membicarakan waktu build, kekurangan fitur bahasa, dan kelemahan lainnya
  • Pokok bahasannya bukan memilih Go atau Rust secara mutlak, melainkan masalah apa yang dapat dikurangi oleh alat yang mampu mengekspresikan mutabilitas, lifetime, dan abstraksi sebagai tipe
  • Di Rust pun tidak semua kasus harus dimodelkan secara ketat
    • Misalnya, jika bukan alat level rendah seperti ls, kita dapat memakai camino dan memutuskan hanya menangani path UTF-8
    • Dalam error handling, beberapa variant penting saja dapat didaftarkan dan sisanya dibiarkan sebagai Other, Internal, atau Unknown
    • Memanggil unwrap() pada Option<T> adalah cara untuk menegaskan secara eksplisit bahwa nilainya ada

Go lebih mirip pulau yang terpisah dari ekosistem lain

  • Jika tidak memakai cgo, Go jauh dari assembler, linker, debugger, memory checker, dan calling convention umum
  • Go lebih dekat ke bahasa closed-world daripada C/C++, dan lebih tidak ramah FFI dibanding Node.js, Python, atau Ruby
  • Perbedaan ini juga punya kelebihan
    • Bagian dalam TLS dan HTTP stack dapat dilihat dengan profiler dengan cara yang sama seperti business logic
    • Ini kontras dengan bahasa dinamis, tempat stack trace berhenti di OpenSSL
    • Runtime dapat menangani non-blocking I/O dan scheduling
  • Namun banyak alat yang sudah ada dan pengetahuan institusional sulit digunakan apa adanya, dan mengintegrasikan Go dengan bahasa lain juga rumit
  • Setiap cara integrasi Go memiliki biayanya sendiri
    • Memanggil C dari Go memerlukan biaya batas FFI dan pelacakan descriptor manual agar tidak merusak GC
    • Memanggil Go dari bahasa lain mengharuskan seluruh Go runtime, termasuk GC, ikut dimasukkan, serta menimbulkan library statis besar dan beban operasional
  • Batas terbaik yang bersentuhan dengan Go lebih dekat ke batas jaringan
    • RPC over TCP seperti REST-ish HTTP/1, JSON-RPC, atau gRPC relatif tidak terlalu menyakitkan jika biaya latensi dapat diterima
    • Namun invariant tetap harus dijaga di kedua sisi, dan di sisi Go compiler tidak menjaminnya jika paket validasi tidak digunakan secara konsisten

Jebakan harapan Go untuk prototipe

  • Ada gagasan bahwa karena Go mudah dipelajari dan mudah untuk perekrutan, kita bisa membuat prototipe terlebih dahulu, lalu menulis ulang atau mendatangkan pakar jika nanti menjadi sulit
  • Namun “kode yang akan dibuang” hampir tidak pernah benar-benar ada dalam kenyataan
    • Penulisan ulang memakan waktu
    • Koordinasi transisi yang mulus sulit dilakukan
    • Detail bisa hilang
    • Pengembangan fitur baru terhenti
    • Orang harus dilatih ulang untuk teknologi baru
  • Semakin banyak komponen Go, semakin banyak alasan untuk terus memilih Go agar dapat berinteraksi dengan kode Go yang sudah ada
  • Linter membantu sebagian, tetapi tidak bisa melakukan sebanyak compiler dari bahasa yang sejak awal menangani masalah secara serius, dan juga memperlambat kecepatan pengembangan
  • Kompleksitas yang tidak ada di bahasa berpindah ke codebase
    • Invariant yang tidak diekspresikan sebagai tipe harus ditulis sendiri dalam kode
    • Dari signature fungsi saja, sulit mengetahui apakah data akan berubah, apakah akan disimpan, apakah zero value diizinkan, apakah goroutine dimulai, apakah channel nil mungkin terjadi, dan tipe apa yang sebenarnya dapat diteruskan ke interface{}
    • Kita menjadi bergantung pada dokumentasi, dan dokumentasi memiliki biaya besar baik untuk diperbarui maupun ketika tidak diperbarui

“Kebohongan” yang dirangkum pada akhirnya

  • Hal-hal yang kita katakan pada diri sendiri agar terus memakai Go dapat dirangkum sebagai berikut
    • Karena orang lain memakainya, itu juga akan baik untuk kita
    • Orang yang menyampaikan kekhawatiran adalah elitis atau tidak sopan
    • Runtime asinkron dan GC yang menarik mengimbangi semua kekurangan lain
    • Setiap cacat desain bahasa baik-baik saja, baik secara terpisah maupun jika digabungkan
    • Kita bisa mengatasinya dengan “berhati-hati”, linter, dan lebih banyak reviewer
    • Karena mudah ditulis, pengembangan software produksi juga mudah
    • Karena bahasanya sederhana, sisanya juga sederhana
    • Kita hanya akan memakainya sedikit atau hanya di awal, dan mudah keluar darinya
    • Nanti bisa ditulis ulang kapan saja
  • Jika alat yang dipilih tidak menghilangkan kompleksitas, kompleksitas itu berpindah ke developer lain, operator, dan pelanggan
  • Situasi ketika nilai nil masuk ke tempat yang tidak boleh dan membangunkan orang pada malam hari saat operasional berjalan berujung pada pengulangan Billion Dollar Mistake

2 komentar

 
tsboard 2024-11-28

Saya sempat ragu apakah pantas menulis, mengingat saya ini cuma amatir yang baru berkutat cukup intens dengan bahasa Go dalam waktu yang sangat singkat... Go memang punya kelebihan dan kekurangan yang sangat jelas, jadi baik yang memilih maupun yang menghindarinya tampaknya punya alasan yang tegas. Secara pribadi, rasanya kurang tepat membandingkannya dengan Rust, dan lebih masuk akal jika dibandingkan dengan Kotlin(Java).

Goroutine di Go memang luar biasa, tetapi bukan sihir. Terutama pada proyek kecil di backend yang hanya memakai satu MySQL, concurrency ini justru sangat merepotkan untuk dikelola. Masalah kehabisan resource MySQL atau pengelolaan pool, yang di runtime JS/TS tidak terlalu perlu dipikirkan, ternyata lebih sulit dari yang dibayangkan. Pada akhirnya, dalam situasi seperti ini DB menjadi bottleneck, sehingga keunggulan Go dalam concurrency agak memudar. (Asynchronous I/O atau event loop pada runtime JS/TS justru bisa jadi lebih cocok) Coba saja langsung hajar dengan alat seperti hey pakai -c 100, nanti akan terasa.

Lalu, meski GC-nya sangat bagus, bukan berarti kita bisa sembarangan hanya melempar pointer ke objek lalu masa bodoh dengan beres-beresnya. Semua ada trade-off, tetapi di Go juga, kalau memungkinkan, objek kecil sebaiknya cukup diteruskan dengan copy by value agar bisa langsung ditangani saat fungsi selesai. Mungkin saya terjebak dalam pola pikir lama, tetapi saya merasa pointer tidak boleh diperlakukan terlalu enteng dari sudut pandang efisiensi seperti di bahasa C/C++.

Harus mengembalikan error hampir setiap kali fungsi return, lalu setiap kali juga harus mengeceknya dengan if err != nil {} memang sangat merepotkan, tetapi ini justru kelebihan. Biayanya lebih murah daripada try catch. Dan keyword defer yang berperan seperti finally {} juga sangat bagus. Menyenangkan karena kita tidak perlu terlalu memikirkan kapan resource harus dilepas. Saya juga suka karena hanya dengan standard library saja kita sudah bisa langsung menyusun server backend yang sangat baik (1.23 ke atas). Yang paling bagus dari semuanya, jika dibuild sesuai target OS, kita tidak memerlukan runtime lain atau instalasi awal tambahan.

Saya belum lama memakai Go, jadi rasanya tulisan ini jadi terlalu panjang untuk opini yang sangat pribadi, maka saya sudahi di sini. Hehe, saya suka bahasa Go, dan saya juga suka bahasa-bahasa lain!

 
GN⁺ 2024-11-27
Komentar Hacker News
  • Artikel ini memang banyak menyoroti kelemahan Go dengan baik, tetapi saya tidak menganggap penanganan error eksplisit sebagai salah satunya
    Saya selama ini tidak suka penanganan exception karena menambahkan lapisan “magis” yang terlalu mudah merusak alur; meski ini bukan argumen yang sempurna secara teknis, berdasarkan pengalaman puluhan tahun saya lebih menyukai cara error ditangani tepat di titik saat error itu terjadi
    Bisa saja dikatakan Rust melakukannya dengan lebih elegan, dan untuk proyek pribadi saya lebih menyukai Rust, tetapi dalam proyek besar yang dimasuki dan ditinggalkan developer dengan tingkat kemahiran beragam, saya melihat filosofi Go sebagai salah satu pendekatan penanganan error modern yang cukup masuk akal
    Di daerah saya, berkat kesederhanaannya, Go diadopsi jauh lebih banyak daripada bahasa “baru” lainnya. Ini bukan bahasa terbaik, tetapi karena memiliki banyak pertimbangan bawaan yang mencegah kita mencelakai diri sendiri, sebagai bahasa serbaguna ia sering menjadi pilihan terbaik

    • Penanganan error di Go memiliki beberapa kelemahan. Karena penulis sangat condong ke Rust, alternatifnya bukan exception, melainkan sum type Result
      Tidak ada stack trace dan error harus dibungkus, sehingga kita perlu membuat bukan hanya pesan error yang unik, tetapi juga pesan pembungkus yang unik di setiap titik pemanggilan, agar pesan itu bisa di-grep untuk memperkirakan sesuatu yang mirip stack trace
      “Tuple return” adalah perangkat aneh yang hanya ada demi error, dan di bagian lain bahasa ini tuple bahkan tidak bisa digunakan. Karena aturan inisialisasi variabel yang canggung, suatu saat Anda akan memakai variabel err yang salah
      Go seharusnya memiliki enum, atau memasukkan syntactic sugar yang lebih baik seperti ? milik Rust alih-alih “tuple return” aneh yang khusus untuk error. Cara saat ini membosankan dan rawan menimbulkan error
      Go memang punya sikap keras kepala, tetapi terlalu sering sikap itu tampak seperti keras kepala untuk melindungi bahasa ini dari kritik. Sayangnya, agar bahasa pemrograman menjadi populer, pemasaran—dengan kata lain kebohongan—juga penting, dan ini berhasil
    • Saya sudah memprogram lebih dari 30 tahun dan memakai C# hampir 10 tahun, tetapi saya menganggap exception sebagai salah satu ide terburuk dalam sejarah pemrograman
      Exception adalah goto mengerikan yang bisa dilemparkan library apa pun ke dalam kode saya, dan hampir tidak pernah ditangani dengan benar. Bahkan setelah exception “ditangani”, aplikasi biasanya berada dalam kondisi yang tidak diketahui sehingga tidak bisa dinalar
      Error Go umumnya mudah di-debug bahkan oleh engineer junior, tetapi penyebab sebenarnya dari exception Java pun sulit dipahami bahkan oleh principal yang berpengalaman
    • Setiap kali saya melihat orang memuji penanganan error Go, tanpa kecuali mereka hanya membandingkannya dengan exception, seolah-olah exception adalah satu-satunya alternatif
      Sebaliknya, saya belum pernah melihat orang yang terbiasa dengan sum type seperti Maybe, Option, atau Result dan tetap menganggap pendekatan Go cukup baik sedikit pun
    • Bagian penanganan error ini nyaris murni soal keyakinan, dan bahkan bertentangan dengan salah satu prinsip paling dasar Go bahwa “kode harus lebih mudah dibaca daripada ditulis”
      Jika saat membaca logika suatu metode, 75% isinya adalah noise error dan hanya 25% baris yang diperlukan untuk memahami perilaku sebenarnya, maka itu sulit dibaca
      Saat pertama kali melihat sebuah codebase, saya ingin lebih dulu tahu apa yang ingin dicapai, bukan edge case error; setelah itu baru melihat bagaimana kebenarannya dijamin
      Dalam hal ini, penanganan error Go gagal besar. Masalahnya bukan bahwa penanganan error eksplisit itu buruk, melainkan keras kepala untuk mencampur jalur sukses dan penanganan error baris demi baris. Penanganan tetap bisa dibuat eksplisit di bagian khusus penanganan error
    • Saya tidak setuju dengan klaim bahwa penanganan error eksplisit itu berlebihan
      Bagian yang saya setujui adalah bahwa pendekatan ini memaksa kita memikirkan semua kemungkinan yang bisa dihasilkan kode. Namun ini lebih merupakan pertanyaan yang dekat dengan C dibandingkan bahasa lain
      Saat mengabstraksikan kode, kadang error tidak perlu langsung ditangani, atau kita ingin menanganinya di bagian lebih bawah dari call stack
      Bahasa ini pada dasarnya mengorbankan banyak keterbacaan demi memaksakan cara tertentu
  • Rust dan Go sangat berbeda, dan tampaknya orang-orang menginginkan titik tengah yang saat ini belum ada
    Maksudnya bahasa yang memiliki garbage collection, relatif sederhana, dan dikompilasi menjadi binary yang ditautkan statis, tetapi punya sistem tipe mirip Rust dan hal-hal seperti rest type
    Secara sintaksis, Gleam dan Kotlin sampai batas tertentu cukup dekat, tetapi belum sepenuhnya. Saya suka Rust, tetapi menurut saya bagi banyak orang yang mampu membangun sesuatu namun bukan lulusan ilmu komputer dan juga tidak bekerja sebagai programmer, Rust terlalu rumit
    Jika hanya sesekali memakai bahasa itu, kita tidak akan ingat apa itu vtable, kapan dan bagaimana sebuah nilai dibebaskan, dan sebagainya. Tidak ada “bahasa sempurna”, tetapi Go dan Rust sama-sama membawa hal-hal hebat, dan saya berharap ada seseorang yang terinspirasi dari keduanya lalu membuat bahasa sederhana yang bisa dipakai luas

    • Kotlin menarik sebagai titik tengah, tetapi menurut saya untuk sebagian besar pekerjaan produktivitasnya jauh lebih rendah daripada Go, dan tidak cocok untuk pekerjaan yang membuat kita perlu mengeluarkan Rust
      Kotlin dalam praktiknya sangat kompleks, dan kita jadi menghabiskan waktu mencoba bersikap terlalu pintar. Ada 1000 cara untuk melakukan sesuatu, serta operator overloading, proxy, property, companion object, exception, dan tipe result semuanya ada
      Jika diasumsikan memakai Gradle, sistem build-nya terasa nyaris seperti siksaan bagi orang yang terbiasa dengan go build
      API coroutine terasa sekaligus lebih kompleks dan lebih terbatas daripada Goroutine. Lebih terstruktur, tetapi kurang fleksibel dan butuh lebih banyak upaya untuk digunakan
      Kontrol aksesnya juga canggung. Tidak ada cara membuat tipe hanya untuk package; pilihannya hanya khusus file atau publik untuk seluruh modul. Akibatnya permukaan API membesar tanpa diinginkan, atau kompleksitas tidak bisa dipecah ke beberapa file
      Kotlin/Native dan Kotlin/JVM pada dasarnya adalah entitas berbeda. Kotlin/JVM sudah matang, tetapi berjalan di atas JVM, sehingga sebagian kelompok penggunaan yang layak memakai Rust menjadi hilang
      Ekosistem Kotlin/Native sangat lemah dan dokumentasinya juga kurang. Di issue tracker ada bug-bug yang menakutkan
      Kotlin/Native bahkan tidak bisa mendistribusikan library yang hanya berupa source, sehingga dibutuhkan CI yang kompleks untuk membangun binary bagi semua sistem operasi dan arsitektur. Atau akhirnya library sama sekali tidak didistribusikan, dan ini tampaknya makin memperburuk ekosistem yang sudah lemah
    • Secara pribadi, saya melihat sebagian besar fitur Rust yang menurut orang akan bagus jika ada di Go masih bisa masuk ke dalam “konsep” Go
      Seperti ketika generics ditambahkan, cukup tambahkan tiga hal saja: Result, container generik untuk error; Optional untuk penanganan nil yang lebih baik; dan sedikit syntactic sugar seperti operator Elvis
      Keunggulan besar yang hampir sendirian menjelaskan keberhasilan Go adalah bahwa bahasa itu dibuat dan dipakai langsung oleh perusahaan raksasa, yang punya kapasitas untuk membuat tooling hebat dan library open source. Fakta bahwa sebuah bahasa sudah dipakai dan punya library tampaknya merupakan faktor penentu terbesar keberhasilan sebuah bahasa
    • Pandangan saya tentang topik ini, dengan kata lain, adalah memulai dari JavaScript
      Sintaks dasarnya sangat langsung, adopsinya sudah sangat besar, ekosistemnya luas, runtime-nya terus membaik, dan bisa juga dikompilasi ke WASM
      Lalu hilangkan bagian-bagian anehnya, misalnya fleksibilitas redefinisi yang terlalu besar, penyalahgunaan global scope, keanehan terkait angka, dan tambahkan tipe, sum type/product type, Result, Maybe, decimal, dan sebagainya
      Kemudian masukkan gaya bahwa semuanya adalah expression, pattern matching, fitur fungsional seperti currying, serta standard library yang komprehensif; maka bisa muncul bahasa yang paling mendekati apa yang diinginkan banyak orang
      Kemajuan besar lain yang ingin saya lihat di developer tools adalah merombak HTML agar memiliki kontrol tingkat tinggi yang layak secara bawaan, dan mudah diberi style dengan inline CSS. Dengan begitu jumlah JS yang dibutuhkan di sisi client akan berkurang
      Saya pikir dua hal ini akan sangat meningkatkan produktivitas pemrograman untuk pengembangan terkait web
    • Saya penulisnya; dalam hal apa Gleam belum mencapai titik itu? Saya juga sedang mencari titik tengah seperti itu, jadi cukup penasaran dengan Gleam
    • C# dan F# jelas yang paling dekat. Opsi lain tidak punya sistem tipe atau tooling yang cukup baik untuk menandingi keduanya
      Dengan dotnet publish -p:PublishAot=true, kode bisa dikompilasi menjadi binary native statis. Di F#, Anda harus memakai metode Console.* alih-alih print*; print memiliki refleksi tak terbatas di dalamnya karena output struktural dari specifier format %A, sehingga berdampak buruk pada ukuran binary dan compiler akan mengeluh
      Khususnya F# layak direkomendasikan sebagai “alternatif Rust yang lebih mudah dan lebih berorientasi bisnis”. Ia berorientasi expression, dan kombinasi discriminated union, inferensi tipe HM penuh, serta penerapan tipe secara bertahap sangat cocok. Analisis data dan pemodelan domain juga sangat nyaman
      Untuk system programming, C# menjadi opsi. Ia menyediakan primitive concurrency yang sangat baik, interop native yang cepat dan kadang hampir tanpa biaya, binary native yang lebih kecil daripada Go, serta banyak API low-level termasuk SIMD portabel
      Go sering kali tidak cocok untuk pekerjaan seperti ini, atau sama sekali tidak bisa melakukannya tanpa jalan memutar. .NET semakin populer di komunitas non-game pada bidang ini, dan banyak library berkinerja tinggi juga bermunculan. Selain itu, berbeda dengan bahasa niche yang diusulkan di komentar saudara, ia mendapat manfaat dari ekosistem besar yang sudah ada sehingga kita tidak perlu mengerjakan sendiri semua pekerjaan fondasional
  • Go: “Aku bahasa yang sederhana!”
    Pengguna memakai Go selama beberapa waktu
    Pengguna: “Aku benci kamu, kamu kan bahasa yang sederhana!”
    Mungkin karena aku sudah berusia 50-an ke atas, aku suka bahasa yang sederhana
    “Kritik” ini tidak terlihat terlalu berimbang, dan segala hal dalam teknologi adalah soal kompromi; menurutku penilaian yang tidak berimbang itu lemah
    Tentu saja kesimpulanku berbeda: https://www.inkmi.com/blog/why-we-chose-go-over-rust-for-our...

    • Ini distorsi yang sering melekat pada kritik terhadap Go. Semacam “kamu tidak paham kesederhanaan, kamu terinfeksi cacing otak Java”
      Di tulisan itu ada banyak contoh yang menunjukkan inkonsistensi bahasa yang menjengkelkan, dan hal-hal seperti itu adalah kebalikan dari kesederhanaan
      Aku menyukai presentasi Go dari Rob Pike, dan sebagian isinya membuka mataku. Namun aku berharap Go yang kulihat dalam praktik jauh lebih dekat dengan Go yang digambarkan para penggemar Go secara abstrak
    • Aku berharap narasi bahwa Go adalah bahasa yang “sederhana” menghilang
      Berbeda dari penampilan luarnya, begitu mulai memakai Go, segera terlihat bahwa ia tidak sederhana. Ada banyak kompleksitas tersembunyi dan jebakan. Contoh: https://archive.ph/WcyF4
      Meski begitu, ini bahasa yang berguna dan cukup banyak dipakai, tetapi tidak “sederhana”
    • Masalah Go adalah ia tidak dirancang sebagai bahasa sederhana untuk pengguna, melainkan sebagai bahasa yang mudah diimplementasikan oleh para maintainer
      Menurutku bahasa yang sederhana harus memiliki konsistensi tinggi. Aturannya sedikit, tetapi berlaku universal dan konsisten di mana-mana. Namun di Go, keanehan, inkonsistensi, dan jalan memutar ada di mana-mana
      Contoh yang bagus adalah penghilangan tipe. Ini bisa dilakukan pada deklarasi array, slice, dan map, tetapi tidak pada struct. Jika diizinkan juga pada struct, ada beberapa keuntungan dari sisi keterbacaan, dan named parameter melalui argumen struct anonim juga menjadi mungkin, sehingga desainnya bisa jauh lebih baik daripada jalan memutar buruk yang dipakai sekarang
    • Scheme adalah bahasa yang sederhana, tetapi Go menyembunyikan kompleksitas sampai meledak pada saat terburuk
      Tentu saja sebagian besar alternatif Go yang masuk akal juga lebih buruk dari sudut pandang ini. Misalnya Python, Ruby, dan JS
    • Go hanya “sederhana” saat melakukan hal-hal sederhana. Coba tulis sendiri KV store atau database, maka kebutuhan akan fitur bahasa yang sedikit lebih modern akan cepat terasa
  • Aku penasaran apa yang memotivasi seseorang untuk menjatuhkan bahasa apa pun sepanjang ini. Bahkan beberapa poin tulisan yang valid tidak ditulis dengan gaya yang konstruktif, jadi aku akan menyebutnya celaan
    Memangnya ada bahasa yang tidak bisa dikritik?
    Apakah tulisan ini ditulis agar merasa lebih baik dengan menyalahkan bahasa atas kegagalan di proyek itu? Atau apakah ia tidak memahami bahwa tidak semua orang berpikir dan bekerja dengan cara yang sama, dan bahwa sesuatu yang sangat mengganggu bagi seseorang bisa hampir tidak terlihat bagi orang lain?
    Bahasa yang tidak memenuhi kebutuhan nyata biasanya akan hilang dengan sendirinya, dan hampir tidak perlu dibantu
    Go, meski berbeda dari bahasa yang “lebih elegan”, bekerja dengan sangat baik di proyek-proyek yang kutemui. Aku berharap penulis tidak dipaksa bekerja dengan Go. Komunitas lainnya akan terus membangun layanan, memberi umpan balik kepada tim Go, dan menyaksikan bahasa itu berevolusi perlahan tanpa merusak produksi

    • Jawaban atas “apa yang membuat seseorang mencela sepanjang itu” ada di dalam tulisan
      Kompleksitas esensial tidak hilang hanya karena kita menutup mata
      Jika kamu memilih untuk tidak peduli pada kompleksitas, kamu hanya mendorong kompleksitas itu kepada developer lain di organisasi, operator, pelanggan, atau seseorang. Kini merekalah yang harus memutari asumsi-asumsimu agar semuanya berjalan lancar
      Belakangan aku sering menjadi “seseorang” itu, dan aku sudah lelah
      Wajar saja Go bekerja dengan baik pada proyek-proyek yang kamu temui. C, C++, PHP, JavaScript juga bekerja. Di dunia kita, sangat banyak hal yang “berfungsi”. Menambah satu lajur jalan juga berfungsi, negara polisi juga berfungsi
      Tetapi bukankah mungkin ada sesuatu yang bekerja jauh lebih baik?
    • Ini hanya blog seseorang dan ia sedang melampiaskan keluhan. Tidak apa-apa, dan tidak perlu dilihat sedalam itu
      Kenapa ia menulisnya? Mungkin karena penulis asli merasa pikirannya tidak cukup terwakili “di luar sana”. Aku juga bukan penggemar Go, jadi popularitas Go pada 2022 terasa membingungkan bagiku. Sebab beberapa kekurangannya yang cukup jelas tampak diabaikan
      Orang sekarang jarang menulis posting blog panjang tentang betapa buruknya PHP sebagai bahasa, karena itu sudah terlalu sering dibahas
    • Tidak semua orang hanya menyukai ulasan yang membosankan dan klinis; ada juga yang menyukai tulisan dengan sedikit gairah dan humor
      Fakta bahwa posting blog ini tidak ditulis dengan cara yang kamu sukai bukan berarti ia tidak bernilai bagi orang lain
    • Salah satu faktor yang sangat subjektif dan tidak rasional yang membuatku hampir membenci Go adalah karena selama bertahun-tahun fanatik Go melakukan gaslighting kepada semua orang tentang setiap bagian Go
      Apa pun yang dilakukan Go dibungkus sebagai hal yang esensial, terbaik, dan satu-satunya cara menyelesaikan masalah itu, tak peduli apakah itu implementasi paling dasar atau sesuatu yang sudah dilakukan lebih baik oleh bahasa lain
      Apa pun yang tidak dilakukan Go diperlakukan sebagai sesuatu yang tidak perlu, seolah-olah itu konspirasi Big Complexity untuk membuat kami para pengguna non-Go yang belum tercerahkan kecanduan syntactic sugar. Fitur seperti penanganan null yang benar, penanganan error, boilerplate yang lebih sedikit, generics, atau solusi yang konsisten tanpa membuat special case untuk segala hal
      Bahkan di thread ini, strawman masih terus berlanjut. Saat penanganan error dibahas, alih-alih mengakui fakta jelas bahwa penanganan error Go bisa dibuat jauh lebih baik, orang mengeluarkan contoh seperti JavaScript. Seolah-olah orang yang mengkritik Go menganggap JavaScript sebagai puncak penanganan error
    • Bjarne mengatakannya paling tepat. Hanya ada dua jenis bahasa: bahasa yang dikeluhkan orang, dan bahasa yang tidak dipakai siapa pun
  • Setiap kali bekerja dengan bahasa lain, meskipun Go bukan bahasa yang sempurna, saya selalu ingin kembali lagi ke Go
    Saya suka fakta bahwa, secara harfiah, ia langsung berjalan. Instal Go, unduh kode, tulis kode, selesai
    Tidak perlu mencari tahu versi, runtime, konfigurasi, build tool, atau package manager apa yang harus dipakai. Cukup instal dan pakai Go
    Bahasa lain yang mungkin memberikan pengalaman serupa barangkali hanya Rust
    Mungkin ini kebohongan yang saya katakan pada diri sendiri, tetapi setiap kali memakai Python, TypeScript, atau Java, saya hanya ingin menulis kode, namun malah jadi takut memprogram karena harus men-debug atau memahami masalah konfigurasi, package manager, build tool, dan versi

    • Kekuatan Go adalah toolchain terpadu. Seperti dikatakan di tulisan itu, ini memang membuat interoperabilitas lebih sulit, tetapi menurut pengalaman pribadi saya yang terbatas, itu bukan use case yang sering dipakai
    • Inilah aspek Go yang paling layak dipuji, dan Rust juga mengadopsi hal ini bersama channel
  • Setiap kali membaca kritik terhadap Go, saya selalu berpikir hal yang sama. Tetap saja saya akan terus memakai Go
    Saya paham ada banyak masalah yang secara teori bisa didokumentasikan dengan mudah dan memang sering ditemui orang, tetapi dalam praktiknya saya tetap merasa Go adalah salah satu bahasa pemrograman yang lebih baik
    Dari hal-hal yang sering dicantumkan sebagai kekurangan, ada juga yang tidak saya setujui; misalnya saya suka cara Go menangani error secara eksplisit di mana-mana. Untuk bagian lain saya setuju, tetapi itu tidak jauh lebih mengganggu dibanding kekurangan bahasa pemrograman lain
    Saya juga agak prihatin bahwa orang-orang yang sangat sensitif terhadap area tempat Go tidak berhasil tampaknya akan mengeluh soal itu seumur hidup
    Namun ketika memilih bahasa untuk sebuah proyek, saya tidak menjejalkan banyak argumen rasional tentang “apa bahasa terbaik”. Saya memilih bahasa yang cocok untuk saya, yang membuat saya merasa bisa terus menulis software yang baik, dan nyaman untuk dikerjakan
    Sebagai orang yang mengutamakan kebenaran, saya berharap bahasa itu lebih mendekati Rust, tetapi saat ini tidak demikian. Saya juga tidak membenci Rust, tetapi itu bukan bahasa yang saya raih ketika sedang terburu-buru
    Sekarang sudah cukup banyak tulisan tentang betapa mengerikannya Go. Setidaknya sekarang saya tahu seperti apa rasanya menjadi penggemar PHP beberapa tahun lalu. Memang berlebihan, tetapi menurut saya tidak terlalu berlebihan

    • Pernyataan bahwa “orang yang sensitif terhadap area tempat Go tidak berhasil akan mengeluh seumur hidup” terdengar seperti dukungan yang bagus untuk tulisan ini. Karena itu memang inti tulisannya secara harfiah
      Anda akan memakai Go
      Dan Anda akan menyesalinya
      Namun saat itu semuanya sudah terlambat, dan Anda sudah terikat padanya
      Penulisnya menyampaikan argumen yang cukup meyakinkan, dan sangat sulit dibantah. Dalam banyak kasus yang disebutkan secara eksplisit, serta dalam banyak situasi profesional ketika perusahaan yang tidak kompeten secara teknis memakai teknologi yang tidak cocok, Go adalah pilihan buruk dan Anda akan menyesal memasukkannya ke production
      Perusahaan seharusnya tetap memakai tool yang membosankan. Untuk proyek pribadi, tentu saja silakan lakukan sesuka hati
    • Saya cukup menyukai Go. Penanganan error eksplisit kadang agak menyebalkan, tetapi itu hanyalah cara untuk menyelesaikan pekerjaan
      Selain itu, saya melihat kesederhanaannya sebagai kekuatan. Rasanya enak dipakai, mudah dipelajari, dan secara umum performanya juga cukup baik. Saya tidak akan memilihnya untuk semua situasi, tetapi ada banyak situasi ketika ia menjadi tool yang bagus
      Demikian pula saya juga cukup menyukai Java dan Python, dan cukup mahir dengan keduanya. Bahasa-bahasa ini adalah tool yang baik sesuai tujuan masing-masing
      Saya tidak mengerti mengapa orang begitu bersemangat terobsesi pada bahasa pemrograman. Bahasa adalah tool. Anda boleh lebih menyukai suatu tool, tetapi tool yang tidak Anda sukai bukan berarti tidak valid
    • “Memilih bahasa yang cocok untuk saya” adalah pilihan paling bijak bagi siapa pun. Golang hanya menjadi masalah ketika manajer memaksa orang memakainya
    • Saya suka Go, tetapi setelah menulis dan membaca terlalu banyak kode Go, saya bermimpi buruk tentang iblis-iblis if err != nil yang menampar wajah saya
      Ada banyak usulan bagus untuk memperbaiki masalah ini, tetapi sebagian komunitas yang sangat konservatif dan vokal membunuh semua usulan dengan umpan balik yang nyaris berupa hujatan
      Kini tim Go secara psikologis takut pada orang-orang seperti itu dan sudah menyerah dalam pertarungan untuk memperbaiki penanganan error
      Dalam setiap survei developer Go, komunitas secara telak memilih perbaikan penanganan error, tetapi segelintir ekstremis menggagalkan semua kemajuan
    • Alasan banyak orang benar-benar membenci Go adalah karena mereka pernah mengalami fitur-fitur bahasa lain
      Go mengambil sikap arogan bahwa ia akan memutuskan sendiri fitur apa yang Anda butuhkan, dan hanya memberi sangat sedikit hal yang bisa Anda pakai untuk bekerja
  • Diskusi saat itu:
    (130 poin, 148 komentar) https://news.ycombinator.com/item?id=34188528
    (748 poin, 544 komentar) https://news.ycombinator.com/item?id=31205072

  • Ada bagian yang berbunyi, “Saya mulai jauh lebih peduli pada semantik daripada sintaks, sehingga saya bahkan tidak melihat Zig, Nim, Odin, dan sejenisnya. Saya tidak lagi tertarik pada ‘C yang lebih baik’”
    Menurut saya tulisannya cukup bertele-tele. Bagian bahwa Go itu “kebetulan” adalah omong kosong, karena Rust juga sama “kebetulan”-nya dalam hal asal-usul dan desain
    Satu hal yang menonjol adalah Nim sama sekali bukan “C yang lebih baik”. Ia punya garbage collection, dan juga bisa memakai reference counting. Jika mau, Anda bisa memakainya seperti C yang lebih baik
    Sistem tipe Nim menghindari banyak masalah yang dimiliki Go, tetapi tidak seketat Rust
    Pada akhirnya, banyak software telah ditulis dan di-deploy dengan Go, berjalan cepat, memiliki downtime rendah, umumnya efektif, dan tampaknya memiliki lebih sedikit masalah keamanan. Menurut saya jauh lebih sedikit proyek software yang di-deploy dengan Rust, dan Firefox pun masih lebih dari 95% C++

    • Pernyataan bahwa “jauh lebih sedikit proyek software yang di-deploy dengan Rust dan Firefox masih lebih dari 95% C++” menarik karena mengingatkan saya pada tweet[0] dari tahun 2022 ini
      Saya tidak punya kepentingan dalam pertarungan ini, dan di tempat kerja saya memakai Python dan C++ dengan puas. Meski software yang ditulis dengan Rust jauh lebih sedikit, tetap saja bisa dikatakan bahwa banyak software telah ditulis dan di-deploy dengan Rust. Investasi dari perusahaan-perusahaan besar juga tidak bisa diabaikan
      0: https://x.com/m_ou_se/status/1599173341117435905
  • Saya tidak mengerti mengapa Go selalu dibandingkan dengan Rust. Perbandingan yang paling tepat adalah Java

    • Menurut saya ini cara yang tepat untuk memahami Go. Go adalah bahasa untuk membuat server di lingkungan yang mengutamakan konsistensi kode yang kuat dan waktu adaptasi singkat bagi engineer junior. Dengan kata lain, sangat cocok untuk skenario perusahaan besar tempat Java dulu digunakan
      Alasan perbandingan Go dan Rust lebih umum tetapi kurang berguna mungkin karena keduanya bagian dari gelombang bahasa baru, dan keduanya pada dasarnya menghasilkan binary yang di-link secara statis
    • Go bukanlah pengulangan Java, melainkan pengulangan C
      Dalam situasi ketika Java adalah pilihan yang baik, Go justru pilihan yang sangat buruk. Bukan hanya bahasanya terbatas, ekosistemnya juga sangat terbatas dibandingkan Java
      Saya mempertahankan Go, C#, dan TypeScript sebagai bahasa utama, dan kombinasi ini memberikan cakupan yang sangat baik. Jika saya punya 6 bulan untuk menanggung penurunan produktivitas, atau ada proyek dengan persyaratan kualitas yang rendah, saya akan menambahkan Rust
      Mempelajari bahasanya hanya butuh 1–2 minggu, tetapi belajar melakukan engineering di dalam ekosistemnya membutuhkan waktu
    • Go sebenarnya dibuat saat menunggu kompilasi C++ selesai. Tujuannya adalah membuat sesuatu yang lebih baik daripada C++ untuk layanan jaringan, dan itu berhasil. Hanya saja patokannya memang cukup rendah
      Sebagian besar perusahaan yang tidak terlalu khawatir soal performa tidak memakai C++ untuk layanan jaringan. Jika Rust sudah matang saat itu, mungkin Rust akan menjadi pilihan yang baik, tetapi waktu kompilasi, salah satu masalah inti awalnya, bisa jadi lebih buruk pada codebase Rust
      Saya juga pernah melihat kasus nyata memakai Go alih-alih Rust, dan alasan terbesarnya adalah Go jauh lebih cepat dikompilasi
    • Orang yang memutuskan bahasa apa untuk menulis sesuatu yang baru kemungkinan besar akan mempertimbangkan Go dan Rust bersama-sama. Kemungkinan mempertimbangkan Java sangat rendah
      Jika pertanyaannya apakah Rust dan Go cukup berbeda sehingga masing-masing harus dipilih untuk kasus yang berbeda, jawabannya ya. Justru karena itulah keduanya dipertimbangkan bersama lalu salah satunya dipilih
  • Dulu saya mencari Python yang “lebih baik”. Saya menginginkan bahasa yang lebih sederhana dan aman daripada C/C++, tetapi lebih cepat daripada Python, dan yang terpenting bisa membuat satu binary tunggal
    Jadi saya melihat semuanya, mulai dari Rust sampai bahasa yang kurang dikenal seperti Hare
    Seharusnya Go menjadi pilihan yang jelas, tetapi entah mengapa saya tidak suka sintaksnya. Rust bisa saya pahami. Rust memakai banyak karakter khusus yang sulit diingat dan sulit diketik di keyboard non-QWERTY, dan ada titik-titik menyakitkan lain. Berbagai Lisp bermasalah dengan tanda kurung dan notasi Polandia terbalik. Tetapi untuk Go, saya tidak bisa merasionalisasi mengapa saya tidak menyukainya
    Akhirnya saya memutuskan mengompilasi kode Python dengan Nuitka. Saya tidak tahu soal peningkatan kecepatannya, tetapi sekarang saya bisa menyediakan binary
    Saya juga makin sering melihat C#, karena kompilasi AOT-nya sedang berkembang. Namun saya tidak suka verbositas mode default-nya dan kesannya terlalu terikat pada Windows
    Nim dan Crystal sangat saya sukai, tetapi komunitas yang kecil menjadi penghalang. Meski begitu, saya benar-benar terkesan dengan apa yang bisa dilakukan Nim dengan komunitas sekecil itu, dan jadi menganggapnya bahasa yang hebat
    Saya berencana mencoba memotivasi diri untuk mempelajari salah satu bahasa yang disebutkan

    • .NET Core tidak terikat pada Windows, kecuali framework tertentu seperti WPF dan penyimpanan kredensial. Untuk WPF pun ada alternatif yang berjalan di mana saja
      Sekarang sebenarnya cukup enak dipakai
    • Nuitka punya kompatibilitas yang baik, tetapi tetap membawa kekurangan Python C-API apa adanya
      Ada juga pendekatan lain yang meninggalkan C-API dan membuat jembatan ke bahasa seperti Go atau Rust
      Saya mengerjakan py2many selama beberapa tahun. Saya ingin mendapat masukan tentang pendekatan ini