Pemikiran tentang Go vs. Rust vs. Zig
(sinclairtarget.com)- 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
- 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 olehArrayList, 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
- Fitur pemrograman berorientasi objek (OOP) sengaja tidak diikutkan
- Tidak ada field private atau dynamic dispatch, dan bahkan
std.mem.Allocatorpun tidak diimplementasikan sebagai antarmuka - Sebagai gantinya, Zig mengarah pada desain berpusat pada data (data-oriented design)
- Tidak ada field private atau dynamic dispatch, dan bahkan
- 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
Komentar Hacker News
Di Rust, membuat mutable global variable tidaklah sulit
Hanya saja Anda perlu memakai
unsafeatau smart pointer yang menyediakan sinkronisasiItu 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
Saat kembali ke bahasa lain dan melihat hal seperti ini dipakai tanpa beban, rasanya seperti kegilaan dari sisi keamanan
Tetapi ketika “hal-hal sederhana” seperti ini menumpuk, hasilnya sama sekali tidak sederhana
Rust sudah melewati batas itu, dan sekarang sama sekali tidak trivial
Jika ya, itu terasa lebih menarik daripada C
Saya juga ingin tahu bagaimana ini ditangani ketika dua variabel harus selalu dikunci bersama
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::newMutable global bisa dibuat seperti
static FOO: Mutex<T> = Mutex::new(...), dan mutex diperlukan demi keamanan memoriSistem tipe Rust dirancang untuk menjamin bukan hanya keamanan memori, tetapi juga keamanan semantik kode
Di C, kompleksitas seperti ini lebih sedikit
Kompleksitas pada akhirnya memang isu penting
Ini bukan sekadar soal bisa atau tidak, melainkan soal perbedaan gaya pemrograman yang mendasar
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
Ini tidak bisa diselesaikan hanya lewat penanganan di level bahasa
Pada akhirnya keduanya menghadapi persoalan yang sama, yaitu manajemen memori manual
Kalau begitu, menurut saya lebih baik memakai bahasa GC
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 Rustappend()mengembalikan slice baru, yang bisa berbagi memori lama atau tidakTidak ada cara untuk mengecilkan memori, dan jika hanya menulis
append(s, ...)slice baru itu akan diabaikanGo 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
Selain itu, jika hanya menulis
append(s, ...)akan terjadi error kompilasi, jadi pernyataan aslinya agak kurang akuratGo adalah bahasa yang sangat berhati-hati menimbang kenaikan kompleksitas saat menambah fitur
Mungkin karena jarang ada kebutuhan untuk langsung meneruskan growable list
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
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
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::newdisalahartikan sebagai “alokasi implisit”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
Mencari implementasi interface memang sulit, tetapi keterbacaannya tinggi sehingga cocok untuk kolaborasi tim
Tidak ada colored function, dan komunikasi berbasis channel itu sederhana sehingga kode konkurensi yang benar bisa ditulis dengan cepat
Tulisan terkait: Structured Concurrency or Go Statement Considered Harmful
std.Iobaru di Zig mirip dengan model konkurensi GoKata kunci
godipadankan denganstd.Io.async, channel denganstd.Io.Queue, danselectdenganstd.Io.selectYang saya inginkan adalah bahasa yang menggabungkan kesederhanaan Go dengan penanganan result/error/enum ala Rust serta generics yang lebih baik
Saya sudah melihat OCaml, D, Swift, Nim, Crystal, dan lainnya, tetapi belum ada yang benar-benar mendominasi pasar
Sebagai gantinya, Gleam layak dilihat
Saya berharap ada perbaikan yang bisa menyelesaikan masalah berulang seperti ini
Generics tampaknya masih akan menjadi tantangan sulit
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
intinya adalah “mana yang dipilih: programmer lambat, kompiler lambat, atau eksekusi lambat”
Tim Go tampaknya pada akhirnya menemukan jalan tengah yang cukup memuaskan