30 poin oleh GN⁺ 2025-12-06 | 1 komentar | Bagikan ke WhatsApp
  • Dengan berfokus pada perbedaan filosofi dan sistem nilai dari tiga bahasa ini, artikel membandingkan masalah apa yang ingin diselesaikan oleh masing-masing bahasa
  • Go dijelaskan sebagai bahasa yang menekankan kesederhanaan dan stabilitas, dengan meminimalkan fitur agar kolaborasi dan pemeliharaan menjadi lebih mudah
  • Rust mengejar keamanan dan performa sekaligus, serta menjamin keamanan memori melalui sistem tipe yang kompleks dan struktur trait
  • Zig digambarkan sebagai bahasa eksperimental yang memberi pengembang kendali penuh melalui manajemen memori manual dan desain berpusat pada data
  • Pendekatan yang saling bertolak belakang dari ketiga bahasa ini memperlihatkan sistem nilai yang diwujudkan oleh bahasa pemrograman, dan pilihan akhirnya bergantung pada filosofi mana yang paling sesuai bagi pengembang

Sudut pandang dalam membandingkan bahasa

  • Penulis tidak berfokus pada bahasa yang digunakan di tempat kerja, melainkan ingin memahami sistem nilai tiap bahasa melalui eksperimen dengan bahasa baru
  • Ditekankan bahwa yang penting bukan sekadar membandingkan daftar fitur, tetapi trade-off apa yang dipilih oleh bahasa tersebut
  • Go, Rust, dan Zig memiliki banyak irisan secara fungsional, tetapi nilai yang diprioritaskan oleh para perancangnya berbeda
  • Dengan memahami filosofi masing-masing bahasa, kita bisa menilai lingkungan dan tujuan apa yang paling cocok untuknya

Go — bahasa yang berpusat pada kesederhanaan dan kolaborasi

  • Go dibedakan oleh minimalisme, dengan karakteristik bahwa “seluruh bahasa bisa dimuat di dalam kepala”
    • Generics baru ditambahkan setelah 12 tahun, dan fitur seperti tagged union atau syntax sugar untuk penanganan error masih belum ada
    Iklan
  • Sangat berhati-hati dalam menambahkan fitur, sehingga meski ada banyak kode boilerplate, stabilitas dan keterbacaan bahasa tetap tinggi
  • Slice di Go mencakup fungsi yang dalam Rust diwakili oleh Vec<T> atau dalam Zig oleh ArrayList, dengan lokasi memori dikelola otomatis oleh runtime
  • Berangkat dari keluhan terhadap kompleksitas C++ dan lambatnya kompilasi, Go dirancang dengan tujuan sederhana dan kompilasi cepat
  • Go menekankan efisiensi kolaborasi di lingkungan perusahaan, dengan memprioritaskan kode yang jelas dan konsisten dibanding fitur yang kompleks

Rust — kompleks tetapi kuat dalam keamanan dan performa

  • Rust mengusung “abstraksi tanpa biaya”, dan merupakan bahasa maksimalis yang menggabungkan beragam konsep
  • Alasan tingkat kesulitannya tinggi adalah karena kepadatan konsepnya besar, dengan sistem tipe yang rumit dan struktur trait yang kompleks
  • Tujuan inti Rust adalah menyatukan performa dan keamanan memori
    • Untuk mencegah UB (Undefined Behavior), Rust melakukan verifikasi pada waktu kompilasi
    • Ini memblokir perilaku tak terduga akibat referensi pointer yang salah atau double free
  • Agar compiler dapat memahami perilaku runtime dari kode, pengembang harus mendefinisikan tipe dan trait secara eksplisit
  • Berkat struktur ini, kepercayaan terhadap kode buatan orang lain menjadi tinggi, dan ekosistem library tetap aktif terpelihara

