diff options
| author | Shulhan <m.shulhan@gmail.com> | 2020-04-26 20:30:58 +0700 |
|---|---|---|
| committer | Shulhan <m.shulhan@gmail.com> | 2020-04-26 20:31:05 +0700 |
| commit | ae87a7a3babc5a7194d630a02f1e79a71d93a647 (patch) | |
| tree | d598230e31050986c877785bb1be50aa69222a8d /_content/doc/faq/index.adoc | |
| parent | 4ff208d604f34d0579399dd289a9a60e19c9a2ab (diff) | |
| download | golang-id-web-ae87a7a3babc5a7194d630a02f1e79a71d93a647.tar.xz | |
all: add underscore prefix to non Go directories
This is to prevent Go tools process any directories that start with
underscore.
Diffstat (limited to '_content/doc/faq/index.adoc')
| -rw-r--r-- | _content/doc/faq/index.adoc | 2398 |
1 files changed, 2398 insertions, 0 deletions
diff --git a/_content/doc/faq/index.adoc b/_content/doc/faq/index.adoc new file mode 100644 index 0000000..e2ce80b --- /dev/null +++ b/_content/doc/faq/index.adoc @@ -0,0 +1,2398 @@ += Tanya Jawab +:toc: +:talks-go-at-google: https://talks.golang.org/2012/splash.article + +[#Origins] +== Asal mula + +[#What_is_the_purpose_of_the_project] +=== Apakah tujuan dari proyek ini? +//{{{ + +Pada saat Go lahir, dunia pemrograman berbeda dari sekarang. +Perangkat lunak di industri biasanya ditulis dengan C++ atau Java, Github +belum ada, kebanyakan komputer belum multi prosesor, dan selain Visual +Studio dan Eclipse hanya ada beberapa IDE atau perkakas pembantu lainnya yang +tersedia, dan tidak semuanya gratis di Internet. + +Sementara itu, kami telah frustasi dengan kompleksnya kebutuhan bahasa yang +kita gunakan untuk mengembangkan perangkat lunak _server_. +Komputer telah menjadi begitu cepat semenjak bahasa seperti C, C++, dan Java +pertama kali dikembangkan tapi pemrograman itu sendiri tidak berkembang begitu +banyak. +Dan juga, jelas bahwa multi prosesor akan menjadi universal tapi kebanyakan +bahasa menyediakan sedikit dukungan untuk dapat memprogramnya secara efisien +dan aman. + +Kami memutuskan untuk berpikir tentang isu-isu mayor apa saja yang akan +mendominasi pembangunan perangkat lunak pada beberapa tahun ke depan saat +teknologi berkembang, dan bagaimana sebuah bahasa baru bisa membantu +mengatasinya. +Misalnya, munculnya CPU dengan multi _core_ bisa menjadi alasan bahwa sebuah +bahasa sebaiknya menyediakan dukungan utama untuk konkurensi dan paralelisme. +Dan untuk membuat manajemen sumber daya mudah dikerjakan dalam sebuah program +yang konkuren, _garbage collection_, atau setidaknya suatu model manajemen +_memory_ yang otomatis dan aman setidaknya dibutuhkan. + +Pertimbangan-pertimbangan ini mengarah ke +https://commandcenter.blogspot.com/2017/09/go-ten-years-and-climbing.html[beberapa +diskusi lanjutan] +yang menyebabkan lahirnya Go, pertama sebagai kumpulan ide dan keinginan, +kemudian sebagai sebuah bahasa. +Tujuan secara keseluruhan yaitu supaya Go lebih membantu pemrogram dengan +menyediakan perkakas, mengotomasi pekerjaan-pekerjaan biasa seperti +pemformatan, dan menghapus permasalahan saat bekerja dalam basis kode yang +besar. + +Deskripsi yang lebih luas dari tujuan dibuatnya Go dan bagaimana ia dicapai, +atau setidaknya bagaimana ia dikembangkan, tersedia dalam artikel +{talks-go-at-google}[Go di Google: Rancangan Bahasa dalam Melayani Rekayasa +Perangkat Lunak (Inggris)]. + +//}}} + +[#history] +=== Bagaimana sejarah proyek ini? +//{{{ + +Robert Griesemer, Rob Pike, dan Ken Thompson mulai membuat sketsa beberapa +sasaran dari sebuah bahasa baru di sebuah papan tulis pada 21 September, 2007. +Dalam beberapa hari, sasaran-sasaran tersebut terkumpul menjadi sebuah rencana +untuk melakukan sesuatu dan gambaran bagaimana bentuknya nanti. +Perancangan dilanjutkan paruh waktu, paralel dengan pekerjaan lainnya. +Pada Januari 2008, Ken mulai bekerja menulis sebuah _compiler_ untuk +mengeksplorasi ide tersebut; +_compiler_ tersebut menghasilkan kode C. +Pada pertengahan tahun, bahasa tersebut menjadi proyek penuh dan telah siap +untuk dicoba sebagai sebuah _compiler_. +Pada Mei 2008, Ian Taylor secara independen mulai membuat antar muka untuk Go +pada GCC menggunakan spesifikasi draf yang ada. +Russ Cox bergabung pada akhir 2008 dan membantu mendorong bahasa dan +pustakanya dari prototipe menjadi realitas. + +Go menjadi proyek sumber terbuka pada 10 November 2009. +Orang-orang yang tak terhitung banyaknya dari komunitas telah +mengkontribusikan ide, diskusi, dan kode mereka. + +Sekarang ada jutaan pemrogram Go--gopher--diseluruh dunia, dan akan bertambah +setiap hari. +Kesuksesan Go telah melampau ekspektasi kita. + +//}}} + +[#gopher] +=== Apakah asal mula dari maskot gopher? +//{{{ + +Maskot dan logo dirancang oleh +https://reneefrench.blogspot.com/[Renée French], +yang juga merancang +https://9p.io/plan9/glenda.html[Glenda], +kelincinya Plan 9. +https://blog.golang.org/gopher[Sebuah blog] +tentang gopher menjelaskan bagaimana ia diturunkan dari rancangan bajunya +https://wfmu.org/[WFMU] +yang ia buat beberapa tahun lalu. +Logo dan maskot berlisensikan +https://creativecommons.org/licenses/by/3.0/[Creative Commons Attribution +3.0]. + +Gopher memiliki +https://golang.org/doc/gopher/modelsheet.jpg[lembar model] +yang mengilustrasikan karakteristiknya dan bagaimana merepresentasikannya +dengan benar. +Lembar model tersebut pertama kali diperlihatkan dalam sebuah +https://www.youtube.com/watch?v=4rw_B4yY69k[presentasi] +oleh Renée pada Gophercon 2016. +Maskot tersebut memiliki fitur unik; +ia adalah _gopher_ -nya Go, bukan hanya _gopher_ yang dulu. + +//}}} + +[#go_or_golang] +=== Apakah bahasanya disebut Go atau Golang? +//{{{ + +Bahasanya disebut Go. +Orang-orang menyebutnya "golang" karena situsnya bernama "golang.org", bukan +"go.org", yang mana tidak tersedia saat itu. +Banyak yang menggunakan nama golang, dan cukup berguna sebagai sebuah label. +Misalnya, tag pada Twitter untuk bahasa Go adalah "#golang". +Nama dari bahasa itu sendiri adalah Go saja. + +Sebagai catatan: Walaupun +https://blog.golang.org/go-brand[logo resmi] +menggunakan dua huruf besar, nama bahasa tetap ditulis Go, bukan GO. + +//}}} + +[#creating_a_new_language] +=== Kenapa membuat sebuah bahasa baru? +//{{{ + +Go lahir dari frustasi terhadap bahasa dan lingkungan pekerjaan yang kita +lakukan di Google. +Pemrograman menjadi semakin sukar dan salah satu yang harus disalahkan yaitu +pilihan dari bahasa. +Seseorang harus memilih salah satu dari kompilasi yang efisien, eksekusi yang +efisien, atau mudah diprogram; +ketiganya tidak tersedia dalam bahasa-bahasa pemrograman yang terkenal. +Para pemrogram memilih kemudahan daripada keamanan dan efisiensi, dengan +pindah ke bahasa bertipe dinamis seperti Python dan JavaScript daripada C++ +atau Java. + +Yang sadar hal ini tidak kita saja. +Setelah beberapa tahun sunyinya bahasa pemrograman, Go adalah salah satu dari +beberapa bahasa baru--Rust, Elixir, Swift, dan lebih banyak lagi--yang telah +membuat pengembangan bahasa pemrograman menjadi bidang yang aktif, hampir +terkenal lagi. + +Go menyelesaikan masalah-masalah tersebut dengan mencoba menggabungkan +kemudahan pemrograman dari bahasa yang diinterpretasi, bertipe dinamis dengan +efisiensi dan keamanan dari bahasa bertipe statis dan dikompilasi. +Ia juga berusaha lebih moderen, dengan dukungan komputasi jaringan dan multi- +_core_. +Terakhir, bekerja dengan Go memang ditujukan supaya _cepat_: ia seharusnya +butuh beberapa detik untuk membuat sebuah program yang besar dalam sebuah +komputer. +Untuk mencapai sasaran tersebut dibutuhkan penanganan sejumlah isu lingustik: +sebuah sistem tipe yang ekspresif namun ringan; +konkurensi dan _garbage collection_; +spesifikasi dependensi yang kokoh; dan lainnya. +Hal ini tidak bisa diatasi dengan mudah oleh pustaka-pustaka atau perkakas +yang ada; +sebuah bahasa baru dibutuhkan. + +Artikel +{talks-go-at-google}[Go di Google (bahasa Inggris)] +mendiskusikan latar belakang dan motivasi dibalik rancangan bahasa Go, dan +juga menyediakan rincian lebih lanjut tentang banyak jawaban-jawaban yang ada +dalam dokumen Tanya-Jawab ini. + +//}}} + +[#ancestors] +=== Apa saja leluhur-leluhur Go? +//{{{ + +Go umumnya berada dalam keluarga dari C (sintaks dasarnya), dengan masukan +yang cukup signifikan dari Pascal/Modula/Oberon (deklarasi, paket), ditambah +beberapa ide dari bahasa yang diinspirasi oleh CSP-nya Tony Hoare, seperti +Newsqueak dan Limbo (konkurensi). +Namun, Go adalah bahasa baru secara keseluruhan. +Dalam segala hal bahasa Go dirancang dengan memikirkan tentang apa yang +pemrogram lakukan dan bagaimana melakukan pemrograman, setidaknya pemrograman +yang kami lakukan, lebih efektif, yang berarti lebih menyenangkan. + +//}}} + +[#principles] +=== Apa saja prinsip panduan dalam rancangan? +//{{{ + +Saat Go dirancang, Java dan C++ adalah bahasa yang paling umum digunakan untuk +membuat program _server_, setidaknya di Google. +Kami merasakan bahwa bahasa tersebut membutuhkan terlalu banyak pencatatan dan +repetisi. +Beberapa pemrogram pindah ke bahasa yang lebih dinamis seperti Python, dengan +mengorbankan efisiensi dan keamanan tipe. +Kami merasakan bahwa adalah memungkinkan untuk memiliki efisiensi, keamanan, +dan _kecairan_ dalam sebuah bahasa. + +Go mencoba mengurangi jumlah pengetikan dan tipe data. +Selama perancangannya, kita mencoba mengurangi kekusutan dan kompleksitas. +Tidak ada deklarasi penerus dan tidak ada berkas-berkas _header_; +semuanya dideklarasikan cukup sekali saja. +Inisialiasi dibuat ekspresif, otomatis, dan mudah digunakan. +Sintaksnya bersih dan ringan dengan kata kunci. +_Kegagapan_ (`foo.Foo* myFoo = new(foo.Foo)) dikurangi dengan tipe turunan +sederhana menggunakan konstruksi `:=` deklarasi-dan-inisialisasi. +Dan yang paling radikal, tidak ada tipe hirarki: tipe hanyalah tipe, mereka +tidak perlu memberitahukan keterkaitannya (dengan tipe lain). +Penyederhanaan ini membuat Go menjadi ekspresif dan tetap mudah dibaca +tanpa mengorbankan kecanggihan. + +Prinsip utama lainnya yaitu menjaga konsepnya tetap ortogonal. +_Method_ dapat diimplementasikan untuk semua tipe; +_struct_ merepresentasikan data, sementara _interface_ merepresentasikan +abstraksi; dan seterusnya. +Sifat ortogonal ini membuatnya mudah untuk memahami apa yang terjadi saat +beberapa hal digabungkan. + +//}}} + +[#Usage] +== Penggunaan + +[#internal_usage] +=== Apakah Google menggunakan Go secara internal? +//{{{ + +Ya. +Go digunakan secara luas dalam _production_ di Google. +Salah satu contoh sederhana yaitu _server_ dibalik +https://golang.org/[golang.org]. +Ia adalah _server_ dokumentasi dari +https://golang.org/cmd/godoc[godoc] +yang berjalan dalam sebuah konfigurasi _production_ di +https://developers.google.com/appengine/[Google App Engine]. + +Contoh yang lebih signifikan yaitu _server_ unduh Google, +`dl.google.com`, yang melayani pengunduhan program Chrome dan berbagai paket +seperti dari `apt-get`. + +Go bukan satu-satunya bahasa yang digunakan di Google, jauh dari itu, tapi ia +merupakan bahasa penting untuk sejumlah wilayah termasuk +https://talks.golang.org/2013/go-sreops.slide[Site Reliability engineering +(SRE)] +dan pemrosesan data berukuran besar. + +//}}} + +[#external_usage] +=== Perusahaan apa saja yang menggunakan Go? +//{{{ + +Penggunaan Go meningkat diseluruh dunia, khususnya, tapi bukan berarti secara +ekslusif, dalam ruang komputasi _cloud_. +Beberapa proyek infrastruktur _cloud_ besar yang ditulis dengan Go adalah +Docker dan Kubernetes, namun masih banyak yang lainnya. + +Tidak hanya pada _cloud_ saja. +https://github.com/golang/go/wiki/GoUsers[Halaman pengguna] +pada Go Wiki, yang cukup sering diperbarui, berisi daftar dari beberapa +perusahaan yang menggunakan Go. + +Go Wiki juga memiliki halaman tentang +https://github.com/golang/go/wiki/SuccessStories[cerita-cerita sukses] +perusahaan dan proyek yang menggunakan Go. + +//}}} + +[#Do_Go_programs_link_with_Cpp_programs] +=== Apakah program Go dapat dikaitkan dengan program C/C++? +//{{{ + +C dan Go bisa saja digunakan dalam ruang _memory_ yang sama, namun hal ini +bukanlah suatu hal yang cocok secara alamiah dan membutuhkan antar muka +perangkat lunak yang spesial. +Menghubungkan C dengan kode Go berarti mengorbankan keamanan _memory_ +dan properti manajemen _stack_ yang Go sediakan. +Terkadang perlu menggunakan pustaka C untuk menyelesaikan sebuah masalah, +namun melakukan hal tersebut selalu menimbulkan risiko yang mana tidak akan +muncul bila menggunakan kode Go yang murni, jadi lakukanlah dengan hati-hati. + +Jika anda benar butuh menggunakan C dengan Go, cara melakukannya bergantung +kepada implementasi _compiler_ Go. +Ada tiga implementasi _compiler_ Go yang didukung secara resmi. +Diantaranya `gc`, _compiler_ bawaan, `gccgo` yang menggunakan GCC, dan +`gollvm` yang kurang stabil, yang menggunakan infrasruktur LLVM. + +`gc` menggunakan konvensi pemanggilan dan _linker_ yang berbeda dari C dan +oleh karena itu tidak bisa dipanggil langsung dari program C, atau sebaliknya. +Program +https://golang.org/cmd/cgo/[cgo] +menyediakan mekanisme untuk sebuah "antarmuka fungsi asing" +(_foreign function interface_) untuk membolehkan pemanggilan pustaka C secara +aman dalam kode Go. +SWIG memperluas kapabilitas ini ke pustaka C++. + +Kita juga bisa menggunakan `cgo` dan SWIG dengan `gccgo` dan `gollvm`. Secara +mereka menggunakan API tradisional, ia juga memungkinkan, namun dengan sangat +hati-hati, untuk mengaitkan kode dari _compiler_ tersebut secara langsung +dengan program C atau C++ yang di- _compile_ dengan GCC/LLVM. +Namun, melakukan hal tersebut secara aman membutuhkan pemahaman konvensi +pemanggilan dari semua bahasa, dan juga perhatian terhadap batas +_stack_ saat memanggil C atau C++ dari Go. + +//}}} + +[#ide] +=== IDE apa saja yang mendukung Go? +//{{{ + +Proyek Go tidak menyediakan kostum IDE, namun bahasa dan pustakanya telah +dirancang untuk membuatnya mudah untuk menganalisis sumber kode. +Akibatnya, banyak _editor_ dan IDE terkenal yang mendukung Go, baik secara +langsung atau lewat sebuah _plugin_. + +Daftar IDE dan _editor_ yang mendukung Go diantaranya Emacs, Vim, VSCode, +Atom, Eclipse, Sublime, IntelliJ (lewat kostum varian bernama Goland), dan +lebih banyak lagi. + +//}}} + +[#protocol] +=== Apakah Go mendukung protokol _buffers_? +//{{{ + +Proyek sumber terbuka lain menyediakan plugin _compiler_ dan pustaka yang +dibutuhkan. +Ia tersedia di +https://github.com/golang/protobuf[github.com/golang/protobuf]. + +//}}} + +[#Can_I_translate_the_Go_home_page] +=== Bolehkah saya menerjemahkan situs Go ke bahasa lain? +//{{{ + +Tentu saja. +Kami mendorong pengembang untuk membuat situs Bahasa Go dengan bahasanya +sendiri. +Namun, bila anda ingin menambahkan logo atau _brand_ Google ke situs anda +(yang mana tidak ada dalam situs +https://golang.org/[golang.org]), +anda harus patuh pada aturan di +https://www.google.com/permissions/guidelines.html. + +//}}} + +== Perancangan + +[#runtime] +=== Apakah Go memiliki sebuah _runtime_? +//{{{ + +Go memiliki sejumlah pustaka yang luas, yang disebut _runtime_, yang merupakan +bagian dari setiap program Go. +Pustaka _runtime_ mengimplementasikan _garbage collection_, konkurensi, +manajemen _stack_, dan fitur penting lainnya dari bahasa Go. +Walaupun lebih terpusat pada bahasa itu sendiri, _runtime_ pada Go analoginya +sama dengan `libc`, pustaka bahasa `C`. + +Harus juga dipahami, bahwa _runtime_ Go tidak mengikutkan mesin virtual, +seperti yang disediakan oleh _runtime_ Java. +Program Go di- _compile_ diawal menjadi kode mesin (atau JavaScript atau +WebAssembly, untuk beberapa implementasi varian). +Oleh karena itu, walaupun istilah tersebut seringkali digunakan untuk +mendeskripsikan lingkungan virtual di mana program Go berjalan, dalam dunia Go +"runtime" adalah nama yang diberikan ke pustaka yang menyediakan +layanan-layanan penting dari bahasa. + +//}}} + +[#unicode_identifiers] +=== Ada apa dengan pengidentifikasi Unicode? +//{{{ + +Saat merancang Go, kami memastikan bahwa ia tidak harus berpusat pada ASCII, +yang artinya memperluas ruang pengidentifikasi dari batas-batas 7-bit ASCII. +Aturan Go--karakter pengidentifikasi haruslah huruf atau angka yang +didefinisikan oleh Unicode--sangat mudah dipahami dan diimplementasikan namun +memiliki batasan. +Misalnya, kombinasi karakter tidak dibolehkan, seperti pada bahasa Devanagari. + +Aturan ini menyebabkan konsekuensi lainnya. +Karena pengidentifikasi yang diekspor harus diawali dengan huruf besar, +pengidentifikasi yang dibuat dari karakter pada bahasa-bahasa tertentu bisa +saja, secara definisi, tidak diekspor. +Untuk saat sekarang, satu-satunya solusi yaitu menggunakan awalan seperti +`X日本語`, yang mana kurang memuaskan. + +Sejak dari versi awal, kami telah mempertimbangkan bagaimana cara terbaik +memperluas ruang pengidentifikasi untuk mengakomodasi pemrogram yang +menggunakan bahasa ibunya. +Hal-hal apa saja yang harus dilakukan saat ini masih menjadi topik diskusi +yang aktif, dan versi selanjutnya dari bahasa Go bisa saja lebih terbuka dalam +definisi dari pengidentifikasi. +Misalnya, ia mungkin mengadopsi +http://unicode.org/reports/tr31/[rekomendasi] untuk pengidentifikasi dari +organisasi Unicode. +Apapun yang terjadi, ia harus kompatibel dan menjaga (atau mungkin +mengembangkan) bagaimana huruf menentukan visibilitas dari pengidentifikasi, +yang mana merupakan fitur favorit dari Go. + +Untuk saat ini, kita memiliki aturan sederhana yang dapat dikembangkan nanti +di masa depan, tanpa mengganggu program, salah satunya untuk menghindari _bug_ +yang bisa saja muncul dari aturan yang menggunakan pengidentifikasi yang +ambigu. + +//}}} + +[#Why_doesnt_Go_have_feature_X] +=== Kenapa Go tidak memiliki fitur _X_? +//{{{ + +Setiap bahasa memiliki fitur-fitur baru yang mengindahkan fitur kesukaan orang +lain. +Go dirancang demi kenyamanan pemrograman, kecepatan _compile_, konsep +ortogonal, dan kebutuhan untuk mendukung fitur seperti konkurensi dan +_garbage collection_. +Fitur kesukaan anda bisa saja tidak ada karena tidak cocok, karena ia +mempengaruhi kecepatan _compile_ atau memperumit rancangan, atau karena ia +akan membuat model sistem fundamentalnya menjadi terlalu sukar. + +Jika anda merasa terganggu dengan tidak adanya fitur _X_ pada Go, mohon +maafkan kami dan cobalah fitur-fitur yang Go miliki. +Anda bisa saja menemukan mereka cukup memenuhi, dengan cara tertentu, dari +ketidakadaannya fitur _X_. + +//}}} + +[#generics] +=== Kenapa Go tidak memiliki tipe generik? +//{{{ + +Tipe generik mungkin akan ditambahkan pada suatu waktu. +Kami tidak merasakan urgensi dari fitur tersebut, walaupun kami paham beberapa +programmer butuh itu. + +Go ditujukan sebagai bahasa untuk menulis program _server_ yang mudah untuk +dipelihara sepanjang waktu. +(Lihat +https://talks.golang.org/2012/splash.article[artikel] +berikut untuk latar belakang lebih lanjut.) +Rancangannya berkonsentrasi pada hal-hal seperti mudah di- _scale_, mudah +dibaca, dan konkurensi. +Pemrograman _polymorphic_ tampak tidak terlalu penting untuk sasaran bahasa Go +pada saat itu, sehingga sengaja ditinggalkan demi kesederhanaan. + +Bahasa Go sekarang lebih matang, sehingga ada ruang untuk mempertimbangkan +sebuah bentuk pemrograman generik. +Namun, ada beberapa yang keberatan. + +Generik sebenarnya baik tapi harus dibayar dengan kompleksitas pada sistem +tipe dan _runtime_. +Kami belum menemukan rancangan yang memberikan nilai yang sebanding dengan +kompleksitasnya, namun kita terus memikirkan hal tersebut. +Untuk sementara, tipe bawaan Go `map` dan `slice`, ditambah dengan `interface` +kosong untuk membentuk sebuah penampung (dengan konversi eksplisit) artinya +pada banyak kasus dimungkinkan untuk menulis kode seperti pada pemrograman +generik, walau sedikit kurang mulus. + +Topik generik ini tetap dibuka. +Untuk melihat percobaan yang gagal merancang solusi generik yang bagus pada +Go, lihat +https://golang.org/issue/15292[proposal ini]. + +//}}} + +[#exceptions] +=== Kenapa Go tidak memiliki eksepsi (_exception_)? +//{{{ + +Kami percaya bahwa mengikutkan eksepsi pada sebuah struktur kontrol, seperti +idiom `try-catch-finally`, menghasilkan kode yang kusut. +Ia juga mendorong pemrogram untuk terlalu banyak melabeli eror yang biasa, +seperti gagal membuka berkas, sebagai sebuah eksepsi. + +Go menggunakan pendekatan yang berbeda. +Untuk penanganan eror biasa, kembalian dengan multi nilai pada Go membuatnya +mudah untuk melaporkan kesalahan tanpa membebani nilai kembalian. +https://golang.org/doc/articles/error_handling.html[Tipe error kanonis +digabungkan dengan fitur Go lainnya], +membuat penanganan eror mudah namun cukup berbeda dengan bahasa lainnya. + +Go juga memiliki beberapa fungsi bawaan untuk memberi sinyal dan pemulihan +dari kondisi yang benar-benar eksepsi. +Mekanisme pemulihan dieksekusi sebagai bagian dari fungsi, yang cukup untuk +menangani _bencana_ dan tidak membutuhkan struktur kontrol tambahan dan, +bila digunakan dengan baik, bisa menghasilkan sebuah kode penanganan eror yang +bersih. + +Lihat artikel +https://golang.org/doc/articles/defer_panic_recover.html[Defer Panic dan +Recover (bahasa Inggris)] +untuk lebih rinci. +Blog tentang +https://blog.golang.org/errors-are-values[Eror adalah nilai (bahasa Inggris)] +menjelaskan salah satu pendekatan untuk menangani eror dengan bersih pada Go +dengan mendemonstrasikan bahwa, secara eror hanyalah nilai, fitur-fitur yang +ada dapat digunakan untuk menangani eror. + +//}}} + +[#assertions] +=== Kenapa Go tidak memiliki fungsi _assert_? +//{{{ + +Go tidak menyediakan fungsi untuk _assert_. +Memang fungsi tersebut cukup masuk akal, tapi berdasarkan pengalaman kami +pemrogram menggunakannya sebagai pembantu untuk menghindari berpikir +tentang penanganan dan pelaporan eror yang lebih baik. +Penanganan eror yang baik artinya _server_ seharusnya terus beroperasi bukan +berhenti setelah eror yang non fatal terjadi. +Pelaporan error yang baik artinya eror jelas dan langsung keintinya, +menghindari pemrogram dari menginterpretasikan hasil _crash_ dari program yang +besar. +Eror yang presisi sangat penting bila pemrogram melihat eror yang tidak lazim +dalam program mereka. + +Kami paham bahwa hal ini adalah sesuatu yang sering diperdebatkan. +Ada banyak hal dalam pustaka dan bahasa Go yang berbeda dengan praktik +modern, alasannya sederhana, karena kami merasa terkadang pantas mencoba +pendekatan yang berbeda. + +//}}} + +[#csp] +=== Kenapa membuat konkurensi berdasarkan ide dari CSP? +//{{{ + +Pemrograman multi _threading_ dan konkurensi selama ini memiliki reputasi +sebagai sesuatu yang rumit. +Kami percaya hal ini disebabkan karena rancangan yang kompleks seperti +https://en.wikipedia.org/wiki/POSIX_Threads[pthreads] +dan sebagian karena terlalu menekankan rincian level-bawah seperti _mutex_, +variabel kondisi, dan pembatasan _memory_. +Antarmuka yang lebih tinggi membuat kode lebih sederhana, walaupun tetap masih +ada _mutex_ dan lainnya di belakangnya. + +Salah satu model yang paling sukses dalam mendukung linguistik tingkat-tinggi +untuk konkurensi datang dari _Communicating Sequential Process_, atau CSP, +dari Hoare. +Occam dan Erlang adalah dua dari bahasa terkenal yang mengimplementasikan CSP. +Konkurensi primitif dari Go diturunkan dari bagian pohon keluarga yang berbeda +(dari Occam dan Erlang) yang kontribusi utamanya yaitu _channel_ sebagai +objek kelas satu. +Pengalaman dengan bahasa-bahasa sebelumnya telah memperlihatkan bahwa model +CSP sesuai dengan kerangka bahasa pemrograman prosedural. + +//}}} + +[#goroutines] +=== Kenapa goroutine bukannya _thread_? +//{{{ + +Goroutine adalah bagian yang membuat konkurensi mudah digunakan. +Idenya, yang mana telah ada sebelumnya, adalah dengan melakukan multipleks +saat mengeksekusi fungsi secara independen--coroutine--ke dalam kumpulan +_thread_. +Saat sebuah coroutine diblok, seperti saat melakukan pemanggilan ke sistem, +_runtime_ secara otomatis memindahkan coroutine yang lain dalam _thread_ yang +sama ke _thread_ yang berbeda yang dapat berjalan sehingga ia tidak ikut +terblok. +Programmer tidak melihat hal ini, itu intinya. +Hasilnya, yang kita sebut goroutine, bisa sangat murah: mereka memiliki +sedikit pengeluaran tambahan selain _memory_ untuk _stack_, yaitu beberapa +kilobyte. + +Untuk membuat supaya _stack_ -nya kecil, _runtime_ Go menggunakan _stack_ yang +terbatas dan bisa berubah ukuran. +Goroutine yang baru dibuat diberikan beberapa kilobyte, yang biasanya cukup. +Bila tidak, _runtime_ memperbesar (atau mengecilkan) _memory_ untuk menyimpan +_stack_ secara otomatis, membolehkan banyak goroutine untuk berjalan di dalam +sejumlah _memory_ yang berukuran sedang. +Ongkos pada CPU rata-rata sekitar tiga instruksi per pemanggilan fungsi. +Cukup praktis untuk membuat ratusan ribu goroutine dalam ruang alamat yang +sama. +Jika goroutine adalah _thread_, sumber daya sistem akan habis dengan jumlah +(_routine_) yang lebih sedikit. + +//}}} + +[#atomic_maps] +=== Kenapa operasi map tidak _atomic_? +//{{{ + +Setelah diskusi yang lama diputuskan bahwa penggunaan umum dari _map_ +dari beberapa goroutine tidak membutuhkan akses yang aman, dan pada kasus +yang membutuhkan akses yang aman, _map_ kemungkinan adalah bagian dari sebuah +struktur data atau komputasi yang besar yang telah disinkronisasi. +Oleh karena itu mengharuskan semua operasi _map_ menggunakan sebuah _mutex_ +akan memperlambat hampir semua program dan hanya mengamankan beberapa program +saja. +Hal ini bukanlah keputusan yang mudah, akan tetapi, akses terhadap _map_ yang +tidak dikontrol dapat membuat program _crash_. + +Bahasa Go sendiri tidak menghalangi pembaruan pada _map_ yang _atomic_. +Bila dibutuhkan, seperti saat menjalankan program yang tidak dipercaya, +implementasi bisa saja saling mengunci akses map. + +Akses _map_ akan tidak aman bila pembaruan terjadi. +Selama semua goroutine hanya membaca--melihat elemen dalam map, termasuk +iterasi menggunakan pengulangan `for range`--dan tidak mengubah _map_ dengan +menempatkan elemen baru atau menghapusnya, maka akan aman untuk mengakses +mereka secara konkuran tanpa sinkronisasi. + +Untuk membantu penggunaan _map_ yang benar, beberapa implementasi bahasa +memiliki pemeriksaan khusus yang secara otomatis melaporkan pada saat +_runtime_ bila sebuah _map_ diubah secara tidak aman oleh eksekusi yang +konkuren. + +//}}} + +[#language_changes] +=== Apakah anda akan menerima perubahan bahasa dari saya? +//{{{ + +Orang terkadang menyarankan perbaikan terhadap +bahasa +-- +https://groups.google.com/group/golang-nuts[milis] +banyak berisi sejarah diskusi ini--namun sangat sedikit dari perubahan +tersebut yang diterima. + +Walaupun Go adalah proyek sumber terbuka, bahasa dan pustakanya dilindungi +oleh +https://golang.org/doc/go1compat.html[perjanjian kompatibilitas] +yang mencegah perubahan yang dapat membuat program tidak dapat di- _compile_, +setidaknya pada tingkat sumber kode (program mungkin harus di _compile_ ulang +sewaktu-waktu). +Jika proposal anda melanggar spesifikasi Go 1 kita tidak dapat menerima ide +anda, terlepas dari kelebihannya. +Rilis mayor selanjutnya dari Go bisa saja tidak kompatibel dengan Go 1, namun +diskusi tentang topik tersebut baru saja dimulai dan satu hal yang pasti: +hanya ada sedikit ketaksesuaian yang diperkenalkan dalam proses tersebut. +Lebih lanjut lagi, perjanjian kompatibilitas mendorong kita untuk menyediakan +sebuah cara otomatis kedepannya supaya program-program yang lama dapat +beradaptasi jika situasi tersebut muncul. + +Bahkan jika proposal anda kompatibel dengan spesifikasi Go 1, ia mungkin tidak +sesuai dengan jiwa dari sasaran rancangan Go. +Artikel +{talks-go-at-google}[Go di Google] +menjelaskan asal mula Go dan motivasi dibalik rancangannya. + +//}}} + +[#types] +== Tipe + +[#Is_Go_an_object-oriented_language] +=== Apakah Go bahasa berorientasi-objek? +//{{{ + +Ya dan tidak. +Walaupun Go memiliki tipe dan _method_ dan membolehkan pemrograman bergaya +orientasi-objek, Go tidak memiliki hirarki tipe. +Konsep "interface" dalam Go menyediakan pendekatan berbeda yang kami percaya +lebih mudah digunakan dan dalam beberapa hal lebih umum. +Ada cara untuk menanam tipe ke dalam tipe lain untuk membentuk analogi yang +sama--tapi tidak identik--dengan _subclass_. +_Method_ dalam Go lebih umum daripada C++ atau Java: mereka dapat +didefinisikan untuk data apapun, bahkan tipe bawaan seperti integer. +_Method_ tidak hanya terbatas pada _struct_ (_class_). + +Selain itu, dengan tidak adanya hirarki tipe membuat "objek" dalam Go lebih +ringan daripada bahasa seperti C++ atau Java. + +//}}} + +[#How_do_I_get_dynamic_dispatch_of_methods] +=== Bagaimana cara mengirim _method_ secara dinamis? +//{{{ + +Satu-satunya cara untuk mengirim _method_ secara dinamis adalah lewat +_interface_. +_Method_ pada _struct_ atau tipe konkret lainnya selalu dikonversi secara +statis. + +//}}} + +[#inheritance] +=== Kenapa tidak ada tipe turunan? +//{{{ + +Pemrograman berorientasi-objek, setidaknya pada bahasa-bahasa yang terkenal, +selalu mendiskusikan hubungan antara tipe, hubungan yang sering kali bisa +diturunkan secara otomatis. +Go mengambil pendekatan berbeda. + +Pemrogram tidak perlu mendeklarasikan bahwa dua tipe saling berelasi, +melainkan dalam Go sebuah tipe otomatis memenuhi _interface_ apapun yang +menspesifikasikan sub bagian dari _method_ nya. +Selain mengurangi pencatatan, pendekatan ini memiliki kelebihan. +Tipe dapat memenuhi banyak _interface_, tanpa adanya kompleksitas dari +multipel turunan tradisional. +Interface bisa sangat ringan--sebuah _interface_ dengan satu atau bahkan tanpa +_method_ dapat mengekspresikan konsep yang berguna. +_Interface_ dapat ditambahkan setelah sebuah ide baru muncul atau untuk +pengujian--tanpa mempengaruhi tipe asilnya. +Karena tidak adanya relasi eksplisit antara tipe dan _interface_, maka tidak +ada hirarki tipe yang harus diatur atau didiskusikan. + +Ide ini bisa digunakan untuk membentuk sebuah analogi dari Unix _pipe_. +Misalnya, lihat bagaimana `fmt.Fprintf` membolehkan pencetakan berformat ke +keluaran apapun, tidak hanya berkas, atau bagaimana paket `bufio` dapat +terpisah sepenuhnya dari berkas I/O, atau bagaimana paket `image` +membangkitkan berkas gambar yang terkompres. +Semua ide-ide ini datang dari sebuah _interface_ (`io.Writer`) yang +merepresentasikan sebuah _method_ (`Write`). +Dan kita baru hanya menyentuh bagian luar dari _interface_. +_Interface_ pada Go memiliki pengaruh yang kuat tentang bagaimana sebuah +program dibangun. + +Butuh beberapa waktu untuk terbiasa namun dengan model dependensi tipe seperti +ini adalah salah satu hal yang produktif dari Go. + +//}}} + +[#methods_on_basics] +=== Kenapa `len` adalah sebuah fungsi bukan _method_? +//{{{ + +Kami memperdebatkan masalah ini namun kemudian memutuskan mengimplementasikan +`len` dan teman-temannya sebagai fungsi karena dalam praktiknya tidak +mempersulit masalah tentang tipe dasar _interface_. + +//}}} + +[#overloading] +=== Kenapa Go tidak mendukung _overloading_ _method_ dan operator? +//{{{ + +Pengiriman _method_ menjadi sederhana jika ia tidak memerlukan pencocokan +tipe. +Pengalaman kami dengan bahasa-bahasa pemrograman lain menyimpulkan bahwa +memiliki beragam _method_ dengan nama yang sama tapi dengan _signature_ yang +berbeda terkadang berguna namun pada praktiknya bisa membingungkan dan rapuh. +Pencocokan hanya dengan nama dan konsistensi pada tipe adalah keputusan +penyederhanaan utama dalam sistem tipe Go. + +Perihal _overloading_ operator, sebenarnya lebih pada kenyamanan daripada +kebutuhan yang absolut. +Sekali lagi, hal-hal menjadi lebih sederhana tanpa adanya kebutuhan tersebut. + +//}}} + +[#implements_interface] +=== Kenapa Go tidak memiliki deklarasi "implement"? +//{{{ + +Sebuah tipe memenuhi sebuah _interface_ dengan mengimplementasikan +_method-method_ pada _interface_ tersebut, cukup itu saja. +Properti ini membolehkan _interface_ didefinisikan dan digunakan tanpa +harus mengubah kode yang ada. +Ia membolehkan semacam +https://en.wikipedia.org/wiki/Structural_type_system[penulisan struktural] +yang mempromosikan pemisahan antara kebutuhan-kebutuhan dan meningkatkan +penggunaan ulang pada kode, dan mempermudah membangun pola-pola yang +muncul pada saat membangun kode. +Semantik dari _interface_ adalah salah satu alasan utama dari kecepatan dan +keringanan pada Go. + +Lihat pertanyaan tentang <<inheritance,turunan>> untuk informasi lebih rinci. + +//}}} + +[#guarantee_satisfies_interface] +=== Bagaimana saya menjamin tipe memenuhi sebuah _interface_? +//{{{ + +Kita bisa menggunakan _compiler_ untuk memeriksa apakah tipe `T` +mengimplementasikan _interface_ `I` dengan mencoba menempatkan nilai kosong +dari `T` atau pointer ke `T`, sebagai berikut: + +---- +type T struct{} +var _ I = T{} // Memverifikasi bahwa T mengimplementasikan I. +var _ I = (*T)(nil) // Memverifikasi bahwa *T mengimplementasikan I. +---- + +Jika `T` (atau `*T`) tidak mengimplementasikan `I`, kesalahan tersebut akan +terdeteksi saat kode di- _compile_. + +Jika kita menginginkan pengguna dari _interface_ secara eksplisit +mengimplementasikannya, kita bisa menambahkan sebuah _method_ dengan nama yang +deskriptif. +Sebagai contohnya: + +---- +type Fooer interface { + Foo() + ImplementsFooer() +} +---- + +Sebuah tipe harus mengimplementasikan _method_ `ImplementsFooer` supaya bisa +menjadi `Fooer`, dengan jelas mendokumentasikan fakta tersebut dan +memunculkannya pada +https://golang.org/cmd/go/#hdr-Show_documentation_for_package_or_symbol[go +doc]. + +---- +type Bar struct{} +func (b Bar) ImplementsFooer() {} +func (b Bar) Foo() {} +---- + +Umumnya kode tidak menggunakan batasan seperti itu, karena membatasi utilitas +dari ide tentang _interface_. +Terkadang, mereka diperlukan juga untuk mengatasi masalah ambigu di antara +_interface_-_interface_ yang mirip. + +//}}} + +[#t_and_equal_interface] +=== Kenapa tipe `T` tidak memenuhi _interface_ Equal? +//{{{ +Anggaplah _interface_ sederhana berikut merepresentasikan sebuah objek yang +dapat dibandingkan dengan nilai yang lain: + +---- +type Equaler interface { + Equal(Equaler) bool +} +---- + +dan tipe `T` berikut: + +---- +type T int +func (t T) Equal(u T) bool { return t == u } // tidak memenuhi Equaler +---- + +Tidak seperti sistem bertipe _polymorphic_, dalam Go, `T` tidak +mengimplementasikan `Equaler`. +Tipe dari argumen `T.Equal` adalah `T`, bukan tipe yang dibutuhkan oleh +`Equaler`. + +Dalam Go, sistem tipe tidak mempromosikan argumen dari `Equal`; +hal tersebut merupakan tanggung jawab dari pemrogram, seperti yang digambarkan +oleh tipe `T2`, yang mengimplementasikan `Equaler`: + +---- +type T2 int +func (t T2) Equal(u Equaler) bool { return t == u.(T2) } // memenuhi Equaler +---- + +Walaupun hal ini tidak seperti sistem tipe lainnya, karena pada Go _semua_ +tipe yang memenuhi _Equaler_ dapat dikirim sebagai argumen ke `T2.Equal`, dan +pada saat _runtime_ kita harus memeriksa bahwa argumen benar bertipe `T2`. +Beberapa bahasa mengatur supaya hal tersebut terjamin pada saat di- _compile_. + +Contoh lain yang berhubungan: + +---- +type Opener interface { + Open() Reader +} + +func (t T3) Open() *os.File +---- + +Dalam Go, `T3` tidak memenuhi `Opener`, walaupun dalam bahasa pemrogram lain +ia bisa saja terpenuhi. + +Memang benar bahwa sistem tipe Go bekerja kurang bagi programmer pada +kasus-kasus tersebut, tidak adanya sub-tipe membuat aturan tentang pemenuhan +sebuah _interface_ sangat mudah ditulis: apakah nama fungsi dan +argumen-argumennya sama dengan yang di _interface_? +Aturan Go ini sangat mudah diimplementasikan secara efisien. +Kami merasakan bahwa keuntungan ini mengimbangi kekurangan dari tipe otomatis. +Bila Go suatu saat nanti mengadopsi sebuah bentuk penulisan _polymorphic_, +kami mengharapkan ada suatu cara mengekspresikan ide dari contoh-contoh +tersebut dan juga membuatnya supaya diperiksa secara statis. + +//}}} + +[#convert_slice_of_interface] +=== Bisakah mengkonversi `[]T` ke `[]interface{}`? +//{{{ + +Tidak secara langsung. +Hal ini tidak dibolehkan oleh spesifikasi bahasa karena kedua tipe tersebut +tidak memiliki representasi yang sama dalam _memory_. +Maka diperlukan penyalinan elemen secara tersendiri ke slice tujuan. +Contoh berikut mengkonversi sebuah slice `int` ke slice `interface{}`: + +---- +t := []int{1, 2, 3, 4} +s := make([]interface{}, len(t)) +for i, v := range t { + s[i] = v +} +---- + +//}}} + +[#convert_slice_with_same_underlying_type] +=== Bisakah mengkonversi `[]T1` ke `[]T2` jika `T1` dan `T2` memiliki tipe dasar yang sama? +//{{{ + +Baris terakhir dari contoh kode berikut tidak bisa di _compile_. + +---- +type T1 int +type T2 int +var t1 T1 +var x = T2(t1) // OK +var st1 []T1 +var sx = ([]T2)(st1) // NOT OK +---- + +Dalam Go, tipe-tipe berkaitan dengan _method_, sehingga setiap tipe bernama +memiliki sebuah (bisa kosong) kumpulan _method_. +Aturan umumnya adalah anda bisa mengubah nama dari tipe yang dikonversi +(sehingga bisa mengubah kumpulan _method_ nya) tapi kita tidak bisa mengubah +nama (dan kumpulan _method_) dari elemen-elemen dari sebuah tipe komposit. +Go mengharuskan kita mengkonversi tipe secara eksplisit. + +//}}} + +[#nil_error] +=== Kenapa nilai error nil tidak sama dengan nil? +//{{{ + +Di balik layar, _interface_ diimplementasikan sebagai dua elemen, sebuah tipe +`T` dan sebuah nilai `V`. +`V` adalah nilai konkret seperti sebuah `int`, `struct` atau pointer, bukan +_interface_, dan memiliki tipe `T`. +Misalnya, jika kita menyimpan nilai `int` 3 ke dalam sebuah _interface_, +kembalian dari _interface_ memiliki, secara semantik, (`T=int, V=3`). +Nilai `V` dikenal juga dengan nilai _dinamis_ dari _interface_, secara +variabel _interface_ tersebut bisa saja menyimpan nilai `V` yang berbeda (yang +berkorespondensi dengan tipe `T`) selama berjalannya program. + +Sebuah _interface_ bernilai `nil` jika dan hanya `V` dan `T` tidak diset, +(`T=nil, `V` tidak di set). +Lebih rincinya, sebuah _interface_ `nil` selalu menyimpan tipe `nil`. +Jika kita menyimpan pointer `nil` bertipe `*int` dalam sebuah nilai +_interface_, maka tipe di dalamnya adalah `*int` berapapun nilai dari pointer +tersebut: (`T=*int, V=nil`). +Nilai _interface_ tersebut akan selalu non-nil walaupun nilai pointer `V` +adalah `nil`. + +Situasi seperti ini bisa membingungkan, dan muncul bila nilai `nil` disimpan +di dalam sebuah nilai _interface_ seperti dalam nilai kembalian `error`. + +---- +func returnsError() error { + var p *MyError = nil + if bad() { + p = ErrBad + } + return p // Akan selalu mengembalikan nilai error non-nil. +} +---- + +Jika semua berjalan dengan baik, fungsi di atas mengembalikan `p` yang `nil`, +jadi nilai kembalian adalah sebuah nilai _interface_ `error` yang menyimpan +(`T=*MyError, V=nil`). +Jika pemanggil fungsi membandingkan nilai kembalian `error` dengan `nil`, ia +akan selalu bernilai `true` walaupun tidak ada eror yang terjadi. +Untuk mengembalikan `nil error` yang benar ke pemanggil, fungsi tersebut harus +mengembalikan `nil` secara eksplisit: + +---- +func returnsError() error { + if bad() { + return ErrBad + } + return nil +} +---- + +Fungsi yang mengembalikan `error` sebaiknya selalu menggunakan tipe `error` +dalam _signature_ -nya (seperti contoh di atas) bukan dengan tipe konkret +seperti `*MyError`, untuk menjamin `error` dibuat dengan benar. +Sebagai contoh, +https://golang.org/pkg/os/#Open[os.Open] +mengembalikan `error` walaupun, jika tidak `nil`, ia selalu bertipe konkret +https://golang.org/pkg/os/#PathError[*os.PathError]. + +Situasi yang sama seperti yang dijelaskan di sini dapat muncul kapan pun +_interface_ digunakan. +Cukup diingat, jika nilai konkret disimpan dalam _interface_, maka _interface_ +tersebut tidak akan bernilai `nil`. +Untuk informasi lebih lanjut, lihat +https://golang.org/doc/articles/laws_of_reflection.html[Hukum refleksi]. + +//}}} + +[#unions] +=== Kenapa tidak ada _union_, seperti pada C? + +Union akan melanggar jaminan keamanan _memory_ pada Go. + +[#variant_types] +=== Kenapa Go tidak memiliki tipe varian? +//{{{ + +Tipe varian, dikenal juga dengan tipe aljabar, menyediakan suatu cara untuk +menspesifikasikan bahwa sebuah nilai bisa memiliki salah satu dari sekumpulan +tipe, namun hanya tipe-tipe yang didefinisikan saja. +Salah satu contoh umum yaitu pada pemrograman sistem yang menspesifikasikan +bahwa sebuah eror adalah eror jaringan, eror keamanan, atau eror pada aplikasi +dan membolehkan pemanggil untuk membedakan sumber dari permasalahan dengan +membedah tipe dari eror. +Contoh lainnya yaitu pohon sintaks yang mana setiap node dapat memiliki tipe +yang berbeda: deklarasi, perintah, penempatan, dan lainnya. + +Kami mempertimbangkan menambahkan tipe varian ke dalam Go, namun setelah +berdiskusi lebih lanjut kami memutuskan untuk mengindahkannya karena tumpang +tindih dengan _interface_. +Apa yang terjadi jika elemen dari sebuah tipe varian adalah _interface_ dari +dirinya sendiri? + +Selain itu, beberapa permasalahan dari tipe varian telah dipenuhi oleh bahasa +Go. +Contohnya pada penanganan eror yang bisa diekspresikan dengan menggunakan +nilai _interface_ yang menyimpan eror dan switch bertipe untuk membedakannya. +Pohon sintaks juga bisa diterapkan dengan model yang sama, walaupun kurang +elegan. + +//}}} + +[#covariant_types] +=== Kenapa Go tidak memiliki tipe kembalian _covariant_? +//{{{ + +Tipe kembalian _covariant_ artinya sebuah _interface_ seperti + +---- +type Copyable interface { + Copy() interface{} +} +---- + +akan dipenuhi oleh _method_ + +---- +func (v Value) Copy() Value +---- + +karena `Value` mengimplementasikan _interface_ kosong. +Dalam Go, tipe _method_ harus sesuai secara eksak, jadi `Value` tidak +mengimplementasikan `Copyable`. +Go memisahkan antara apa yang sebuah tipe dapat lakukan--_method_ -nya--dari +apa yang diimplementasinya. +Jika dua _method_ mengembalikan tipe yang berbeda, mereka berarti tidak +melakukan hal yang sama. +Pemrogram yang menginginkan tipe kembalian _covariant_ terkadang mencoba +mengekspresikan hirarki tipe lewat _interface_. +Dalam Go lebih wajar untuk memiliki pemisahan yang jelas antara _interface_ +dan implementasinya. + +//}}} + +[#values] +== Nilai + +[#conversions] +=== Kenapa Go tidak menyediakan konversi numerik implisit? +//{{{ + +Kenyamanan dari konversi otomatis antara tipe numerik dalam C lebih dirugikan +oleh kebingungan yang disebabkannya. +Kapan sebuah ekspresi menjadi _unsigned_? +Berapa besar nilainya? +Apakah nilainya _overflow_? +Apakah hasilnya portabel, independen terhadap mesin dimana program dieksekusi? +Ia juga memperuit _compiler_; +"konversi aritmatika biasa" tidaklah mudah diimplementasikan dan tidak +konsisten antara arsitektur (mesin). +Dengan alasan portabilitas, kami memutuskan untuk membuat konversi lebih jelas +dan lugas dengan biaya beberapa konversi eksplisit dalam kode. +Definisi dari konstanta dalam Go--nilai presisi acak bebas dari notasi ukuran +dan _signed_--memperbaiki banyak hal. + +Rincian yang berhubungan dengan ini adalah, tidak seperti C, `int` dan `int64` +adalah tipe yang berbeda walaupun jika `int` bertipe 64-bit. +Tipe `int` adalah generik; +jika anda ingin tahu berapa bits dalam sebuah integer, Go menyarankan kita +untuk eksplisit. + +//}}} + +[#constants] +=== Bagaimana konstanta bekerja dalam Go? +//{{{ + +Walaupun Go ketat dalam konversi antara variabel dari tipe numerik yang +berbeda, kontansta lebih fleksibel. +Konstanta harfiah seperti `23`, `3.14159`, dan +https://golang.org/pkg/math/#pkg-constants[math.Pi] +menggunakan ruang yang sama, dengan presisi yang berubah dan tanpa _overflow_ +atau _underflow_. +Misalnya, nilai `math.Pi` dispesifikasikan memakai 63 bit dalam sumber kode, +dan ekspresi konstanta yang mengikutkan nilai tersebut menjaga presisi tetap +sesuai dengan batas maksimum yang dapat disimpan dalam `float64`. +Hanya pada saat konstanta atau ekspresi konstanta diberikan ke sebuah +variabel--sebuah lokasi _memory_ dalam program--ia menjadi sebuah angka +"komputer" dengan properti dan presisi nilai _float_. + +Secara mereka adalah angka, bukan nilai bertipe, konstanta dalam Go dapat +digunakan lebih bebas daripada variabel, sehingga meringankan beberapa +kecanggungan antar aturan-aturan konversi yang baku. +Kita dapat menulis ekspresi berikut + +---- +sqrt2 := math.Sqrt(2) +---- + +tanpa ada keluhan dari _compiler_ karena angka `2` bisa dikonversi secara aman +dan akurat ke `float64` untuk pemanggilan `math.Sqrt`. + +Sebuah blog berjudul +https://blog.golang.org/constants[Konstanta (Inggris)] +mengeksplorasi topik ini lebih rinci. + +//}}} + +[#builtin_maps] +=== Kenapa map merupakan tipe bawaan? +//{{{ + +Dengan alasan yang sama seperti `string`: karena map adalah struktur data yang +penting dan kuat sehingga dengan menyediakan implementasi yang istimewa dengan +dukungan sintaktis membuat pemrograman lebih menyenangkan. +Kami percaya implementasi map pada Go cukup kuat sehingga ia dapat digunakan +untuk hampir semua kasus. +Jika aplikasi tertentu lebih menguntungkan dari implementasi kostum, maka +memungkinan untuk membuatnya namun tidak akan lebih nyaman secara sintaks; +hal ini pengorbanan masuk akal. + +//}}} + +[#map_keys] +=== Kenapa map tidak membolehkan slice sebagai key? +//{{{ + +Pencarian key pada map membutuhkan operator ekualitas, yang mana tidak +diimplementasikan pada slice. +Slice tidak memiliki ekualitas karena ekualitas tidak terdefinisi dengan baik +pada tipe tersebut; +ada beberapa pertimbangan yang mengikutkan perbandingan _shallow_ dan _deep_, +perbandingan pointer vs. nilai, bagaimana berurusan dengan tipe rekursif, dan +lainnya. +Kami mungkin akan menelaah kembali isu ini--dan mengimplementasikan ekualitas +pada slice tidak akan merubah program yang sudah ada--namun tanpa adanya ide +yang jelas tentang apa itu ekualitas pada slice, maka lebih mudah untuk +mengindahkannya untuk saat sekarang. + +Pada Go 1, tidak seperti rilis sebelumnya, ekualitas didefinisikan untuk +`struct` dan _array_, sehingga tipe tersebut dapat digunakan sebagai key dari +map. +Slice masih belum memiliki definisi tentang ekualitas. + +//}}} + +[#references] +=== Kenapa map, slice, dan channel menggunakan referensi sementara array dengan nilai? +//{{{ + +Sejarah mengenai topik ini cukup panjang. +Pada awalnya, map dan channel secara sintaks adalah pointer dan memungkinan +untuk mendeklarasikan atau menggunakan instansi yang bukan pointer (pada map +dan channel). +Dan juga, kami agak susah dengan mendefinisikan bagaimana _array_ seharusnya +bekerja dalam Go. +Akhirnya kami memutuskan bahwa pemisahan yang baku antara pointer dan nilai +membuat bahasa sulit untuk digunakan. +Mengubah tipe tersebut untuk bersifat referensi terhadap asosiasi, struktur +data berbagi, mengatasi masalah tersebut. +Perubahan ini menambah kompleksitas yang disesalkan pada bahasa namun memiliki +efek yang besar pada kebergunaan: Go menjadi lebih produktif, bahasa yang +nyaman saat dikenalkan ke dunia luar. + +//}}} + +[#Writing_Code] +== Menulis Kode + +[#How_are_libraries_documented] +=== Bagaimana pustaka didokumentasikan? +//{{{ + +Sebuah program, `godoc`, ditulis dengan Go, mengekstrak dokumentasi paket dari +sumber kode dan membuatnya dapat dibukan dalam sebuah halaman web dengan +tautan ke deklarasi, berkas, dan lainnya. +Salah satu instansinya berjalan di +https://golang.org/pkg/[golang.org/pkg]. +Pada kenyataannya, `godoc` mengimplementasikan keseluruhan situs +https://golang.org/[golang.org]. + +Instansi dari `godoc` bisa dikonfigurasi untuk menyediakan analisis interaktif +yang kaya dari simbol dalam program; +rinciannya ada dalam daftar +https://golang.org/lib/godoc/analysis/help.html[berikut]. + +Untuk mengakses dokumentasi dari baris perintah, perkakas +https://golang.org/pkg/cmd/go/[go] +memiliki sub-perintah +https://golang.org/pkg/cmd/go/#hdr-Show_documentation_for_package_or_symbol[doc] +yang menyediakan antarmuka tekstual dari informasi yang sama. + +//}}} + +[#Is_there_a_Go_programming_style_guide] +=== Apakah ada panduan gaya pemrograman Go? +//{{{ + +Tidak ada aturan gaya yang eksplisit, meskipun ada beberapa "Gaya Go" yang +cukup dikenal. + +Go telah menetapkan konvensi untuk membantu melakukan penamaan, susunan, dan +pengorganisasian berkas. +Dokumentasi +link:/doc/effective_go.html[Efektif Go] +memiliki beberapa saran mengenai topik ini. +Lebih lanjut, program `gofmt` bertujuan untuk mencetak sumber kode dengan +aturan-aturan yang baku; +ia menggantikan aturan tertulis yang memboleh interpretasi. +Semua kode Go dalam repositori, dan hampir mayoritas dalam dunia _open +source_, telah dijalankan lewat `gofmt`. + +Dokumen berjudul +https://golang.org/s/comments[Komentar Pemeriksaan Kode Go] +berisi kumpulan esai ringkas tentang rincian idiom dari Go yang terkadang +luput oleh para pemrogram. +Dokumen tersebut adalah referensi yang membantu bagi yang ingin memeriksa kode +untuk proyek Go. + +//}}} + +[#How_do_I_submit_patches_to_the_Go_libraries] +=== Bagaimana cara mengirim _patch_ untuk pustaka Go? +//{{{ + +Sumber pustaka ada di dalam direktori `src` dari repositori. +Jika anda ingin membuat perubahan yang signifikan, mohon diskusikan terlebih +dahulu di milis sebelum memulai. + +Lihat dokumentasi +https://golang.org/doc/contribute.html[Berkontribusi pada proyek Go] +untuk informasi lebih lanjut. + +//}}} + +[#git_https] +=== Kenapa "go get" menggunakan HTTPS saat menyalin repositori? +//{{{ + +Perusahaan terkadang hanya membolehkan trafik TCP keluar pada port standar 80 +(HTTP) dan 443 (HTTPS), dan memblok trafik lainnya, termasuk port 9418 pada +TCP (git) dan port TCP 22 (SSH). +Bila menggunakan HTTPS, `git` mengharuskan validasi sertifikat, menyediakan +perlindungan terhadap _man in the middle_, penyadapan, dan perusakan. +Perintah `go get` oleh karena itu menggunakan HTTPS untuk keamanan. + +`Git` bisa dikonfigurasi untuk melakukan otentikasi lewat HTTP atau +menggunakan SSH. +Untuk otentikasi lewat HTTP, kita bisa menambahkan baris berikut dalam berkas +`$HOME/.netrc` yang akan dibaca oleh `git`: + +---- +machine github.com login _USERNAME_ password _APIKEY_ +---- + +Untuk akun Github, kata kunci (_password_) bisa berupa +https://help.github.com/articles/creating-a-personal-access-token-for-the-command-line/[token +akses personal]. + +`Git` juga bisa dikonfigurasi menggunakan SSH bukan HTTPS untuk URL yang cocok +dengan prefiks tertentu. +Misalnya, untuk menggunakan SSH untuk semua akses ke Github, tambahkan baris +berikut ke `~/.gitconfig`: + +---- +[url "ssh://git@github.com/"] + insteadOf = https://github.com/ +---- + +//}}} + +[#get_version] +=== Bagaimana cara mengatur versi paket menggunakan "go get"? +//{{{ + +Sejak awal proyek, Go tidak memiliki konsep versi paket, namun hal ini +berubah. +_Versioning_ (paket dengan versi) adalah sebuah kompleksitas yang signifikan, +terutama dalam basis kode yang besar, dan butuh waktu yang cukup lama untuk +mengembangkan sebuah pendekatan yang bekerja dalam skala yang cukup besar +untuk beragam situasi yang cocok bagi semua pengguna Go. + +Rilis Go 1.11 menyediakan dukungan eksperimental untuk paket dengan versi +terhadap perintah `go`, dalam bentuk modul. +Untuk informasi lebih lanjut, lihat +https://golang.org/doc/go1.11#modules[catatan rilis Go 1.11] +dan +https://golang.org/cmd/go#hdr-Modules__module_versions__and_more[dokumentasi +perintah go]. + +Bagaimanapun teknologi manajemen paketnya, "go get" dan perkakas Go lainnya +menyediakan isolasi paket dengan path import yang berbeda. +Misalnya, pustaka standar `html/template` dan `text/template` hidup +berdampingan walaupun keduanya adalah "paket untuk template". +Hal ini mengarah pada beberapa anjuran untuk penulis paket dan pengguna paket. + +Paket yang ditujukan untuk digunakan secara umum sebaiknya mencoba untuk +menjaga kompatibilitas selama berkembang. +https://golang.org/doc/go1compat.html[pedoman kompatibilitas Go 1] adalah +sebuah referensi yang baik: jangan menghapus nama-nama yang diekspor, +menganjurkan komposit dengan tag, dan lainnya. +Jika fungsionalitas berbeda dibutuhkan, tambahkan nama baru bukan dengan +mengubah nama yang sudah ada. +Jika perubahan besar benar-benar tidak dapat dielakan, buatlah paket baru +dengan path impor yang baru. + +Jika menggunakan paket luar dan khawatir ia akan berubah secara tidak terduga, +namun belum menggunakan Go module, solusi termudah yaitu menyalinnya ke dalam +repositori anda. +Pendekatan ini digunakan oleh Google secara internal dan didukung oleh +perkakas `go` lewat sebuah teknik yang disebut "vendoring". +Hal ini mengikutkan penyimpanan semua salinan dependensi dibawah path import +yang mengidentifikasi mereka sebagai salinan lokal. +Lihat +https://golang.org/s/go15vendor[dokumen rancangan] untuk lebih rinci. + +//}}} + +[#Pointers] +== Pointer dan Alokasi + +[#pass_by_value] +=== Kapan parameter fungsi dikirim dengan nilai? +//{{{ + +Semua parameter pada fungsi dikirim dengan nilai pada Go. +Fungsi selalu menerima salinan dari apa yang dikirim. +Misalnya, mengirim nilai `int` ke sebuah fungsi membuat salinan dari `int`, +dan mengirim nilai pointer membuat salinan dari pointer, tapi tidak menyalin +data yang diacu. +(Lihat +<<methods_on_values_or_pointers, bagian selanjutnya>> +untuk diskusi bagaimana hal ini mempengaruhi penerima _method_.) + +Nilai map dan slice memiliki perilaku yang sama dengan pointer: mereka adalah +struktur data yang mengandung pointer ke bagian dalam data map dan slice. +Mengirim sebuah nilai map atau slice tidak akan menyalin data yang diacunya. +Mengirim nilai _interface_ membuat salinan dari apa yang disimpan dalam nilai +_interface_. +Jika nilai _interface_ menyimpan sebuah struct, mengirim nilai _interface_ +akan membuat salinan dari struct. +Jika _interface_ menyimpan pointer, mengirim nilai _interface_ berarti membuat +salinan dari pointer, namun sekali lagi tidak membuat salinan dari data yang +diacu. + +Ingatlah bahwa diskusi ini lebih kepada semantik dari operasi. +Implementasi sebenarnya bisa saja memiliki optimisasi untuk menghindari +penyalinan selama optimisasi tersebut tidak merubah semantik. + +//}}} + +[#pointer_to_interface] +=== Kapan sebaiknya menggunakan pointer ke interface? +//{{{ + +Hampir tidak pernah. +Pointer ke nilai _interface_ muncul hanya pada situasi yang rumit dan unik +yang mengikutkan penyembunyian tipe nilai _interface_ untuk evaluasi yang +ditunda. + +Kesalahan yang sering terjadi yaitu mengirim pointer ke sebuah nilai +_interface_ terhadap fungsi yang mengharapkan sebuah _interface_. +_compiler_ akan melaporkan kesalahan ini, namun situasi ini terkadang juga +membingungkan, karena terkadang +https://golang.org/doc/faq#different_method_sets[pointer diperlukan untuk +memenuhi sebuah interface]. +Intinya adalah pointer ke tipe kongkret akan memenuhi sebuah _interface_, +namun pointer ke sebuah _interface_ tidak akan pernah memenuhi _interface_. + +Misalnya deklarasi variabel berikut, + +---- +var w io.Writer +---- + +Fungsi pencetakan `fmt.Fprintf` menerima argumen pertama yang memenuhi +`io.Writer`--apapun yang mengimplementasikan method `Write`. +Maka kita dapat menulis + +---- +fmt.Fprintf(w, "hello, world\n") +---- + +Jika kita mengirim alamat dari `w`, program tidak akan bisa di- _compile_. + +---- +fmt.Fprintf(&w, "hello, world\n") // Compile-time error. +---- + +Satu-satunya pengecualian yaitu nilai apapun, bahkan sebuah pointer ke +_interface_, dapat ditempatkan ke sebuah variabel bertipe interface kosong +(`interface{}`). +Namun demikian, sudah pasti sebuah kesalahan bila nilainya adalah pointer ke +_interface_; +hasilnya bisa membingungkan. + +//}}} + +[#methods_on_values_or_pointers] +=== Apakah method sebaiknya didefinisikan dengan nilai atau pointer? +//{{{ + +---- +func (s *MyStruct) pointerMethod() { } // method dengan pointer +func (s MyStruct) valueMethod() { } // method dengan nilai +---- + +Bagi pemrogram yang tidak terbiasa dengan pointer, perbedaan antara kedua +contoh di atas bisa membingungkan, tapi sebenarnya situasinya cukup sederhana. +Saat mendefinisikan method pada sebuah tipe, penerima (`s` pada contoh di +atas) berlaku seperti sebuah argumen terhadap _method_. + +---- +func pointerMethod(s *MyStruct) { } // ilustrasi method dengan pointer +func valueMethod(s MyStruct) { } // ilustrasi method dengan nilai +---- + +Apakah sebaiknya mendefinisikan penerima dalam bentuk nilai atau pointer +adalah pertanyaan yang sama dengan apakah sebuah argumen dari fungsi sebaiknya +dengan nilai atau pointer. +Ada beberapa pertimbangan di sini. + +Pertama, dan yang paling penting, apakah method butuh mengubah penerimanya? +Jika iya, si penerima _harus_ berupa pointer. +(Slice dan map berlaku sebagai referensi, perilakunya sedikit berbeda, +misalnya untuk mengubah panjang dari sebuah slice dalam sebuah method, si +penerima harus berupa pointer.) +Pada contoh di atas, jika `pointerMethod` mengubah _field_ dari `s`, pemanggil +akan melihat perubahannya, namun `valueMethod` dipanggil dengan salinan dari +argumen pemanggil (ini adalah definisi dari pengiriman dengan nilai), sehingga +perubahan yang terjadi tidak terlihat bagi pemanggil. + +Penerima method pada Java selalu pointer, walaupun bentuk pointer-nya +disamarkan (dan sekarang ada proposal untuk menambahkan penerima dengan nilai +ke bahasa Java). +Penerima dengan nilai-lah sebenarnya yang tidak umum di Go. + +Yang kedua yaitu pertimbangan efisiensi. +Jika struktur data si penerima cukup besar, akan lebih efisien bila +menggunakan pointer sebagai penerima. + +Selanjutnya yaitu konsistensi. +Jika beberapa penerima method dari tipe harus berupa pointer, sisanya juga +sebaiknya sama, sehingga kumpulan method dari tipe tersebut konsisten walau +bagaimanapun tipe tersebut digunakan. +Lihat bagian +<<different_method_sets,kumpulan method>> +untuk lebih rinci. + +Untuk tipe dasar, slice, dan `struct` yang kecil, penerima dengan nilai +sangatlah murah, jadi bila semantik dari method membutuhkan pointer, +penerima dengan nilai bisa efisien dan lebih jelas. + +//}}} + +[#new_and_make] +=== Apakah perbedaan antara new dan make? +//{{{ + +Singkat kata: `new` mengalokasikan _memory_, sementara `make` menginisialisasi +tipe slice, map, dan channel. + +Lihat +link:/doc/effective_go.html#allocation_new[bagian terkait pada Efektif Go] +untuk lebih rincinya. + +//}}} + +[#q_int_sizes] +=== Berapakah ukuran `int` pada mesin 64-bit? +//{{{ + +Ukuran dari `int` dan `uint` spesifik pada implementasi namun ukurannya sama +pada semua _platform_. +Demi portabilitas, kode yang bergantung pada ukuran nilai tertentu sebaiknya +menggunakan ukuran tipe yang eksplisit, seperti `int64`. +Pada mesin 32-bit, _compiler_ menggunakan 32-bit integer secara bawaan, +sementara pada mesin 64-bit, integer memiliki ukuran 64-bit. +(Dalam sejara bahasa pemrograman, hal ini tidak selalu benar.) + +Di lain sisi, tipe skalar _floating point_ dan _complex_ selalu memiliki +ukuran (tidak ada tipe dasar `float` atau `complex`), karena pemrogram +seharusnya memperhatikan presisi saat menggunakan bilangan _floating point_. +Tipe standar untuk konstanta _floating point_ (tanpa tipe) adalah `float64`. +Maka `foo := 3.0` mendeklarasikan sebuah variabel `foo` bertipe `float64`. +Untuk variabel bertipe `float32` yang diinisialisasi dengan konstanta, tipe +variabel haruslah dispesifikasikan saat deklarasi: + +---- +var foo float32 = 3.0 +---- + +Cara lain, yaitu mendeklarasikan kontanta tersebut menggunakan konversi tipe +seperti berikut `foo := float32(3.0)`. + +//}}} + +[#stack_or_heap] +=== Bagaimana mengetahui variabel dideklarasikan dalam _heap_ atau _stack_? +//{{{ + +Dari sisi penggunaan, anda tidak perlu tahu. +Setiap variabel di Go akan disimpan selama ada yang mengacunya. +Lokasi penyimpanan yang dipilih oleh implementasi tidak relevan dengan +semantik dari bahasa. + +Lokasi penyimpanan memang berpengaruh pada efisiensi program. +Bila memungkinkan, Go _compiler_ akan mengalokasikan variabel lokal dari fungsi +dalam _stack frame_ dari fungsi tersebut. +Namun, jika _compiler_ tidak dapat membuktikan bahwa variabel tersebut tidak +diacu setelah fungsi selesai, maka _compiler_ akan mengalokasikan variabel +dalam _heap_ (_garbage collected_) untuk menghindari adanya kesalahan pointer. +Jika variabel lokal sangat besar, maka akan lebih masuk akal bila disimpan +dalam _heap_ bukan dalam _stack_. + +Pada Go _compiler_ saat ini, jika sebuah variabel diambil alamatnya, variabel +tersebut merupakan kandidat untuk alokasi dalam _heap_. +Namun, analisis pelepasan (_analytic escape_) dasar mengenali beberapa kasus +saat variabel seperti +itu tidak akan hidup sampai fungsi selesai sehingga dapat disimpan dalam +_stack_. + +//}}} + +[#Why_does_my_Go_process_use_so_much_virtual_memory] +=== Kenapa proses Go menggunakan _virtual memory_ yang besar? +//{{{ + +Pengalokasi _memory_ pada Go memesan sejumlah besar wilayah _virtual memory_ +sebagai arena alokasi. +_Virtual memory_ ini adalah lokal terhadap proses Go tertentu; +pemesanan ini tidak menghilangkan _memory_ pada proses yang lain. + +Untuk mengetahui alokasi _memory_ sebenarnya dari sebuah proses Go, gunakan +perintah `top` pada Unix dan perhatikan kolom `RES` (Linux) atau `RSIZE` +(macOS). + +//}}} + + +[#Concurrency] +== Konkurensi + +[#What_operations_are_atomic_What_about_mutexes] +=== Operasi apa saja yang _atomic_? Bagaimana dengan _mutex_? +//{{{ + +Penjelasan dari operasi _atomic_ dalam Go dapat ditemukan dalam dokumen +https://golang.org/ref/mem[Model _memory_ Go (Inggris)]. + +Sinkronisasi tingkat-rendah dan primitif _atomic_ tersedia dalam paket +https://golang.org/pkg/sync[sync] +dan +https://golang.org/pkg/sync/atomic[sync/atomic]. +Paket-paket tersebut cukup bagus untuk pekerjaan sederhana seperti +penghitungan referensi (_reference counts_) atau menjamin mutual eksklusi +(_mutual exclusion_) dalam skala kecil. + +Untuk operasi tingkat-tinggi, seperti koordinasi antara server, Go +mendukungnya dengan pendekatan lewat goroutine dan channel. +Misalnya, kita dapat menyusun program supaya hanya satu goroutine yang +bertanggung jawab untuk suatu data tertentu. +Pendekatan ini diringkas dalam +https://www.youtube.com/watch?v=PAAkCSZUG1c[Pepatah Go (Video - Inggris)]. + +____ +"Jangan berkomunikasi dengan berbagi _memory_. Namun, bagilah _memory_ dengan +berkomunikasi" +____ + +Lihat contoh kode +https://golang.org/doc/codewalk/sharemem/[Berbagi Memory dengan Berkomunikasi] +dan +https://blog.golang.org/2010/07/share-memory-by-communicating.html[artikel +terkait] +untuk diskusi lebih rinci mengenai konsep ini. + +Program besar yang konkuren biasanya menggunakan kedua metode ini. + +//}}} + +[#parallel_slow] +=== Kenapa program tidak lebih cepat dengan CPU yang banyak? +//{{{ + +Apakah sebuah program berjalan lebih cepat dengan banyaknya CPU bergantung +pada permasalahan yang ditanganinya. +Bahasa Go menyediakan konkurensi primitif, seperti goroutine dan channel, +namun konkurensi hanya mengaktifkan paralelisme saat permasalahan yang +ditangani secara intrinsik benar paralel. +Permasalahan yang secara intrinsik sekuensial tidak akan bisa dipercepat +dengan menambahkan CPU, sementara kode yang dipecah menjadi lebih kecil +dan dapat dieksekusi secara paralel bisa jadi mempercepat program. + +Terkadang menambah CPU malah memperlambat program. +Dalam praktiknya, program yang menghabiskan waktu lebih banyak untuk +sinkronisasi dan berkomunikasi, daripada melakukan komputasi, bisa mengalami +penurunan performansi saat menggunakan beberapa _thread_ di OS. +Hal ini disebabkan karena pengiriman data antara _thread_ mengikutkan +perpindahan konteks (_context switching_), yang memiliki biaya yang +signifikan, dan biaya tersebut dapat bertambah dengan menambah jumlah CPU. +Misalnya, +https://golang.org/ref/spec#An_example_package[contoh penyaringan bilangan +prima] +dalam spesifikasi Go tidak memiliki performansi paralelisme yang signifikan +walaupun ia menjalankan banyak goroutine; +menambah jumlah _thread_ (CPU) akan lebih memungkinkan memperlambatnya +daripada mempercepatnya. + +Untuk rincian lanjut tentang topik ini lihatlah wicara yang berjudul +https://blog.golang.org/2013/01/concurrency-is-not-parallelism.html[Konkurensi +bukanlah Paralelisme (Inggris)]. + +//}}} + +[#number_cpus] +=== Bagaimana cara mengatur jumlah CPU? +//{{{ + +Jumlah CPU yang tersedia secara simultan yang mengeksekusi goroutine dikontrol +oleh variabel lingkungan `GOMAXPROCS`, yang nilai bakunya adalah jumlah _core_ +CPU yang tersedia. +Program yang berpotensi untuk dieksekusi paralel akan secara bawaan dieksekusi +secara paralel pada mesin dengan multipel CPU. +Untuk mengubah jumlah CPU yang digunakan, atur nilai variabel lingkungan atau +gunakan +https://golang.org/pkg/runtime/#GOMAXPROCS[fungsi] +dengan nama yang sama dari paket runtime untuk mengatur supaya _runtime_ +menggunakan jumlah _thread_ yang berbeda. +Mensetnya dengan `1` berarti mengindahkan kemungkinan paralelisme, memaksa +setiap goroutine untuk dieksekusi secara bergantian. + +_runtime_ bisa mengalokasikan _thread_ lebih banyak daripada nilai +`GOMAXPROCS` untuk melayani beberapa permintaan I/O yang tertunda. +`GOMAXPROCS` hanya mempengaruhi berapa banyak goroutine yang dieksekusi secara +bersamaan; +bisa saja banyak yang diblok saat pemanggilan ke sistem dilakukan. + +Penjadwal goroutine pada Go tidak selalu bagus, walaupun dari waktu ke waktu +mengalami perbaikan dan peningkatan. +Di suatu saat, ia mungkin lebih mengoptimasi penggunaan _thread_ OS. +Untuk saat sekarang, jika ada masalah performansi, menset `GOMAXPROCS` pada +aplikasi mungkin cukup membantu. + +//}}} + +[#no_goroutine_id] +=== Kenapa tidak ada ID untuk goroutine? +//{{{ + +Goroutine tidak memiliki nama; mereka hanyalah pekerja yang anonim. +Mereka juga tidak membuka identifikasi unik, nama, atau struktur data ke +pemrogramnya. +Beberapa orang cukup terkejut dengan hal ini, mengharapkan perintah `go` +mengembalikan sebuah item yang dapat digunakan untuk mengakses dan mengontrol +goroutine. + +Alasan fundamental kenapa goroutine anonim adalah supaya bahasa Go sepenuhnya +tersedia untuk kode pemrograman konkuren. +Sebaliknya, pola penggunaan yang berkembang saat _thread_ dan goroutine +memiliki nama dapat membatasi apa yang pustaka dasar dapat gunakan. + +Berikut ilustrasi dari beberapa permasalahan tersebut. +Saat kita memberi nama sebuah goroutine dan membangun model disekitarnya, ia +menjadi spesial, dan kita tergoda untuk mengasosiasikan semua komputasi +terhadap goroutine tersebut, mengindahkan kemungkinan menggunakan multipel, +atau bisa saja goroutine yang berbeda untuk pemrosesan. +Jika paket `net/http` mengasosiasikan _state_ per permintaan dengan sebuah +goroutine, maka klien tidak akan bisa menggunakan lebih banyak goroutine untuk +melayani permintaan. + +Lebih lanjut, pengalaman kami dengan pustaka-pustaka seperti sistem grafis +yang mengharuskan semua pemrosesan terjadi dalam "main thread" telah +memperlihatkan bagaimana kaku dan terbatasnya pendekatan tersebut saat +dikembangkan pada bahasa yang konkuren. +Adanya _thread_ atau goroutine khusus memaksa pemrogram memutar-balikan +program untuk menghindari _crash_ dan permasalahan lain yang disebabkan karena +tidak sengaja beroperasi pada _thread_ yang salah. + +Untuk kasus-kasus dimana goroutine tertentu benar-benar spesial, bahasa Go +menyediakan fitur seperti channel yang dapat digunakan dengan cara yang +fleksibel. + +//}}} + + +[#Functions_methods] +== Fungsi dan method + +[#different_method_sets] +=== Kenapa T dan *T memiliki kumpulan method yang berbeda? +//{{{ + +Seperti yang ditulis dalam +https://golang.org/ref/spec#Types[spesifikasi Go], +kumpulan method dari tipe `T` terdiri dari semua method yang penerimanya +adalah `T`, sementara tipe dengan pointer `*T` mengikutkan semua method yang +penerimanya adalah `*T` atau `T`. +Ini artinya semua method `*T` mengikutkan `T`, tapi tidak sebaliknya. + +Perbedaan ini muncul karena jika sebuah nilai interface berisi `*T`, +pemanggilan method pada `T` dapat dilakukan dengan mengembalikan referensi +kepada pointer, namun jika nilai interface mengandung nilai `T`, tidak ada +cara yang aman untuk melakukan pemanggilan method lewat pointer. +(Cara tersebut akan menyebabkan method dapat mengubah nilai di dalam +interface, yang mana tidak dibolehkan oleh spesifikasi bahasa.) + +Bahkan apabila _compiler_ dapat mengambil alamat dari sebuah nilai untuk +dikirim ke method, jika method tersebut mengubah nilai maka perubahannya akan +hilang pada sisi pemanggil. +Sebagai contoh, jika method `Write` dari +https://golang.org/pkg/bytes/#Buffer[bytes.Buffer] +menggunakan penerima dengan nilai bukan pointer, kode berikut: + +---- +var buf bytes.Buffer +io.Copy(buf, os.Stdin) +---- + +akan menyalin standar input ke dalam salinan dari `buf`, bukan ke dalam `buf` +itu sendiri. +Hal seperti ini bukanlah yang kita inginkan. + +//}}} + +[#closures_and_goroutines] +=== Apa yang terjadi bila goroutine dijalankan secara _closure_? +//{{{ + +Beberapa kesalahan bisa muncul saat menggunakan _closure_ dengan konkurensi. +Misalnya pada contoh program berikut: + +---- +func main() { + done := make(chan bool) + + values := []string{"a", "b", "c"} + for _, v := range values { + go func() { + fmt.Println(v) + done <- true + }() + } + + // Tunggu sampai semua goroutine selesai sebelum keluar. + for _ = range values { + <-done + } +} +---- + +Seseorang mengharapkan mendapatkan `a`, `b`, `c` sebagai keluaran. +Apa yang tercetak bisa saja `c`, `c`, `c`. +Hal ini disebabkan karena setiap iterasi dari pengulangan menggunakan instansi +variabel `v` yang sama, sehingga setiap _closure_ berbagi variabel yang sama. +Saat _closure_ dijalankan, ia akan mencetak nilai dari `v` saat `fmt.Println` +dieksekusi, namun `v` bisa saja telah diubah sejak goroutine diluncurkan. +Untuk membantu mendeteksi permasalahan seperti ini, gunakan +https://golang.org/cmd/go/#hdr-Run_go_tool_vet_on_packages[go vet]. + +Untuk menempatkan nilai dari `v` ke setiap _closure_ saat dijalankan, kita +harus mengubah pengulangan supaya membuat variabel baru untuk setiap iterasi. +Salah satu caranya yaitu dengan mengirim variabel sebagai argumen dari +_closure_: + +---- + for _, v := range values { + go func(u string) { + fmt.Println(u) + done <- true + }(v) + } +---- + +Pada contoh ini, nilai `v` dikirim sebagai argumen ke fungsi anonim. +Nilai tersebut diakses di dalam fungsi sebagai variabel `u`. + +Cara yang lebih mudah lagi untuk membuat variabel baru yaitu menggunakan +deklarasi, yang mungkin tampak aneh tapi bekerja pada Go: + +---- + for _, v := range values { + v := v // buat variabel 'v' yang baru. + go func() { + fmt.Println(v) + done <- true + }() + } +---- + +Perilaku bahasa Go seperti ini, yang mana tidak mendefinisikan variabel baru +untuk setiap iterasi, kalau dilihat kembali mungkin adalah suatu kesalahan +pada rancangan bahasa. +Ia mungkin akan diatasi pada versi selanjutnya, tapi demi kompatibilitas, hal +ini tidak bisa diubah pada Go versi 1. + +//}}} + + +[#Control_flow] +== Alur kontrol + +[#Does_Go_have_a_ternary_form] +=== Kenapa Go tidak punya operator `?:`? +//{{{ + +Tidak ada operasi ternari (`?:`) dalam Go. +Kita bisa menggunakan kode berikut untuk mendapatkan hal yang sama: + +---- +if expr { + n = trueVal +} else { + n = falseVal +} +---- + +Alasan kenapa `?:` tidak ada dalam Go yaitu karena perancang bahasa terlalu +sering melihat operator tersebut digunakan untuk menulis ekspresi yang +kompleks. +Bentuk `if-else`, walau lebih panjang, tidak dapat disangsikan lagi lebih +jelas. +Sebuah bahasa hanya perlu satu konstruksi alur kontrol kondisi. + +//}}} + + +[#Packages_Testing] +== Paket dan Pengujian + +[#How_do_I_create_a_multifile_package] +=== Bagaimana cara membuat paket dengan banyak berkas? +//{{{ + +Simpan semua berkas kode untuk paket tersebut di dalam sebuah direktori. +Sebuah berkas sumber kode dapat mengacu ke item di berkas yang berbeda; +tidak perlu membuat deklarasi acuan atau berkas _header_ (seperti pada C/C++). + +Selain dapat dipisahkan menjadi beberapa berkas, paket akan di _compile_ dan +di tes seperti dibuat dalam berkas yang tunggal. + +//}}} + +[#How_do_I_write_a_unit_test] +=== Bagaimana membuat unit tes? +//{{{ + +Buat berkas baru yang berakhiran `_test.go` di direktori yang sama dengan +sumber paket. +Di dalam berkas tersebut, `import "testing"` dan tulis fungsi dengan bentuk + +---- +func TestFoo(t *testing.T) { + ... +} +---- + +Jalankan `go test` di direktori tersebut. +Program tersebut akan mencari fungsi yang berawalan `Test`, membuat binari +tes, dan menjalankannya. + +Lihat dokumentasi +link:/doc/code.html[Cara Menulis Kode Go], +paket +https://golang.org/pkg/testing/[testing] +dan perintah +https://golang.org/cmd/go/#hdr-Test_packages[go test] +untuk lebih rinci. + +//}}} + +[#testing_framework] +=== Dimana atau apa saja fungsi pembantu untuk pengujian? +//{{{ + +Paket standar +https://golang.org/pkg/testing/[testing] +pada Go memudahkan menulis unit tes, namun ia tidak memiliki fitur yang pada +kerangka bahasa lain seperti fungsi untuk _assert_. +Seperti yang telah dijelaskan pada +<<assertions,bagian sebelumnya>>, Go tidak memiliki _assert_, dan argumen yang +sama juga berlaku untuk fungsi `assert` pada pengujian. +Penanganan eror yang baik artinya membolehkan tes yang lain berjalan saat +salah satu darinya gagal, sehingga orang yang melakukan _debugging_ terhadap +kegagalan tersebut mendapatkan gambaran secara keseluruhan. +Akan lebih berguna bila unit tes melaporkan bahwa fungsi `isPrime` +memberikan jawaban yang salah untuk 2, 3, 5, dan 7 (atau untuk 2, 4, 8, dan +16) daripada melaporkan bahwa `isPrime` mengembalikan jawaban yang salah untuk +2 sehingga tidak ada pengujian yang berjalan lagi. +Pemrogram yang menjalankan tes dan gagal bisa saja tidak paham dengan kode +yang melaporkan kesalahan. +Waktu yang dihabiskan untuk menulis sebuah pesan eror yang baik nanti akan +dibayar saat mendapatkan pengujian gagal. + +Alasan lainnya yaitu kerangka pengujian condong berkembang menjadi sebuah +bahasa-kecil sendiri, dengan mekanisme kontrol, kondisi, dan pencetakan +tersendiri, namun Go sudah memiliki semua kemampuan tersebut; +kenapa dibuat lagi? +Kita lebih baik menulis unit tes dengan Go; +lebih sedikit bahasa yang dipelajari dan pendekatan ini menjaga pengujian +tetap mudah digunakan dan dipahami. + +Jika jumlah kode yang dibutuhkan untuk menulis eror yang baik tampak repetitif +dan terlalu besar, pengujian mungkin lebih baik ditulis dalam bentuk _tabel_, +mengiterasi sebuah daftar masukan dan keluaran yang didefinisikan dalam sebuah +struktur data (Go mendukung struktur data anonim). +Penulisan tes dan pesan eror yang baik nantinya akan diamortisasi oleh +banyaknya kasus-kasus pengujian. +Pustaka standar Go mengandung banyak contoh unit tes, seperti +https://golang.org/src/fmt/fmt_test.go[pengujian pemformatan pada paket +`fmt`]. + +///}}} + +[#x_in_std] +=== Kenapa _X_ tidak ada dalam pustaka standar? +//{{{ + +Tujuan dari pustaka standar yaitu untuk mendukung _runtime_, menghubungkan +sistem operasi, dan menyediakan fungsionalitas utama yang dibutuhkan oleh +banyak program Go, seperti pemformatan I/O dan jaringan. +Ia juga mengandung elemen-elemen penting untuk pemrograman web, termasuk +kriptografi dan dukungan untuk standar seperti HTTP, JSON, dan XML. + +Tidak ada kriteria yang jelas yang menentukan apa saja yang diikutkan dalam +pustaka standar karena selama ini, _hanya_ inilah pustaka Go. +Namun ada kriteria yang mendefinisikan apa yang dapat ditambahkan untuk saat +sekarang. + +Penambahkan pada pustaka standar biasanya sangat jarang dan syarat supaya +dapat ditambah biasanya cukup tinggi. +Kode yang dimasukan ke dalam pustaka standar membutuhkan biaya pemeliharaan +(bahkan ditanggung oleh selain penulis awalnya), subjek terhadap +https://golang.org/doc/go1compat.html[perjanjian kompatibilitas Go 1] +(menahan perbaikan dari kesalahan dalam API), dan juga subjek terhadap +https://golang.org/s/releasesched[jadwal rilis] Go, +yang mencegah perbaikan _bug_ tersedia secara langsung terhadap pengguna +dengan cepat. + +Umumnya kode yang baru sebaiknya ada di luar pustaka standar dan dapat diakses +lewat https://golang.org/cmd/go/[perkakas go] dengan perintah `go get`. +Kode tersebut memiliki pemelihara, siklus rilis, dan jaminan kompatibilitasnya +sendiri. +Pengguna Go dapat mencari paket dan membaca dokumentasinya di +https://godoc.org/[godoc.org]. + +Walaupun sebenarnya ada beberapa bagian dalam pustaka standar yang seharusnya +tidak diikutkan, seperti `log/syslog`, kami terus memelihara semua yang ada +dalam pustaka standar karena perjanjian kompatibilitas Go. +Namun kami menyarankan untuk kode yang baru supaya dibuat ditempat yang lain. + +//}}} + + +[#Implementation] +== Implementasi + +[#What_compiler_technology_is_used_to_build_the_compilers] +=== Teknologi _compiler_ apa saja yang digunakan untuk membangun _compiler_ Go? +//{{{ + +Ada beberapa _compiler_ untuk Go yang siap digunakan, dan ada juga yang dalam +tahap pengembangan untuk _platform_ yang beragam. + +_Compiler_ bawaan, `gc`, disertakan dalam distribusi Go untuk mendukung +perintah `go`. +`Gc` awalnya ditulis dalam bahasa C karena kesulitan dalam melakukan +_bootstrapping_--proses yang mana sebuah _compiler_ Go diperlukan untuk +menyiapkan lingkungan Go (_compiler_ yang menghasilkan _compiler_). +Namun beberapa hal telah berkembang dan sejak rilis Go 1.5, _compiler_ +tersebut sudah dalam bentuk program Go. +_Compiler_ tersebut dikonversi dari C ke Go menggunakan perangkat translasi +otomatis, seperti yang dijelaskan dalam +https://golang.org/s/go13compiler[dokumen rancangan] +dan +https://talks.golang.org/2015/gogo.slide#1[wicara] berikut. +Sekarang _compiler_ bersifat "self-hosting", yang artinya dibutuhkan untuk +mengatasi permasalahan _bootstrapping_. +Solusinya yaitu dengan memiliki lingkungan Go yang telah terpasang, seperti +halnya seperti pada lingkungan C yang siap digunakan. +Sejarah dan dokumentasi untuk cara membangun lingkungan Go yang baru dari +sumber dijelaskan di +https://golang.org/s/go15bootstrap[sini] +dan di +https://golang.org/doc/install/source[sini]. + +`Gc` ditulis dalam Go menggunakan _recursive descent parser_ dan menggunakan +kostum _loader_, yang juga ditulis dengan Go berdasarkan loader pada Plan 9, +untuk menghasilkan binari dalam format ELF/Mach-O/PE. + +Pada awal proyek kami mempertimbangkan menggunakan LLVM untuk `gc` namun +tidak jadi karena terlalu besar dan lambat untuk sesuai dengan tujuan dari +performansi yang ingin kami capai. +Alasan utama lainnya, dengan LLVM akan membuat lebih sukar untuk melakukan +perubahan pada tingkat ABI (_Application Binary Interface_) dan sekitarnya, +seperti manajemen _stack_, yang dibutuhkan oleh Go namun bukan bagian dari +standar C. +https://go.googlesource.com/gollvm/[Implementasi LLVM] yang baru mulai +merintis hal tersebut sekarang. + +_Compiler_ `gccgo` adalah antar muka yang ditulis dalam bahasa C++ dengan +_recursive descent parser_ digabung dengan GCC sebagai _back end_ nya. + +Go ternyata menjadi bahasa yang bagus untuk mengimplementasikan _compiler_ Go, +walaupun itu bukan tujuan awalnya. +Dengan tidak menggunakan _self-hosting_ sejak awal, membolehkan perancangan Go +fokus pada tujuan penggunaan awalnya, yaitu sebagai server dalam jaringan. +Bila kami memutuskan Go supaya dapat meng- _compile_ dirinya sendiri sedari +awal, kami mungkin berakhir dengan bahasa yang berfokus pada konstruksi +_compiler_, yang mana merupakan tujuan yang berguna namun bukan yang dari awal +kita harapkan. + +Walaupun `gc` belum menggunakannya, _parser_ dan _lexer_ untuk Go tersedia +dalam paket +https://golang.org/pkg/go/[go] +dan juga ada paket untuk +https://golang.org/pkg/go/types[pemeriksaan tipe]. + +//}}} + +[#How_is_the_run_time_support_implemented] +=== Bagaimana dukungan _runtime_ diimplementasikan? +//{{{ + +Sekali lagi karena permasalahan _bootstrapping_, kode _runtime_ awalnya +ditulis dalam C (dengan sedikit _assembler_) namun telah diterjemahkan ke Go +(kecuali bagian _assembler_). +Dukungan _runtime_ `gccgo` menggunakan `glibc`. +_Compiler_ `gccgo` mengimplementasikan goroutine menggunakan teknik yang +dikenal dengan _stack_ tersegmentasi, yang didukung oleh modifikasi terbaru +dari _gold linker_. +Hal yang sama, `Gollvm` dibangun berdasarkan infrastruktur LLVM. + +//}}} + +[#Why_is_my_trivial_program_such_a_large_binary] +=== Kenapa program sederhana saya ukurannya sangat besar? +//{{{ + +_Linker_ pada `gc` membuat binari yang secara statis terkait +(_statically linked_) secara bawaan. +Semua program Go oleh karena itu mengikutkan _runtime_ Go, bersamaan dengan +informasi tipe _runtime_ yang dibutuhkan untuk mendukung pemeriksaan tipe, +refleksi, dan pelacakan _stack_ saat panic. + +Sebuah program "hello, world" dengan C yang secara statis terkait menggunakan +gcc pada Linux ukurannya sekitar 750 kB, mengikutkan implementasi `printf`. +Sebuah program Go yang sama menggunakan `fmt.Printf` ukurannya sekitar +beberapa _megabyte_, namun berisi dukungan _runtime_ dan tipe yang lebih kuat +dan informasi _debugging_. + +Program Go yang di- _compile_ dengan `gc` dapat dikaitkan dengan `-ldflags=-w` +untuk menonaktifkan pembangkit DWARF, sehingga menghapus informasi _debugging_ +pada binari tanpa ada fungsi yang hilang. +Cara ini bisa mengurangi ukuran binari yang cukup besar. + +//}}} + +[#unused_variables_and_imports] +=== Apakah bisa menghentikan eror dari variabel/import yang tidak digunakan? +//{{{ + +Adanya variabel yang tidak terpakai menandakan sebuah _bug_, sementara import +yang tak terpakai memperlambat kompilasi, efeknya bisa besar saat kode program +bertambah sepanjang waktu. +Karena itu, Go menolak meng- _compile_ program yang memiliki import atau +variabel yang tak terpakai, mengganti kenyamanan sementara demi kecepatan dan +kejelasan program untuk waktu yang panjang. + +Tetap saja, saat menulis kode, sangat umum situasi seperti ini terjadi dan +terkadang mengganggu karena harus disunting dahulu sebelum program dapat di- +_compile_. + +Beberapa orang meminta supaya menyediakan opsi untuk mematikan pemeriksaan +tersebut atau setidaknya menjadi peringatan (_warning_). +Opsi tersebut belum ditambahkan, karena opsi _compiler_ seharusnya tidak +mempengaruhi semantik dari bahasa dan karena _compiler_ Go tidak melaporkan +peringatan, hanya eror yang mencegah kompilasi. + +Ada dua alasan kenapa tidak adanya peringatan, tapi hanya ada eror. +Pertama, jika layak untuk dikeluhkan, maka ia patut diperbaiki di dalam kode. +(Dan jika tidak patut diperbaiki, maka tidak layak dikeluhkan.) +Kedua, membuat _compiler_ yang mencetak peringatan mendorong implementasi yang +melaporan kasus-kasus lemah yang membuat kompilasi menjadi berisik, menutup +adanya eror yang sebenarnya yang seharusnya diperbaiki. + +Cukup mudah untuk mengatasi masalah ini sebenarnya. +Cukup gunakan pengidentifikasi kosong untuk membiarkan variabel atau import +yang tak terpakai tetap ada saat anda membangun program. + +---- +import "unused" + +// Deklarasi ini menandai import sedang digunakan dengan mengacu item dari +// paket tersebut. +var _ = unused.Item // TODO: Hapus sebelum di- commit! + +func main() { + debugData := debug.Profile() + _ = debugData // Digunakan hanya saat debugging. + ... +} +---- + +Sekarang, kebanyakan pemrogram Go menggunakan perkakas +https://godoc.org/golang.org/x/tools/cmd/goimports[goimports], +yang secara otomatis menulis ulang sumber kode supaya memiliki import yang +benar, menghapus permasalahan import yang tidak terpakai. +Program ini dengan mudah dapat disambungkan ke _editor_ supaya dijalankan +secara otomatis saat sumber berkas Go disimpan. + +//}}} + +[#virus] +=== Kenapa anti-virus menganggap binari Go terinfeksi? +//{{{ + +Hal ini sering terjadi, khususnya pada mesin Windows, dan biasanya itu adalah +peringatan yang salah. +Program anti-virus komersial terkadang bingung dengan struktur binari Go, yang +jarang mereka lihat dari binari yang di- _compile_ pada bahasa lain. + +Jika anda baru saja memasang distribusi Go dan sistem melaporkan bahwa ia +terinfeksi, itu adalah kesalahan. +Untuk lebih teliti, kita bisa memverifikasi berkas yang diunduh dengan +membandingkan _checksum_ yang ada pada +https://golang.org/dl/[halaman unduhan]. + +Jika anda percaya bahwa laporan tersebut salah, silahkan laporkan sebagai +_bug_ ke pembuat anti-virus. +Mungkin suatu saat nanti anti-virus akan belajar untuk memahami program Go. + +//}}} + + +[#Performance] +== Performansi + +[#Why_does_Go_perform_badly_on_benchmark_x] +=== Kenapa benchmark X berjalan buruk dengan Go? +//{{{ + +Salah satu tujuan dari rancangan Go yaitu mendekati performansi C dari program +yang sama, namun beberapa _benchmark_ Go berjalan cukup buruk, termasuk +beberapa _benchmark_ dalam +https://go.googlesource.com/exp/+/master/shootout/[golang.org/x/exp/shootout]. +Benchmark yang paling lambat bergantung kepada pustaka yang mana versi +performansi yang lebih baik tidak tersedia pada Go. +Misalnya, +https://go.googlesource.com/exp/+/master/shootout/pidigits.go[pidigits.go] +bergantung pada paket multi-presisi `math`, dan versi C -nya menggunakan +https://gmplib.org/[GMP] +(yang ditulis dengan _assembler_ dan dioptimisasi). +_Benchmark_ yang bergantung pada ekspresi regular (misalnya, +https://go.googlesource.com/exp/+/master/shootout/regex-dna.go[regex-dna.go] +) +membandingkan +https://golang.org/pkg/regexp[paket regex] +natif dari Go dengan pustaka regex yang lebih matang dan sangat dioptimasi +seperti PCRE. + +_Benchmark game_ dimenangkan oleh penyetelan lebih lanjut (dari kode yang di +_benchmark_) dan versi Go dari kebanyakan _benchmark_ membutuhkan perhatian +tambahan. +Jika anda membandingkan program C dan Go (misalnya +https://go.googlesource.com/exp/+/master/shootout/reverse-complement.go[reverse-complement.go]), +kita akan melihat kedua bahasa saling berdekatan performansinya daripada yang +diindikasikan oleh _benchmark game_. + +Tentu saja, masih ada ruang untuk peningkatan. +_Compiler_ yang ada sekarang cukup bagus namun bisa lebih baik lagi, banyak +pustaka membutuhkan peningkatan performansi, dan _garbage collector_ belum +cukup cepat. + +Pada kasus lainnya, Go seringkali sangat kompetitif. +Telah ada beberapa peningkatan pada banyak program selama bahasa dan perkakas +dikembangkan. +Lihat blog tentang +https://blog.golang.org/2011/06/profiling-go-programs.html[profiling program +Go] +untuk contoh yang informatif. + +//}}} + + +[#change_from_c] +== Perbedaan dari C + +[#different_syntax] +=== Kenapa sintaks Go sangat berbeda dengan C? +//{{{ + +Selain sintaks deklarasi, perbedaannya tidak terlalu banyak dan berangkat dari +dua keinginan. +Pertama, sintaks seharusnya ringan, tanpa terlalu banyak kata kunci, +pengulangan, atau _misteri_. +Kedua, bahasa Go dirancang supaya mudah dianalisis dan dapat diurai tanpa +tabel simbol. +Hal ini membuatnya mudah untuk membuat perkakas seperti _debugger_, +penganalisis dependensi, pengekstrak dokumentasi otomatis, _plugin_ untuk IDE, +dan lainnya. +C dan turunannya terkenal sangat sukar dalam hal ini. + +//}}} + +[#declarations_backwards] +=== Kenapa deklarasinya terbalik? +//{{{ + +Ia tampak terbalik bila kita terlalu terbiasa dengan C. +Dalam C, notasinya adalah sebuah variabel dideklarasikan dengan ekspresi yang +mengacu tipenya, yang mana merupakan ide yang bagus, tapi tata-bahasa dari +tipe dan ekspresi tidak tergabung dengan baik dan hasilnya terkadang +membingungkan; +yang dapat kita lihat pada pointer ke fungsi. +Go pada umumnya memisahkan ekspresi dan sintaks dari tipe dan hal ini +menyederhanakan beberapa hal (menggunakan prefiks `*` untuk pointer adalah +pengecualian yang membuktikan aturan ini). +Dalam C, deklarasi + +---- + int* a, b; +---- + +mendeklarasikan `a` sebagai pointer tapi tidak `b`; +dalam Go + +---- + var a, b *int +---- + +mendeklarasikan keduanya sebagai pointer. +Hal ini lebih jelas dan lebih umum. +Juga, bentuk deklarasi singkat `:=` menyatakan bahwa deklarasi variabel +secara keseluruhan harusnya sama seperti dengan adanya `:=` sehingga + +---- + var a uint64 = 1 +---- + +memiliki efek yang sama dengan + +---- + a := uint64(1) +---- + +Penguraian juga disederhanakan dengan memiliki tata-bahasa yang jelas pada +tipe-tipe bukan saja pada tata-bahasa ekspresi; +kata kunci seperti `func` dan `chan` membuat hal-hal tertentu lebih jelas. + +Lihat artikel tentang +https://golang.org/doc/articles/gos_declaration_syntax.html[Sintaks Deklarasi +Go (Inggris)] untuk lebih rinci. + +//}}} + +[#no_pointer_arithmetic] +=== Kenapa tidak ada operasi aritmatika pada pointer? +//{{{ + +Keamanan. +Tanpa adanya operasi aritmatika pada pointer maka memungkinkan membuat sebuah +bahasa yang tidak pernah memperoleh alamat _memory_ yang salah. +Teknologi perangkat keras dan _compiler_ telah berkembang di mana pengulangan +menggunakan indeks array bisa seefisien seperti pengulangan dengan aritmatika +pointer. +Dan juga, tidak adanya aritmatika pointer mempermudah implementasi dari +_garbage collector_. + +//}}} + +[#inc_dec] +=== Kenapa `++` dan `--` merupakan penempatan bukan ekspresi? Dan kenapa hanya posfiks, tidak prefiks? +//{{{ + +Tanpa adanya aritmatika pointer, kenyamanan dari peningkatan menggunakan +operator pre- dan posfiks dihilangkan. +Dengan menghapus mereka dari hirarki ekspresi, sintaks ekspresi menjadi mudah +dan masalah rumit mengenai urutan evaluasi dari `++` dan `--` (misalkan +`f(i++)` dan `p[i] = q[++i]`) menjadi hilang juga. +Penyederhanaan ini signifikan. +Untuk posfiks vs. prefiks, salah satunya akan bekerja dengan baik, tapi versi +yang posfiks lebih tradisional; +adanya prefiks timbul dari STL, pustaka dari sebuah bahasa yang namanya +mengandung, secara ironis, peningkatan posfiks (C++). + +//}}} + +[#semicolons] +=== Kenapa ada tanda kurung kurawal tapi tidak titik-koma? dan kenapa kurawal buka tidak bisa dibaris berikutnya? +//{{{ + +Go menggunakan kurung kurawal untuk pengelompokan perintah, sintaks yang cukup +akrab bagi yang sering bekerja dengan bahasa dari keluarga C. +Titik-koma, sebenarnya untuk _parser_ bukan untuk pemrogram, dan kami ingin +menghilangkannya sebisa mungkin. +Untuk mencapai tujuan ini, Go meminjam trik dari BCPL: titik-koma yang +memisahkan perintah ada dalam tata-bahasa formal namun disisipkan secara +otomatis, tanpa perlu melihat (_lookahead_), oleh _lexer_ +disetiap akhir baris yang bisa mengakhiri sebuah perintah. +Hal ini bekerja cukup baik pada praktiknya tapi memiliki efek yang memaksa +gaya penggunaan kurung kurawal. +Misalnya, kurawal buka dari fungsi tidak bisa muncul pada baris selanjutnya. + +Beberapa orang memperdebatkan bahwa _lexer_ seharusnya melakukan _lookahead_ +supaya kurawal buka bisa ada dibaris selanjutnya. +Kami tidak setuju. +Secara kode Go ditujukan untuk diformat secara otomatis oleh +https://golang.org/cmd/gofmt/[gofmt], +_beberapa_ gaya harus dipilih. +Gaya tersebut mungkin berbeda dengan apa yang anda sering gunakan di C atau +Java, tapi Go bahasa yang berbeda dan gaya `gofmt` sama baiknya dengan yang +lainnya. +Lebih penting lagi, keuntungan dari format (gaya kode) yang tunggal, yang +diatur secara programmatis, untuk semua program Go menjadi lebih penting dari +kekurangan terhadap gaya kode tertentu. + +//}}} + +[#garbage_collection] +=== Kenapa _garbage collection_? Bukannya itu mahal? +//{{{ + +Salah satu sumber pencatatan terbesar dalam program yaitu mengatur waktu-hidup +dari objek yang dialokasi. +Pada bahasa seperti C, waktu-hidup dari objek dilakukan secara manual, yang +bisa menghabiskan waktu pemrogram yang cukup signifikan dan terkadang +menyebabkan _bug_ yang buruk. +Bahkan pada bahasa seperti C++ atau Rust yang menyediakan mekanisme untuk +membantu hal tersebut, mekanisme tersebut bisa memiliki efek yang signifikan +pada rancangan perangkat lunak, terkadang menambah biaya pemrograman +tersendiri. +Kami merasakan perlu untuk menghilangkan biaya pemrograman tersebut, dan +dengan perkembangan teknologi _garbage collection_ pada beberapa tahun +belakangan ini memberi kita kepercayaan bahwa ia dapat diimplementasikan +dengan cukup murah, dengan latensi yang cukup rendah, dan bisa menjadi +pendekatan yang cukup bagus untuk pemrograman pada sistem jaringan. + +Kesulitan yang umum dari pemrograman konkuren berakar dari permasalahan +waktu-hidup dari objek: saat objek dikirim diantara _thread_ maka akan menjadi +rumit untuk menjamin bahwa objek tersebut akan dibebaskan secara aman. +_Garbage collection_ otomatis membuat kode yang konkuren lebih mudah ditulis. +Tentu saja, mengimplementasikan _garbage collection_ dalam lingkungan yang +konkuren adalah sebuah tantangan, namun menerapkannya sekali saja (pada +_runtime_) daripada di setiap program dapat membantu semua orang. + +Terakhir, disamping konkurensi, _garbage collection_ membuat _interface_ lebih +mudah karena mereka tidak membutuhkan bagaimana _memory_ diatur diantara +mereka. + +Ini bukan berarti bahwa pekerjaan dan teknologi bahasa terbaru dalam +bahasa seperti Rust yang membawa ide baru terhadap permasalah pengaturan +sumber daya adalah salah; +kami sangat mendorong pekerjaan tersebut dan ikut merasa bersemangat melihat +bagaimana mereka berkembang. +Namun Go mengambil pendekatan lebih tradisional dengan mengatasi waktu-hidup +objek lewat _garbage collection_, dan cukup dengan _garbage collection_ saja. + +Implementasi _garbage collection_ pada Go sekarang menggunakan metode kolektor +_mark-and-sweep_. +Pada mesin yang memiliki banyak _processor_, maka kolektor berjalan pada +_core_ CPU tersendiri, paralel dengan program utama. +Pekerjaan utama pada pengembangan kolektor pada beberapa tahun terakhir telah +mengurangi waktu _pause_ bahkan sampai ke sub-milidetik, bahkan untuk +_heap_ yang besar. +Pekerjaan masih terus dilanjutkan untuk memperbagus algoritma, mengurangi +biaya dan latensi lebih rendah lagi, dan mengeksplorasi pendekatan baru. +https://blog.golang.org/ismmkeynote[Intisari ISSM] oleh Rick Hudson dari tim +Go menjelaskan progres sejauh ini dan menyarankan beberapa pendekatan di masa +depan. + +Mengenai performansi, ingatlah bahwa Go memberikan pemrogram kontrol yang +cukup terhadap pengaturan dan alokasi _memory_, lebih banyak dari bahasa +dengan _garbage collection_ pada umumnya. +Pemrogram dapat mengurangi biaya _garbage collection_ lebih banyak dengan +menggunakan bahasa dengan baik; +lihat artikel +https://blog.golang.org/2011/06/profiling-go-programs.html[_Profiling_ program +Go_ (Inggris)] +untuk melihat contohnya, termasuk demonstrasi dari perkakas profiling pada Go. + +//}}} |