Zig — kendali penuh dan desain berpusat pada data

  • Zig adalah bahasa termuda di antara ketiganya; saat ini masih di tahap versi 0.14 dan dokumentasi standard library hampir tidak ada
  • Zig mengadopsi manajemen memori manual, sehingga pengembang harus memanggil alloc() sendiri dan memilih allocator
  • Berbeda dari Rust atau Go, pembuatan variabel global lebih sederhana, dan runtime akan mendeteksi “illegal behavior” lalu menghentikan program
    • Melalui 4 mode rilis yang dapat dipilih saat build, keseimbangan antara performa dan stabilitas bisa diatur
    Iklan
  • Fitur pemrograman berorientasi objek (OOP) sengaja tidak diikutkan
    • Tidak ada field private atau dynamic dispatch, dan bahkan std.mem.Allocator pun tidak diimplementasikan sebagai antarmuka
    • Sebagai gantinya, Zig mengarah pada desain berpusat pada data (data-oriented design)
  • Dalam manajemen memori pun, Zig merekomendasikan struktur yang mengalokasikan dan membebaskan blok memori besar secara berkala, alih-alih pengelolaan detail per objek ala RAII
  • Zig digambarkan sebagai bahasa yang bebas dan anti-establishment, yang menghapus cara berpikir OOP dan memaksimalkan kontrol di tangan pengembang
  • Saat ini timnya berfokus pada penulisan ulang seluruh dependensi, dan versi stabil (1.0) masih belum ditentukan

Kesimpulan — perbedaan nilai yang ditampakkan oleh bahasa

  • Go menjadikan kolaborasi dan kesederhanaan, Rust menjadikan keamanan dan performa, dan Zig menjadikan kebebasan serta kontrol sebagai nilai utamanya
  • Perbedaan ketiga bahasa ini bukan sekadar perbandingan fitur, melainkan mencerminkan pilihan filosofis terhadap pengembangan perangkat lunak
  • Pengembang pada akhirnya memilih bahasa berdasarkan nilai seperti apa yang paling mereka rasakan cocok

1 komentar

 
GN⁺ 2025-12-06
Komentar Hacker News
  • Di Rust, membuat mutable global variable tidaklah sulit
    Hanya saja Anda perlu memakai unsafe atau smart pointer yang menyediakan sinkronisasi
    Itu karena Rust secara default bersifat re-entrant dan menjamin keamanan thread pada waktu kompilasi
    Jika Anda tidak peduli dengan keamanan thread statis, itu bisa dibuat semudah di Zig atau C
    Perbedaannya adalah Rust menyediakan lebih banyak alat jaminan terhadap perilaku runtime kode

    • Sebagai orang yang sudah memakai Rust selama bertahun-tahun, saya menganggap mutable global variable adalah contoh klasik dari “bisa dilakukan bukan berarti harus dilakukan”
      Saat kembali ke bahasa lain dan melihat hal seperti ini dipakai tanpa beban, rasanya seperti kegilaan dari sisi keamanan
    • Ungkapan seperti “itu sepele, hanya perlu ~” adalah hal yang juga pernah saya dengar di C++, Perl, dan Haskell
      Tetapi ketika “hal-hal sederhana” seperti ini menumpuk, hasilnya sama sekali tidak sederhana
      Rust sudah melewati batas itu, dan sekarang sama sekali tidak trivial
    • Saya penasaran apakah kompiler Rust menangkap race condition antarthread pada waktu kompilasi
      Jika ya, itu terasa lebih menarik daripada C
      Saya juga ingin tahu bagaimana ini ditangani ketika dua variabel harus selalu dikunci bersama
    • Jika saya membuat bahasa pemrograman, saya akan melarang mutable global variable sepenuhnya
      Saat melakukan debugging, pada akhirnya sumber masalahnya selalu datang dari sana
  • Menanggapi tulisan yang menyoroti kepadatan konsep Rust, saya rasa pada praktiknya cukup tahu 5% saja untuk bisa produktif
    Saya sudah memakai Rust lebih dari 12 tahun, tetapi belum pernah sekali pun perlu memakai hal seperti #[fundamental]
    Rust juga bisa melakukan arena allocation, dan konsep allocator juga ada
    Hanya saja ada allocator bawaan, dan biasanya orang memakai alokasi heap eksplisit seperti Box::new
    Mutable global bisa dibuat seperti static FOO: Mutex<T> = Mutex::new(...), dan mutex diperlukan demi keamanan memori
    Sistem tipe Rust dirancang untuk menjamin bukan hanya keamanan memori, tetapi juga keamanan semantik kode

    • Namun karena pengembang lain bisa memakai 5–10% konsep yang berbeda, saat kolaborasi pada akhirnya kita tetap harus mempelajari lebih banyak konsep
      Di C, kompleksitas seperti ini lebih sedikit
      Kompleksitas pada akhirnya memang isu penting
    • Pernyataan “Rust juga bisa arena allocation” memang benar, tetapi kebanyakan kode Rust/Go menjadikan banyak alokasi berukuran kecil sebagai jalur utama
      Ini bukan sekadar soal bisa atau tidak, melainkan soal perbedaan gaya pemrograman yang mendasar
    • Jika allocator di Rust adalah sebuah tipe, saya penasaran apakah dalam model thread m:n setiap request bisa diberi arena terpisah
    • Juga ditanyakan apakah allocator Rust itu global, dan apakah semua alokasi heap memakai allocator yang sama
    • Sambil menyebut video batch allocation Casey Muratori, ada yang menyoroti bahwa sebagian pengembang salah memahaminya lalu mengkritik RAII Rust
      Zig Software Foundation juga pernah salah mengutip pernyataan Asahi Lina tentang Rust
      Saya kurang suka sikap pemasaran Zig yang menjatuhkan bahasa lain
  • Alasan saya menyukai Zig adalah karena ini bahasa yang bisa menangani kehabisan memori dengan elegan
    Semua alokasi diasumsikan bisa gagal (fallible), dan harus ditangani secara eksplisit
    Ruang stack juga tidak diperlakukan secara ajaib; kompiler menganalisis call graph untuk menyimpulkan ukuran maksimum
    Dalam lingkungan embedded, desain yang berfokus pada sumber daya seperti ini bersifat wajib

    • Namun pada OS seperti Linux yang memakai overcommit, kegagalan alokasi pada praktiknya tidak benar-benar terjadi
      Ini tidak bisa diselesaikan hanya lewat penanganan di level bahasa
    • Menanggapi pertanyaan apa alasan Zig harus ada jika Rust sudah ada, saya justru akan bertanya “jika sudah ada C, mengapa Zig?”
      Pada akhirnya keduanya menghadapi persoalan yang sama, yaitu manajemen memori manual
      Kalau begitu, menurut saya lebih baik memakai bahasa GC
    • Saya penasaran bagaimana inferensi ukuran stack Zig bekerja ketika ada rekursi atau pemanggilan function pointer
    • Zig bukan yang pertama; kita perlu melihat sejarah bahasa sistem sejak JOVIAL pada 1958
    • Di Rust juga pre-allocation bisa ditangani dengan baik
      Hanya saja pustaka standar Rust memakai panic saat OOM, sehingga ada ekosistem terpisah yang mendukung pengembangan embedded di lingkungan no-std
  • Slice di Go berbeda dari Vec<T> di Rust
    append() mengembalikan slice baru, yang bisa berbagi memori lama atau tidak
    Tidak ada cara untuk mengecilkan memori, dan jika hanya menulis append(s, ...) slice baru itu akan diabaikan
    Go bermentalitas “lakukan seperti yang saya katakan”, sedangkan Rust bermentalitas “verifikasi apakah Anda benar-benar melakukan seperti yang saya katakan”
    Artinya, Go menerima kesalahan demi kesederhanaan, sedangkan Rust memilih arah mengurangi kesalahan meski menjadi lebih kompleks

    • Sebenarnya memori bisa dikecilkan dengan slices.Clip
      Selain itu, jika hanya menulis append(s, ...) akan terjadi error kompilasi, jadi pernyataan aslinya agak kurang akurat
      Go adalah bahasa yang sangat berhati-hati menimbang kenaikan kompleksitas saat menambah fitur
    • Karena “append(s, …)” bahkan tidak akan lolos kompilasi, saya rasa pemula pun tidak bisa membuat kesalahan seperti itu
    • Menarik bahwa meskipun Go sudah punya generics, tipe seperti List[T] tetap tidak banyak dipakai
      Mungkin karena jarang ada kebutuhan untuk langsung meneruskan growable list
    • Di Go, sebagian besar foot gun sudah dijelaskan dengan jelas di spesifikasi dan dokumentasi
      Sering kali orang hanya tidak membaca dokumen lalu merasa terkejut
  • Saya rasa menangkap UB (Undefined Behavior) di C/C++ dengan pemeriksaan runtime itu sulit dilakukan secara realistis
    Android juga sudah menerapkan sanitizer pada setiap commit, tetapi baru setelah beralih ke Rust eksploit berkurang

    • Ada yang meminta sumber untuk klaim tentang sanitizer di Android
  • Saya suka karena tulisan perbandingan bahasa ini membahas kelebihan dan kelemahan tiap bahasa secara jujur
    Hanya saja agak disayangkan Raku tidak disebut
    Menurut saya, jika C–Zig–C++–Rust–Go adalah spektrum bahasa tingkat rendah, maka di sisi tingkat tinggi ada Julia–R–Python–Lua–JS–PHP–Raku–WL

    • Ada yang bertanya WL itu apa
    • Raku adalah bahasa serbaguna dengan daya ekspresi tinggi, dengan multiple dispatch, roles, gradual typing, lazy evaluation, dan sistem regex kuat yang sudah terintegrasi
      Definisi sintaks didukung di level bahasa, sehingga DSL atau parsing log menjadi mudah
      Karena berbasis VM, performanya rendah, tetapi cocok untuk mengekspresikan struktur masalah secara langsung
      Sebagai penerus Perl, arahnya adalah bahasa yang fleksibel dan konsisten
  • Mengira bahwa di Rust fungsi yang mengembalikan pointer otomatis melakukan alokasi heap adalah kesalahpahaman
    Variabel lokal ada di stack, dan menghilang saat dikembalikan, sehingga pointer menjadi tidak valid
    Di mode aman, Rust tidak mengizinkan dereferensi pointer, dan di mode unsafe pengembang memikul tanggung jawab menjamin validitasnya
    Kemungkinan Box::new disalahartikan sebagai “alokasi implisit”

    • Sulit dipahami bagaimana orang bisa mencampuradukkan escape analysis di Go dengan alokasi heap eksplisit di Rust
      Ini terlihat seperti salah paham konsep, atau sengaja menyesatkan
  • Kelebihan terbesar Go adalah model konkurensi yang sederhana
    Berkat goroutine, kode paralel bisa ditulis dengan mudah

    • Salah satu kelebihan Go adalah mudahnya menelusuri codebase besar berkat konsistensi kode
      Mencari implementasi interface memang sulit, tetapi keterbacaannya tinggi sehingga cocok untuk kolaborasi tim
    • Ceramah Rob Pike “Concurrency is not Parallelism” menjelaskan filosofi konkurensi Go dengan baik
      Tidak ada colored function, dan komunikasi berbasis channel itu sederhana sehingga kode konkurensi yang benar bisa ditulis dengan cepat
    • Namun saya rasa Structured Concurrency adalah model yang lebih mudah
      Tulisan terkait: Structured Concurrency or Go Statement Considered Harmful
    • Antarmuka std.Io baru di Zig mirip dengan model konkurensi Go
      Kata kunci go dipadankan dengan std.Io.async, channel dengan std.Io.Queue, dan select dengan std.Io.select
    • Jika Anda pengembang Erlang, Anda mungkin tidak akan setuju bahwa model konkurensi Go adalah yang paling mudah
  • Yang saya inginkan adalah bahasa yang menggabungkan kesederhanaan Go dengan penanganan result/error/enum ala Rust serta generics yang lebih baik

    • Saya juga setuju. Ada permintaan pasar besar untuk bahasa native dengan GC tetapi memiliki sistem tipe yang lebih kuat
      Saya sudah melihat OCaml, D, Swift, Nim, Crystal, dan lainnya, tetapi belum ada yang benar-benar mendominasi pasar
    • Saya dengar OCaml modern punya model konkurensi yang sangat kuat, dan performanya juga bisa bersaing dengan Go
    • Bahasa Borgo pernah mencoba ke arah itu, tetapi sekarang sudah dihentikan
      Sebagai gantinya, Gleam layak dilihat
    • Proposal error Go menarik
      Saya berharap ada perbaikan yang bisa menyelesaikan masalah berulang seperti ini
      Generics tampaknya masih akan menjadi tantangan sulit
    • Alternatif yang paling dekat adalah C#, tetapi tetap saja itu bahasa yang berpusat pada OOP
  • Saya suka nada umum tulisan ini karena terasa ada semangat dan rasa ingin tahu khas pengembang junior
    Ketiadaan generics di Go menurut saya bukan sekadar minimalisme sederhana, melainkan hasil pertimbangan trade-off
    Lifetime di Rust adalah hambatan terbesar bagi banyak orang, dan kebaruan bahasa itu lahir dari kombinasi konsep-konsep yang sudah ada
    Manajemen memori manual di Zig lebih berlandaskan filosofi Data-Oriented Design (DOD) daripada sekadar menyingkirkan OOP
    Ceramah terkait: presentasi DOD Andrew

    • Seperti persoalan yang diajukan Russ Cox pada 2009 dalam tulisan “The Generic Dilemma”,
      intinya adalah “mana yang dipilih: programmer lambat, kompiler lambat, atau eksekusi lambat”
      Tim Go tampaknya pada akhirnya menemukan jalan tengah yang cukup memuaskan