TableofContents Introduction 1.1 BerkenalanDenganGolang 1.2 InstalasiGolang 1.3 GOPATHDanWorkspace 1.4 InstalasiEditor 1.5 Command 1.6 ProgramPertama:HelloWorld 1.7 Komentar 1.8 Variabel 1.9 TipeData 1.10 Konstanta 1.11 Operator 1.12 SeleksiKondisi 1.13 Perulangan 1.14 Array 1.15 Slice 1.16 Map 1.17 Fungsi 1.18 FungsiMultipleReturn 1.19 FungsiVariadic 1.20 FungsiClosure 1.21 FungsiSebagaiparameter 1.22 Pointer 1.23 Struct 1.24 Method 1.25 PropertyPublic&Private 1.26 Interface 1.27 InterfaceKosong 1.28 Reflect 1.29 Goroutine 1.30 2 Channel 1.31 BufferedChannel 1.32 Channel-Select 1.33 Channel-Range&Close 1.34 Channel-Timeout 1.35 Defer&Exit 1.36 Error&Panic 1.37 LayoutFormatString 1.38 Time,ParsingTime,&FormatTime 1.39 Timer 1.40 KonversiData 1.41 FungsiString 1.42 Regexp 1.43 Encode-DecodeBase64 1.44 HashSha1 1.45 Arguments&Flag 1.46 Exec 1.47 File 1.48 Web 1.49 URLParsing 1.50 JSON 1.51 WebJSONAPI 1.52 HTTPRequest 1.53 SQL 1.54 MongoDB 1.55 AutomatedTest 1.56 WaitGroup 1.57 Mutex 1.58 3 Introduction DasarPemrogramanGolang Golang(atauGo)adalahbahasapemrogramanbaru,yangmulaidilirikolehparadeveloper karenakelebihan-kelebihanyangdimilikinya.Sudahbanyakperusahaanbesaryang menggunakanbahasainiuntukproduk-produkmerekahinggadilevelproduction. Bukuinimerupakansalahsatudarisekianbanyakreferensiyangbisadigunakanuntuk belajarpemrogramanGolang.Halyangdisampaikandisinibenar-benardasar,dengan pembelajaranmulaidari0.Diharapkandenganadanyabukuinikawan-kawanbisalebih pahamdalammemahamisepertiapasihGolangitu. EbookDasarPemrogramanGolanggratisuntukdisebarluaskansecarabebas,selamatidak melanggaraturanlisensiGNULGPL2.1. Sourcecodecontoh-contohprogrambisadiunduhdiGithub.Dianjurkanuntuktidakcopypastedarisourcecodedalambelajar,usahakanuntukmenulissendirikodeprogram,agar cepatterbiasadenganbahasaGolang. Versi1.2017.01.23 Bukuinibisadi-downloaddalambentukPDF,linkdownloadPDF. BantudeveloperlainuntukmengenaldanbelajarGolang,dengancaratweetbukuiniatau sharekefacebook. BukuinidibuatolehNovalAgungPrayogo.Untukpertanyaan,kritik,dansaran,silakan [email protected]. Jikaberkenan,andabisamembantupenulisdengancaradonasilewatpaypal. 4 Introduction 5 BerkenalanDenganGolang BerkenalanDenganGolang Golang(ataubiasadisebutdenganGo)adalahbahasapemrogramanbaruyang dikembangkandiGoogleolehRobertGriesemer,RobPike,danKenThompsonpada tahun2007danmulaidiperkenalkandipubliktahun2009. PenciptaanbahasaGolangdidasaribahasaCdanC++,olehkarenaitugayasintaks-nya mirip. KelebihanGolang Golangmemilikikelebihandibandingbahasalainnya,beberapadiantaranya: Mendukungkonkurensidilevelbahasadenganpengaplikasiancukupmudah Mendukungpemrosesandatadenganbanyakprosesordalamwaktuyangbersamaan (pararelprocessing) Memilikigarbagecollector Proseskompilasisangatcepat Bukanbahasapemrogramanyanghirarkial,menjadikandevelopertidakperluribet memikirkansegmenOOP-nya Package/modulyangdisediakanterbilanglengkap.Karenabahasainiopensource, banyaksekalideveloperyangjugamengembangkanmodul-modullainyangbisa dimanfaatkan Meskipunbahasainimasihberumursekitar5tahunan,sudahbanyakindustridan perusahaanygmenggunakanGolangsampailevelproduction,termasukdiantaranyaadalah Googlesendiri. DibukuinikitaakanbelajartentangdasarpemrogramanGolangmulaidari0. 6 InstalasiGolang InstalasiGolang HalpertamayangperludilakukansebelumbisamenggunakanGolangadalah menginstalnyaterlebihdahulu.Carainstalasinyaberbeda-bedauntuktiapjenissistem operasi.PanduaninstalasiGolangsebenarnyasudahdisediakan,bisadilihatdisitusofficialnyahttp://golang.org/doc/install#install. BabinimerupakanringkasandaripanduaninstalasiyangdisediakanolehGolang. DibukuiniversiGolangyangdigunakanadalah1.7.Direkomendasikanmenggunakan versitersebut,atauversilainminimal1.4.2keatas. Digolang,perbedaansignifikanantaraversi1.4.2,1.5,1.6,1.7kebanyakanadalah dibagianperforma,hanyasedikitupdatedibagiansintaksbahasa. InstalasiGolangdiWindows 1. Downloadterlebihdahuluinstaller-nya.Pilihsesuaijenisbitprosesoryangdigunakan. 32bit=>go1.7.wind*ws-386.msi 64bit=>go1.7.wind*ws-amd64.msi 1. Setelahter-download,jalankaninstaller,kliknextsampaiprosesinstalasiselesai. Default-nyaGolangakanterinstaldi c:\go\bin.Pathtersebutakansecaraotomatis terdaftardipathvariable. 2. BukaCommandPrompt/CMD,eksekusiperintahberikutuntukmengetesapakah Golangsudahterinstaldenganbenar. $goversion 3. JikaoutputcommanddiatasadalahversiGolangyangdi-instal,makainstalasi berhasil. Seringterjadicommand goversiontidakbisadijalankanmeskipunGolangsudah terinstal.SolusinyaadalahdenganrestartCMD(closeCMD,lalubukakembali). Setelahitucobajalankansekalilagicommandtersebut. InstalasiGolangdiMacOSX 7 InstalasiGolang CaratermudahinstalasiGolangdiM*cOSXadalahdenganmenggunakanhomebrew. HomebrewsendiriadalahpackagemanagerkhususuntukM*cOSX(miripseperti aptgetmilikUbuntu). DibawahinimerupakanlangkahinstalasiGolangmenggunakanhomebrew. 1. Installterlebihdahuluhomebrew(jikabelumada),dengancaramengeksekusiperintah berikutditerminal. $ruby-e"$(curl-fsSLhttp://git.io/pVOl)" 2. InstallGolangmenggunakancommand brew. $brewinstallgo 3. Selanjutnya,eksekusiperintahdibawahiniuntukmengetesapakahgolangsudah terinstaldenganbenar. $goversion 4. JikaoutputcommanddiatasadalahversiGolangyangdi-instal,makainstalasi berhasil. InstalasiGolangdiUbuntu CaramenginstalGolangdiUb*ntubisadenganmemanfaatkan apt-get.Silakanikuti petunjukdibawahini. 1. Jalankancommandberikutditerminal. $sudoadd-apt-repositoryppa:gophers/go $sudoapt-getupdate $sudoapt-getinstallGolang-stable 2. Setelahinstalasiselesai,eksekusiperintahdibawahiniuntukmengetesapakah Golangsudahterinstaldenganbenar. $goversion 3. JikaoutputcommanddiatasadalahversiGolangyangdi-instal,makainstalasi berhasil. 8 InstalasiGolang InstalasiGolangdiDistroLinuxLain 1. Downloadarchiveberikut,pilihsesuaijenisbitkomputeranda. 32bit=>go1.7.lin*x-386.tar.gz 64bit=>go1.7.lin*x-amd64.tar.gz 1. Bukaterminal,ekstrakarchivetersebutke /usr/local.Setelahituexportpath-nya. Gunakancommanddibawahiniuntukmelakukanhaltersebut. $tarzxvfgo1.7.lin*x-....tar.gz-C/usr/local $exportPATH=$PATH:/usr/local/go/bin 2. Selanjutnya,eksekusiperintahberikutuntukmengetesapakahGolangsudahterinstal denganbenar. $goversion 3. JikaoutputcommanddiatasadalahversiGolangyangdi-instal,makainstalasi berhasil. 9 GOPATHDanWorkspace GOPATHDanWorkspace SetelahGolangberhasildi-instal,adahalyangperludisiapkansebelumbisamasukkesesi pembuatanaplikasi,yaitusetupworkspaceuntukproyek-proyekyangakandibuat.Dandi babinikitaakanbelajarbagaimanacaranya. Variabel GOPATH GOPATHadalahvariabelyangdigunakanolehGolangsebagairujukanlokasidimana semuafolderproyekdisimpan.Gopathberisikian3buahsubfolder: src, bin,dan pkg. ProyekdiGolangharusditempatkanpadapath $GOPATH/src.Sebagaicontohkitaingin membuatproyekdengannama belajar,makaharusdibuatkansebuahfolderdengan nama belajarditempatkandalam src( $GOPATH/src/belajar).Nantinyasemuafileuntuk keperluanproyekyangbersangkutanditempatkandisana. Pathseparatoryangdigunakansebagaicontohdibukuiniadalahslash /.Khusus penggunaWind*ws,pathseparatoradalahbackslah \. SetupWorkspace Lokasiataualamatfolderyangakandijadikansebagaiworkspacebisaditentukansendiri. Andabisamenggunakanalamatfoldermanasaja,bebas.Lokasitersebutperludisimpan kedalampathvariabledengannama GOPATH.Sebagaicontoh,sayamemilihpath $HOME/Documents/go,makasayadaftarkanalamattersebut.Caranya: BagipenggunaWind*ws,tambahkanpathfoldertersebutkepathvariabledengan nama GOPATH.Setelahvariabeldidaftarkan,cekapakahpathsudahterdaftardengan benar. Seringterjadi GOPATHtidakdikenalimeskipunvariabelsudahdidaftarkan.Jikahal sepertiiniterjadi,restartcommandpromptanda,lalucobalagi. Bagipenggunanon-Wind*ws,gunakankeyword exportuntukmendaftarkan GOPATH. $exportGOPATH=$HOME/Documents/go Setelahvariabeldidaftarkan,cekapakahpathsudahterdaftardenganbenar. 10 GOPATHDanWorkspace Setelah GOPATHberhasildikenali,perludisiapkan3buahsubfolderdidalamnyadengan kriteriasebagaiberikut: Folder src,adalahpathdimanaproyekgolangdisimpan Folder pkg,berisifilehasilkompilasi Folder bin,berisifileexecutablehasilbuild StrukturdiatasmerupakanstrukturstandarworkspaceGolang.Jadipastikanpenamaandan hirarkifolderadalahsama. 11 InstalasiEditor InstalasiEditor PembuatanprogrammenggunakanbahasaGolang,akanlebihmaksimaljikadidukung editoratauIDEyangpas.Adacukupbanyakpilihanbagusyangbisadipertimbangkan, diantaranya:Intellij,Netbeans,Atom,Brackets,danlainnya. Padasaatmenulisbukuini,editoryangsayagunakanadalahSublimeText3.Editorini ringan,mudahdidapat,danmemilikicukupbanyakplugin.Andabisamemiliheditoryang samadenganyangdigunakandibukuini,ataueditorlainnya,bebas,yangpentingnyaman ketikadigunakan. BagiyangmemilihSublime,sayasarankanuntukmenginstallpluginbernamaGoSublime. Plugininimenyediakanbanyaksekalifituryangsangatmembantuprosespengembangan aplikasimenggunakanGolang.Diantaranyaseperticodecompletion,lint(deteksikesalahan dilevelsintaks),perapiankodeotomatis,danlainnya. DibabiniakandijelaskanbagaimanacarainstalasieditorSublime,packagecontrol,dan pluginGoSublime. InstalasiEditorSublimeText 1. DownloadSublimeTextversi3dihttp://www.sublimetext.com/3,pilihsesuaidengan sistemoperasiyangdigunakan. 2. Setelahter-download,bukafiletersebutuntukmemulaiinstalasi. 3. Setelahinstalasiselesai,jalankanaplikasi. InstalasiPackageControl Packagecontrolmerupakanaplikasi3rdpartyuntukSublime,digunakanuntuk mempermudahinstalasiplugin.Default-nyaSublimetidakmenyediakanaplikasini,kita perlumenginstalnyasendiri.Silakanikutipetunjukberikutuntukcarainstalasinya. 12 InstalasiEditor 1. Bukasitushttps://packagecontrol.io/installation,copyscriptyangadaditabSublime Text3(tabbagiankiri). 2. Selanjutnya,jalankanaplikasiSublime,klikmenuView>ShowConsole,lalupaste scriptyangsudahdi-copytadi,keinputankecildibagianbawaheditor.Lalutekan Enter. 3. Tungguhinggaprosesinstalasiselesai.Perhatikankaraktersamadengan(=)dibagian kiribawaheditoryangbergerak-gerak.Jikakaraktertersebutmenghilang,menandakan bahwaprosesinstalasisudahselesai. 4. Setelahselesai,tutupaplikasi,lalubukakembali.Packagecontrolsudahberhasildiinstall. InstalasiPluginGoSublime Denganmemanfaatkanpackagecontrol,instalasipluginakanmenjadilebihmudah.Berikut merupakanlangkahinstalasipluginGoSublime. 1. BukaSublime,tekanctrl+shift+p(ataucmd+shift+puntukpengguna*SX),akan munculsebuahinputdialog.Ketikandisana install,lalutekanenter. 13 InstalasiEditor 2. Akanmuncullagiinputdialoglainnya,ketikkan GoSublimelalutekanenter.Tunggu hinggaprosesselesai(acuaninstalasiselesaiadalahkaraktersamadengan(=)di bagiankiribawaheditoryangsebelumnyabergerak-gerak.Ketikakaraktertersebut sudahhilang,menandakanbahwainstalasiselesai). 3. Setelahselesai,restartSublime,pluginGoSublimesudahberhasilter-install. 14 Command Command PengembanganaplikasiGolangtakjauhdarihal-halyangberbaucommandlineinterface. Sepertikompilasi,testing,eksekusiprogram,semuadilakukanlewatcommandline. Golangmenyediakancommand gountukkeperluanpengembanganaplikasi.Dibabini kitaakanbelajarmengenaipemanfaatannya. Command gorun Command gorundigunakanuntukeksekusifileprogram(fileber-ekstensi .go).Cara penggunaannyaadalahdenganmenuliskancommandtersebutdiikutnamafile. Berikutadalahcontohpenerapan gorununtukeksekusifileprogram bab5.goyang tersimpandipath $GOPATH/src/belajar-golang. $cd$GOPATH/src/belajar-golang $gorunbab5.go Command gorunhanyabisadigunakanpadafileyangpackage-nyaadalahmain.Untuk lebihjelasnyaakandibahaspadababselanjutnya(bab6). Jikaadabanyakfileyangber-package maindanfile-filetersebutdi-importdifileutama, makaeksekusinyaadalahdenganmenyisipkansemuafilesebagaiargument gorun(lebih jelasnyaakandibahaspadabab25).Contohnyabisadilihatpadakodeberikut. $gorunbab5.golibrary.go Command gotest Golangmenyediakanpackage testingyangbisadimanfaatkanuntukkeperluanunit testing.Fileyangakandi-testharusber-suffix _test.go. 15 Command Berikutadalahcontohpenggunaancommand gotestuntuktestingfile bab5_test.go. $gotestbab5_test.go Command gobuild Commandinidigunakanuntukmengkompilasifileprogram. Sebenarnyaketikaeksekusiprogrammenggunakan gorun,terjadiproseskompilasijuga, hanyasajafilehasilkompilasiakandisimpanpadafoldertemporaryuntukselanjutnya langsungdieksekusi. Berbedadengan gobuild,commandinimenghasilkanfileexecutablepadafolderyang sedangaktif.Contohnyabisadilihatpadakodeberikut. Padacontohdiatas,file bab5.godi-build,menghasilkanfilebarupadafolderyangsama, yaitu bab5,yangkemudiandieksekusi. PadapenggunaWind*ws,fileexecutableber-ekstensi .exe. Command goinstall Command goinstallmemilikifungsiyangsamadengan gobuild,hanyasajasetelah proseskompilasiselesai,dilanjutkankeprosesinstalasiprogramyangbersangkutan. Targeteksekusiharusberupafolderproyek(bukanfile .go),danpathfoldertersebut dituliskanrelatifterhadap $GOPATH/src.Contoh: $goinstallgithub.com/novalagung/godong goinstallmenghasilkanoutputberbedauntukpackage maindannon-main. Padapackagenon-main,menghasilkanfileberekstensi .atersimpandalamfolder $GOPATH/pkg Padapackagemain,menghasilkanfileexecutabletersimpandalamfolder $GOPATH/bin 16 Command Berikutmerupakancontohpenerapan goinstall. Padakodediatasbisadilihatcommand goinstalldieksekusi2kali. 1. Padapackagenon-main, github.com/novalagung/godong.Hasilinstalasiadalahfile berekstensi .atersimpanpadafolder $GOPATH/pkg 2. Padapackagemain, github.com/novalagung/godong/godong_test.Hasilinstalasiadalah fileexecutabletersimpanpadafolder $GOPATH/bin Command goget Commandiniberbedadengancommand-commandyangsudahdibahasdiatas. goget digunakanuntukmen-downloadpackage.Sebagaicontohsayainginmen-download packagemgo. $gogetgopkg.in/mgo.v2 $ls$GOPATH/src/gopkg.in/mgo.v2 gopkg.in/mgo.v2adalahalamaturlpackagemgo.Packageyangsudahter-downloadakan tersimpanpada $GOPATH/srcdenganstrukturfoldersesuaidenganurlpackage-nya. Sebagaicontoh,packagemgodiatastersimpandi $GOPATH/src/gopkg.in/mgo.v2. 17 Command 18 ProgramPertama:HelloWorld ProgramPertama:HelloWorld Semuapersiapansudahselesai,saatnyamulaimasukpadasesipembuatanprogram. Programpertamayangakandibuatadalahaplikasisederhanauntukmemunculkantulisan HelloWorld. Dibabiniakandijelaskansecarabertahapdariawal.Mulaipembuatanproyek,pembuatan fileprogram,sesipenulisankode(coding),hinggaeksekusiaplikasi. Load GOPATHKeSublimeText Halpertamayangperludilakukan,adalahme-loadataumemunculkanfolder GOPATHdi editorSublime.Denganbegituproyek-proyekGolangakanlebihmudahdi-maintain. Caranya: 1. BukaSublime 2. Bukaexplorer/finder,lalucarikefolderyangmerupakan GOPATH 3. Klik-dragfoldertersebut(kebetulanlokasifolder GOPATHsayabernama go),tarikke Sublime 4. Seluruhsubfolder GOPATHakanterbukadiSublime Namavariabeldisistemoperasinon-Wind*wsdiawalidengantandadollar $,sebagai contoh $GOPATH.SedangkandiWind*ws,namavariabeldiapitkarakterpersen %, contohnyaseperti %GOPATH%. MenyiapkanFolderProyek Selanjutnyakitasiapkansebuahproyekuntukkeperluanpembuatanprogram.Buatdirektori barudalam $GOPATH/srcdengannamafoldersilakanditentukansendiri(boleh menggunakannama belajar-golangataulainnya).Agarlebihpraktis,buatfoldertersebut lewatSublime.Berikutadalahcaranya. 19 ProgramPertama:HelloWorld 1. Klikkanandifolder src 2. KlikNewFolder,dibagianbawahakanmunculinputankecilFolderName 3. Ketikkannamafolder,belajar-golang,laluenter MenyiapkanFileProgram FileprogramdisinimaksudnyaadalahfileyangberisikankodeprogramGolang,fileyang berekstensi .go. Didalamproyekyangtelahdibuat( $GOPATH/src/belajar-golang/),perludisiapkansebuah filedengannamabebas,yangjelasharusber-ekstensi .go(Padacontohinisaya menggunakannamafile bab6-hello-world.go). PembuatanfileprogramjugaakandilakukanlewatSublime.Caranyasilakanikutpetunjuk berikut. 1. Klikkanandifolder belajar-golang 2. KlikNewFile,makaakanmuncultabbarudibagiankanan 3. Ketikkandikonten: bab6-hello-world.go 4. Lalutekanctrl+s(cmd+suntukM*cOSX),kemudianenter 5. Fileakanterbuat 20 ProgramPertama:HelloWorld ProgramPertama:HelloWord Setelahfolderproyekdanfileprogramsudahsiap,saatnyauntukmulaimasukkesesi penulisanprogramataucoding. Dibawahinimerupakancontohkodeprogramsederhanauntukmemunculkantextatau tulisan"helloworld"kelayaroutput(commandline). Silakansalinkodeberikutkefileprogramyangtelahdibuat.Sebisamungkinjangancopy paste.Biasakanuntukmenulisdariawal,agarcepatterbiasadanfamiliardengan pemrogramanGolang. packagemain import"fmt" funcmain(){ fmt.Println("helloworld") } Setelahkodedisalin,bukaterminal(atauCMDbagipenggunaWind*ws),lalumasukke direktoriproyekmenggunakanperintah cd. Wind*ws $cd%GOPATH%\src\belajar-golang Non-Wind*ws $cd$GOPATH/src/belajar-golang 21 ProgramPertama:HelloWorld Setelahitujalankanprogramdenganperintah gorun. $gorunbab6-hello-world.go Akanmuncultulisanhelloworlddilayarconsole. Selamat!AndatelahberhasilmembuatprogrammenggunakanGolang! Meskikodeprogramdiatassangatsederhana,mungkinakanmunculbeberapapertanyaan dibenak.Dibawahinimerupakandetailpenjelasanmengenaikodediatas. PenggunaanKeyword package Setiapfileprogramharusmemilikipackage.Setiapproyekharusadasatufiledengan packagebernama main.Fileyangber-packagemain,akandieksekusipertamakaliketika programdijalankan. Carapenentuanpackageadalahmenggunakankeyword package,berikutadalahcontoh penggunaannya. package<nama-package> packagemain PenggunaanKeyword import Keyword importdigunakanuntukmeng-includepackagelainkedalamfileprogram,agarisi packageyangdi-includebisadimanfaatkan. Package fmtmerupakansalahsatupackageyangdisediakanolehGolang,berisikan banyakfungsiuntukkeperluanI/Oyangberhubungandengantext. 22 ProgramPertama:HelloWorld Berikutadalahskemapenulisankeyword importbesertacontohnya. import"<nama-package>" import"fmt" PenggunaanFungsi main() Dalamsebuahproyekharusadafileprogramyangberisikansebuahfungsibernama main().Fungsitersebutharusberadadalampackageyangjugabernama main.Fungsi main()adalahyangdipanggilpertamakalipadasaateksekusiprogram. Berikutmerupakancontohpenulisannya. funcmain(){ } PenggunaanFungsi fmt.Println() Fungsi fmt.Println()digunakanuntukmemunculkantextkelayar(padakonteksini, terminalatauCMD).Diprogrampertamayangtelahkitabuat,fungsiinimemunculkan tulisanHelloWorld. Berikutadalahskemapenulisanfungsi fmt.Println()besertacontohnya. fmt.Println("<isi-pesan>") fmt.Println("helloworld") Fungsi fmt.Println()beradapadapackage fmt,makauntukmenggunakannyaperludiimportterlebihdahulupackagetersebut. Fungsiinibisamenampungparameteryangtidakterbatasjumlahnya.Semuadata parameterakandimunculkandenganpemisahtandaspasi.Contohnyabisadilihatdikode berikut. fmt.Println("hello","world!","how","are","you") Outputnya:helloworld!howareyou. 23 ProgramPertama:HelloWorld 24 Komentar Komentar Komentarbiasadimanfaatkanuntukmenyisipkancatatanpadakodeprogram,menulis penjelasanataudeskripsimengenaisuatublokkode,ataubisajugadigunakanuntukmeremarkkode(men-non-aktifkankodeygtidakdigunakan).Komentarakandiabaikanketika kompilasimaupuneksekusiprogram. Ada2jeniskomentardiGolang,inline&multiline.Dibabakandijelaskantentang penerapandanperbedaankeduajeniskomentartersebut. KomentarInline Penulisankomentarjenisinidiawalidengantandadoubleslash( //)laludiikutipesan komentarnya.Komentarinlinehanyaberlakuutuksatubarispesansaja.Jikapesan komentarlebihdarisatubaris,makatanda //harusditulislagidibarisselanjutnya. Berikutinimerupakancontohpenulisankomentarinline. packagemain import"fmt" funcmain(){ //komentarkode //menampilkanpesanhelloworld fmt.Println("helloworld") //fmt.Println("barisinitidakakandieksekusi") } Marikitapraktekankodediatas.Siapkanfileprogrambarudiproyek belajar-golang dengannamabisaapasaja.isidengankodediatas,lalujalankan. Hasilnyahanyatulisanhelloworldsajayangmunculdilayar,karenasemuayangdiawali tandadoubleslash //diabaikanolehcompiler. KomentarMultiline 25 Komentar Komentaryangcukuppanjangakanlebihrapijikaditulismenggunakanteknikkomentar multiline.Ciridarikomentarjenisiniadalahpenulisannyadiawalidengantanda /*dan diakhiri */. /* komentarkode menampilkanpesanhelloworld */ fmt.Println("helloworld") //fmt.Println("barisinitidakakandieksekusi") Sifatkomentarinisamasepertikomentarinline,yaitusama-samadiabaikanolehCompiler. 26 Variabel Variabel Golangmengadopsiduajenispenulisanvariabel,yangdituliskantipedata-nyadanyang tidak.Keduacaratersebutintinyaadalahsama,pembedanyahanyalahcarapenulisannya saja. Padababiniakandikupastuntastentangmacam-macamcaradeklarasivariabel. DeklarasiVariabelDenganTipeData Golangmemilikiaturancukupketatdalamhalpenulisanvariabel.Padasaatdeklarasinya, tipedataygdigunakanharusdituliskanjuga.Istilahlaindarikonsepiniadalahmanifest typing. Berikutadalahcontohcarapembuatanvariabelyangtipedatanyaharusditulis. packagemain import"fmt" funcmain(){ varfirstNamestring="john" varlastNamestring lastName="wick" fmt.Printf("halo%s%s!\n",firstName,lastName) } Keyword vardigunakanuntukdeklarasivariabel.Contohnyabisadilihatpada firstName dan lastName.Nilaivariabel firstNamediisilangsungketikadeklarasi,berbedadibanding lastNameyangnilainyadiisisetelahbariskodedeklarasi.Caratersebutdiperbolehkandi Golang. DeklarasiVariabelMenggunakanKeyword var Padakodediatasbisadilihatbagaimanasebuahvariabeldideklarasikandandisetnilainya. Keyword vardigunakanuntukmembuatvariabelbaru. 27 Variabel Skemapenggunaankeywordvar: var<nama-variabel><tipe-data> var<nama-variabel><tipe-data>=<nilai> Contoh: varlastNamestring varfirstNamestring="john" Nilaivariabelbisadiisilangsungpadasaatdeklarasivariabel. PenggunaanFungsi fmt.Printf() Fungsiinidigunakanuntukmenampilkanoutputdalambentuktertentu.Kegunaannyasama sepertifungsi fmt.Println(),hanyasajastrukturoutputnyadidefinisikandiawal. Perhatikanbagian "halo%s%s!\n",karakter %sdisituakandigantidengandata string yangberadadiparameterke-2,ke-3,danseterusnya. Agarlebihmudahdipahami,silakanperhatikankodeberikut.Ketigabariskodedibawahini menghasilkanoutputyangsama,meskipuncarapenulisannyaberbeda. fmt.Printf("halojohnwick!\n") fmt.Printf("halo%s%s!\n",firstName,lastName) fmt.Println("halo",firstName,lastName+"!") Tandaplus( +)jikaditempatkandiantarastring,fungsinyaadalahuntukpenggabungan string(concatenation). Fungsi fmt.Printf()tidakmenghasilkanbarisbarudiakhirtext,olehkarenaitu digunakanlahliteral \nuntukmemunculkanbarisbarudiakhir.Halinisangatberbedajika dibandingkandenganfungsi fmt.Println()yangsecaraotomatismenghasilkanendline (barisbaru)diakhir. DeklarasiVariabelTanpaTipeData Selainmanifesttyping,Golangjugamengadopsimetodetypeinference,yaitumetode deklarasivariabelyangtipedata-nyaditentukanolehtipedatanilainya,kontradiktifjika dibandingkandengancarapertama.Denganmetodejenisini,keyword vardantipedata tidakperluditulis.Agarlebihjelas,silakanperhatikankodeberikut. 28 Variabel varfirstNamestring="john" lastName:="wick" fmt.Printf("halo%s%s!\n",firstName,lastName) Variabel lastNamedideklarasikandenganmenggunakanmetodetypeinference. Penandanyatipedatatidakdituliskanpadasaatdeklarasi.Padapenggunaanmetodeini, operand =harusdigantidengan :=dankeyword vardihilangkan. Tipedata lastNamesecaraotomatisakanditentukanmenyesuaikanvalueataunilai-nya. Jikanilainyaadalahberupa stringmakatipedatavariabeladalah string.Padacontoh diatas,nilainyaadalahstring "wick". Diperbolehkanuntuktetapmenggunakankeyword varpadasaatdeklarasi,dengan ketentuantidakmenggunakantanda :=,melainkantetapmenggunakan =.Contohnya bisadilihatpadakodeberikut. //menggunakanvar,tanpatipedata,menggunakanperantara"=" varfirstName="john" //tanpavar,tanpatipedata,menggunakanperantara":=" lastName:="wick" Keduadeklarasidiatasmaksudnyaadalahsama.Silakanpilihyangnyamandihati. Tanda :=hanyadigunakansekalidiawalpadasaatdeklarasisaja.Setelahitu,untuk assignmentnilaiselanjutnyaharusmenggunakantanda =.Contoh: lastName:="wick" lastName="ethan" lastName="bourne" DeklarasiMultiVariabel Golangmendukungmetodedeklarasibanyakvariabelsecarabersamaan,caranyadengan menuliskanvariabel-variabel-nyadenganpembatastandakoma( ,).Untukpengisian nilainya-pundiperbolehkansecarabersamaan.Contoh: varfirst,second,thirdstring first,second,third="satu","dua","tiga" 29 Variabel Pengisiannilaijugabisadilakukanbersamaanpadasaatdeklarasi.Caranyadengan menuliskannilaimasing-masingvariabelberurutansesuaivariabelnyadenganpembatas koma( ,).Contohnyasepertipadakodeberikut. varfourth,fifth,sixthstring="empat","lima","enam" Kalauinginlebihringkas: seventh,eight,ninth:="tujuh","delapan","sembilan" Denganmenggunakantekniktypeinference,deklarasimultivariabelbisadilakukanuntuk variabel-variabelyangtipedatasatusamalainnyaberbeda.Contoh: one,isFriday,twoPointTwo,say:=1,true,2.2,"hello" Istimewabukan?Istimewasekali. VariabelUnderscore _ Golangmemilikiaturanunikyangtidakdimilikibahasalain,yaitutidakbolehadasatupun variabelyangmenganggur.Artinya,semuavariabelyangdideklarasikanharusdigunakan. Jikaadavariabelyangtidakdigunakantapidideklarasikan,programakangagaldikompilasi. Underscore( _)adalahpredefinedvariabelyangbisadimanfaatkanuntukmenampung nilaiyangtidakdipakai.Bisadibilangvariabelinimerupakankeranjangsampah.Berikut adalahcontohpenggunaanvariabeltersebut. _="belajarGolang" _="Golangitumudah" name,_:="john","wick" Padacontohdiatas,variabel nameakanberisikantext john,sedangnilai wickakan ditampungolehvariabelunderscore,menandakanbahwanilaitersebuttidakakan digunakan. 30 Variabel Variabelunderscoreadalahpredefined,jaditidakperlumenggunakan :=untukpengisian nilai,cukupdengan =saja.Namunkhususuntukpengisiannilaimultivariabelyang dilakukandenganmetodetypeinference,bolehdidalamnyaterdapatvariabelunderscore. Biasanyaunderscoreseringdimanfaatkanuntukmenampungnilaibalikfungsiyangtidak digunakan. Perludiketahui,bahwaisivariabelunderscoretidakdapatditampilkan.Datayangsudah masukvariabeltersebutakanhilang.Ibaratblackhole,sekalimasuk,tidakakanbisakeluar :-) DeklarasiVariabelMenggunakanKeyword new Keyword newdigunakanuntukmencetakdatapointerdengantipedatatertentu.Nilaidata default-nyaakanmenyesuaikantipedatanya.Contohpenerapannya: name:=new(string) fmt.Println(name)//0x20818a220 fmt.Println(*name)//"" Variabel namemenampungdatabertipepointerstring.Jikaditampilkanyangmuncul bukanlahnilainyamelainkanalamatmemorinilaitersebut(dalambentuknotasi heksadesimal).Untukmenampilkannilaiaslinya,variabeltersebutperludi-dereference terlebihdahulu,menggunakantandaasterisk( *). Mungkinuntuksekarangbanyakyangakanbingung,namuntakapa,karenanantinyadi bab22akandikupashabistentangapaitupointerdandereference. DeklarasiVariabelMenggunakanKeyword make Keywordinihanyabisadigunakanuntukpembuatanbeberapajenisvariabelsaja,yaitu: channel slice map Danlagi,mungkinbanyakyangakanbingung,tapitakapa.Ketikasudahmasukke pembahasanmasing-masingpointersebut,akanterlihatapakegunaandarikeywordini. 31 Variabel 32 TipeData TipeData Golangmengenalbeberapajenistipedata,diantaranyaadalahtipedatanumerik(desimal& non-desimal),string,danboolean. Dibab-babsebelumnyasecarataksadarkitasudahmenerapkanbeberapatipedata, seperti stringdantipenumerik int. Padababini,akandijelaskanbeberapamacamtipedatastandaryangdisediakanoleh Golang,danbagaimancarapenggunaannya. TipeDataNumerikNon-Desimal Tipedatanumeriknon-desimalataunonfloatingpointdiGolangadabeberapamacam. Secaraumumada2tipedatayangperludiketahui,yaitu: uint,merupakantipedatauntukbilangancacah(bilanganpositif),dan int,merupakantipedatauntukbilanganbulat(bilangannegatifdanpositif) Keduatipedatadiataskemudiandibagilagimenjadibeberapa,denganpembagian berdasarkanlebarcakupannilainya,detailnyabisadilihatditabelberikut. Tipedata Cakupanbilangan uint8 0↔255 uint16 0↔65535 uint32 0↔4294967295 uint64 0↔18446744073709551615 uint samadengan uint32atau uint64(tergantungnilai) byte samadengan uint8 int8 -128↔127 int16 -32768↔32767 int32 -2147483648↔2147483647 int64 -9223372036854775808↔9223372036854775807 int samadengan int32atau int64(tergantungnilai) rune samadengan int32 33 TipeData Dianjurkanuntuktidaksembarangandalammenentukantipedatavariabel,sebisamungkin tipeyangdipilihharusdisesuaikandengannilainya,karenaefeknyaadalahkealokasi memorivariabel.Pemilihantipedatayangtepatakanmembuatpemakaianmemorilebih optimal,tidakberlebihan. Contohpenggunaanvariabelnumeriknon-desimalbisadilihatdikodeberikut. varpositiveNumberuint8=89 varnegativeNumber=-1243423644 fmt.Printf("bilanganpositif:%d\n",positiveNumber) fmt.Printf("bilangannegatif:%d\n",negativeNumber) Variabel positiveNumberbertipe uint8dengannilaiawal 89.Sedangkanvariabel negativeNumberdideklarasikandengannilaiawal -1243423644.Compilersecaracerdas akanmenentukantipedatavariabeltersebutsebagai int32(karenaangkatersebutmasuk kecakupantipedata int32). Template %dpada fmt.Printf()digunakanuntukmemformatdatanumeriknon-desimal. TipeDataNumerikDesimal Tipedatanumerikdesimalyangperludiketahuiada2, float32dan float64.Perbedaan keduatipedatatersebutberadadilebarcakupannilaidesimalyangbisaditampung.Untuk lebihjelasnyabisamerujukkespesifikasiIEEE-75432-bitfloating-pointnumbers.Contoh penggunaantipedatainibisadilihatdikodeberikut. vardecimalNumber=2.62 fmt.Printf("bilangandesimal:%f\n",decimalNumber) fmt.Printf("bilangandesimal:%.3f\n",decimalNumber) Padakodediatas,variabel decimalNumberakanmemilikitipedata float32,karena nilainyaberadadicakupantipedatatersebut. Template %fdigunakanuntukmemformatdatanumerikdesimalmenjadistring.Digit desimalyangakandihasilkanadalah6digit.Padacontohdiatas,hasilformatvariabel decimalNumberadalah 2.620000.Jumlahdigityangmunculbisadikontrolmenggunakan 34 TipeData %.nf,tinggalganti ndenganangkayangdiinginkan.Contoh: %.3fmakaakan menghasilkan3digitdesimal, %.10fmakaakanmenghasilkan10digitdesimal. TipeData bool(Boolean) Tipedata boolberisikanhanya2variansinilai, truedan false.Tipedatainibiasa dimanfaatkandalamseleksikondisidanperulangan(yangnantinyaakankitabahaspada bab12danbab13).Contohsederhanapenggunaan bool: varexistbool=true fmt.Printf("exist?%t\n",exist) Gunakan %tuntukmemformatdata boolmenggunakanfungsi fmt.Printf(). TipeData string Cirikhasdaritipedatastringadalahnilainyadiapitolehtandaquoteataupetikdua( "). Contohpenerapannya: varmessagestring="Halo" fmt.Printf("message:%s\n",message) Selainmenggunakantandaquote,deklarasistringjugabisadengantandagrave accent/backticks( `),tandainiterletakdisebelahkiritombol1.Keistimewaanstringyang dideklarasikanmenggunakanbackticsadalahmembuatsemuakarakterdidalamnyatidak akandiescape,termasuk \n,tandapetikduadantandapetiksatu,barisbaru,dan lainnya.Semuaakanterdeteksisebagaistring.Berikutadalahcontohpenerapannya. varmessage=`Namasaya"JohnWick". Salamkenal. Maribelajar"Golang".` fmt.Println(message) Ketikadijalankan,outputakanmunculsamapersisisesuainilaivariabel messagediatas. Tandapetikduaakanmuncul,barisbarujugamuncul,samapersis. 35 TipeData Nilai nilDanNilaiDefaultTipeData nilbukanmerupakantipedata,melainkansebuahnilai.Variabelyangisinilainya nil, berartivariabeltersebutmemilikinilaikosong. Semuatipedatayangsudahdibahasdiatasmemilikinilaidefault.Artinyameskipunvariabel dideklarasikandengantanpanilaiawal,akanadanilaidefault-nya. Nilaidefault stringadalah ""(stringkosong) Nilaidefault booladalah false Nilaidefaulttipenumeriknon-desimaladalah 0 Nilaidefaulttipenumerikdesimaladalah 0.0 niladalahnilaikosong,benar-benarkosong. niltidakbisadigunakanpadatipedata yangsudahdibahasdiatas,karenakesemuanyasudahmemilikinilaidefaultpadasaat deklarasi.Adabeberapatipedatayangbisadi-setnilainyadengan nil,diantaranya: pointer tipedatafungsi slice map channel interfacekosongatau interface{} Nantinyakitaakanseringbertemudengan nilketikasudahmasukpadapembahasan bab-babtersebut. 36 Konstanta Konstanta Konstantaadalahvariabelyangnilainyatidakbisadiubah.Inisialisasinilaihanyadilakukan sekalidiawal,setelahnyadatatidakbisadiubahnilainya. PenggunaanKonstanta Datasepertipi(22/7),kecepatancahaya(299.792.458m/s),adalahcontohdatayangtepat jikadideklarasikansebagaikonstantadaripadavariabel,karenanilainyasudahpastidan tidakberubah. Carapenerapankonstantasamasepertideklarasivariabelbiasa,selebihnyatinggalganti keyword vardengan const.Contohnya: constfirstNamestring="john" fmt.Print("halo",firstName,"!\n") Tekniktypeinferencebisaditerapkanpadakonstanta,caranyayaitucukupdengan menghilangkantipedatapadasaatdeklarasi. constlastName="wick" fmt.Print("nicetomeetyou",lastName,"!\n") PenggunaanFungsi fmt.Print() Fungsiinimemilikiperanyangsamasepertifungsi fmt.Println(),pembedanyafungsi fmt.Print()tidakmenghasilkanbarisbarudiakhiroutputnya. Perbedaanlainnyaadalah,nilaipadaparameter-parameteryangdimasukkankefungsi tersebutdigabungkantanpapemisah.Tidaksepertipadafungsi fmt.Println()yangnilai paremeternyadigabungmenggunakanpenghubungspasi.Agarlebihmudahdipahami, perhatikankodeberikut. 37 Konstanta fmt.Println("johnwick") fmt.Println("john","wick") fmt.Print("johnwick\n") fmt.Print("john","wick\n") fmt.Print("john","","wick\n") Kodediatasmenunjukkanperbedaanantara fmt.Println()dan fmt.Print().Output yangdihasilkanoleh5statementdiatasadalahsama,meskicarayangdigunakanberbeda. Bilamenggunakan fmt.Println()tidakperlumenambahkanspasiditiapkata,karena fungsitersebutakansecaraotomatismenambahkannyadisela-selanilai.Berbedadengan fmt.Print(),perluditambahkanspasidisitu,karenafungsiinitidakmenambahkanspasidi sela-selanilaiparameteryangdigabungkan. 38 Operator Operator Babinimembahasmengenaioperator-operatoryangbisadigunakandiGolang.Secara umumoperatordibagimenjadi3kategori:operatoraritmatika,perbandingan,danlogika. OperatorAritmatika Operatoraritmatikaadalahoperatoryangdigunakanuntukoperasiyangsifatnya perhitungan.Golangmendukungbeberapaoperatoraritmatikastandar,list-nyabisadilihat ditabelberikut. Tanda Penjelasan + penjumlahan - pengurangan * perkalian / pembagian % modulus/sisahasilpembagian Contohpenggunaannya: varvalue=(((2+6)%3)*4-2)/3 OperatorPerbandingan Operatorperbandingandigunakanuntukmenentukankebenaransuatukondisi.Hasilnya berupanilaiboolean, trueatau false. TabelberikutberisikanoperatorperbandinganyangbisadigunakandiGolang. 39 Operator Tanda Penjelasan == apakahnilaikirisamadengannilaikanan != apakahnilaikiritidaksamadengannilaikanan < apakahnilaikirilebihkecildaripadanilaikanan <= apakahnilaikirilebihkecilatausamadengannilaikanan > apakahnilaikirilebihbesardarinilaikanan >= apakahnilaikirilebihbesaratausamadengannilaikanan Contohpenggunaannya: varvalue=(((2+6)%3)*4-2)/3 varisEqual=(value==2) fmt.Printf("nilai%d(%t)\n",value,isEqual) Padakodediatas,terdapatstatementoperasiaritmatikayanghasilnyaditampungoleh variabel value.Selanjurnya,variabeltersebuttersebutdibandingkandenganangka2 untukdicekapakahnilainyasama.Jikaiya,makahasilnyaadalah true,jikatidakmaka false.Nilaihasiloperasiperbandingantersebutkemudiandisimpandalamvariabel isEqual. Untukmemunculkannilai boolmenggunakan fmt.Printf(),bisamemakailayoutformat %t. OperatorLogika Operatorinidigunakanuntukmencaribenartidaknyakombinasidatabertipe bool(yang bisaberupavariabelbertipe bool,atauhasildarioperatorperbandingan). Beberapaoperatorlogikastandaryangbisadigunakan: Tanda Penjelasan && kiridankanan || kiriataukanan ! negasi/nilaikebalikan Contohpenggunaannya: 40 Operator varleft=false varright=true varleftAndRight=left&&right fmt.Printf("left&&right\t(%t)\n",leftAndRight) varleftOrRight=left||right fmt.Printf("left||right\t(%t)\n",leftOrRight) varleftReverse=!left fmt.Printf("!left\t\t(%t)\n",leftReverse) Hasildarioperatorlogikasamadenganhasildarioperatorperbandingan,yaituberupanilai boolean. Berikutadalahpenjelasanstatemenoperatorlogikapadakodediatas. leftAndRightbernilai false,karenahasildari falsedan trueadalah false leftOrRightbernilai true,karenahasildari falseatau trueadalah true leftReversebernilai true,karenanegasi(ataulawandari) falseadalah true Template \tdigunakanuntukmenambahkanindenttabulasi.Biasadimanfaatkanuntuk merapikantampilanoutputpadaconsole. 41 SeleksiKondisi SeleksiKondisi Seleksikondisidigunakanuntukmengontrolalurprogram.Kalaudianalogikan,fungsinya miripsepertirambulalulintasdijalanraya.Kapankendaraandiperbolehkanmelajudan kapanharusberhenti,diaturolehrambutersebut.Samasepertipadaseleksikondisi,kapan sebuahblokkodeakandieksekusijugaakandiatur. Yangdijadikanacuanolehseleksikondisiadalahnilaibertipe bool,bisaberasadari variabel,ataupunhasiloperasiperbandingan.Nilaitersebutakanmenentukanblokkode manayangakandieksekusi. Golangmemiliki2macamkeyworduntukseleksikondisi,yaituifelsedanswitch.Dibabini kitaakanmempelajarinyasatu-persatu. Golangtidakmendukungseleksikondisimenggunakanternary. Statementseperti: vardata=(isExist?"ada":"tidakada")akanmenghasilkan error. SeleksiKondisiMenggunakanKeyword if, elseif,& else Carapenerapanif-elsediGolangsamadenganpadabahasapemrogramanlain.Yang membedakanhanyatandakurungnya(parentheses),diGolangtidakperluditulis.Kode berikutmerupakancontohpenerapanseleksikondisiifelse,denganjumlahkondisi4buah. varpoint=8 ifpoint==10{ fmt.Println("lulusdengannilaisempurna") }elseifpoint>5{ fmt.Println("lulus") }elseifpoint==4{ fmt.Println("hampirlulus") }else{ fmt.Printf("tidaklulus.nilaianda%d\n",point) } Darike-empatkondisidiatas,yangterpenuhiadalah ifpoint>5karenanilaivariabel pointmemanglebihbesardari 5.Makablokkodetepatdibawahkondisitersebutakan dieksekusi(blokkodeditandaikurungkurawalbukadantutup),text "lulus"akanmuncul diconsole. 42 SeleksiKondisi SkemaifelseGolangsamasepertipadapemrogramanumumnya.Yaitudiawalseleksi kondisimenggunakan if,danketikakondisinyatidakterpenuhiakanmenujuke else (jikaada).Ketikaadabanyakkondisi,gunakan elseif. Dibahasapemrogramanlain,ketikaadaseleksikondisiyangisiblok-nyahanya1baris saja,kurungkurawalbolehtidakdituliskan.BerbedadenganaturandiGolang,kurung kurawalharustetapdituliskanmeskiisinyahanya1bloksatement. VariabelTemporaryPada if- else Variabeltemporaryadalahvariabelyanghanyabisadigunakanpadablokseleksikondisi dimanaiaditempatkansaja.Penggunaanvariabelinimembawabeberapamanfaat,antara lain: Scopeataucakupanvariabeljelas,hanyabisadigunakanpadablokseleksikondisiitu saja Kodemenjadilebihrapi Ketikanilaivariabeltersebutdidapatdarisebuahkomputasi,perhitungantidakperlu dilakukandidalamblokmasing-masingkondisi. Berikutmerupakancontohpenerapannya. varpoint=8840.0 ifpercent:=point/100;percent>=100{ fmt.Printf("%.1f%sperfect!\n",percent,"%") }elseifpercent>=70{ fmt.Printf("%.1f%sgood\n",percent,"%") }else{ fmt.Printf("%.1f%snotbad\n",percent,"%") } Variabel percentnilainyadidapatdarihasilperhitungan,danhanyabisadigunakandi deretanblokseleksikondisiitusaja. Deklarasivariabeltemporaryhanyabisadilakukanlewatmetodetypeinferenceyang menggunakantanda :=.Penggunaankeyword vardisitutidakdiperbolehkan karenaakanmenyebabkanerror. 43 SeleksiKondisi SeleksiKondisiMenggunakanKeyword switch Switchmerupakanseleksikondisiyangsifatnyafokuspadasatuvariabel.Contoh sederhananyasepertipenentuanapakahnilaivariabel xadalah: 1, 2, 3,ataulainnya. Agarlebihjelas,silakanmelihatcontohdibawahini. varpoint=6 switchpoint{ case8: fmt.Println("perfect") case7: fmt.Println("awesome") default: fmt.Println("notbad") } Padakodediatas,tidakadakondisiatau caseyangterpenuhikarenanilaivariabel point adalah 6.Ketikahalsepertiiniterjadi,blokkondisi defaultakandipanggil.Bisadibilang bahwa defaultmerupakan elsedalamsebuahswitch. Perludiketahui,switchpadapemrogramanGolangmemilikiperbedaandibandingbahasa lain.DiGolang,ketikasebuahcaseterpenuhi,tidakakandilanjutkankepengecekkancase selanjutnya,meskipuntidakadakeyword breakdisitu.Konsepiniberkebalikandengan switchpadaumumnya,yangketikasebuahcaseterpenuhi,makaakantetapdilanjut mengecekcaseselanjutnyakecualiadakeyword break. Pemanfaatan1 caseUntukBanyakKondisi Sebuah casedapatmenampungbanyakkondisi.Carapenerapannyayaitudengan menuliskannilaipembanding-pembandingvariabelyangdi-switchsetelahkeyword case dipisahtandakoma( ,).Contohbisadilihatpadakodeberikut. 44 SeleksiKondisi varpoint=6 switchpoint{ case8: fmt.Println("perfect") case7,6,5,4: fmt.Println("awesome") default: fmt.Println("notbad") } Kondisi case7,6,5,4:akanterpenuhiketikanilaivariabel pointadalah7atau6atau5 atau4. KurungKurawalPadaKeyword case& default Tandakurungkurawal( {})bisaditerapkanpadakeyword casedan default.Tandaini opsional,bolehdipakaibolehtidak.Bagusjikadipakaipadablokkondisiyangdidalamnya adabanyakstatement,kodeakanterlihatlebihrapidanmudahdi-maintain. Berikutadalahcontohpenggunaannya.Bisadilihatpadakeyword defaultterdapatkurung kurawalyangmengapit2statementdidalamnya. varpoint=6 switchpoint{ case8: fmt.Println("perfect") case7,6,5,4: fmt.Println("awesome") default: { fmt.Println("notbad") fmt.Println("youcanbebetter!") } } SwitchDenganGaya if- else UniknyadiGolang,switchbisadigunakandengangayaalaif-else.Nilaiyangakan dibandingkantidakdituliskansetelahkeyword switch,melainkanakanditulislangsung dalambentukperbandingandalamkeyword case. 45 SeleksiKondisi Padakodedibawahini,kodeprogramswitchdiatasdiubahkedalamgaya if-else. Variabel pointdihilangkandarikeyword switch,lalukondisi-kondisinyadituliskanditiap case. varpoint=6 switch{ casepoint==8: fmt.Println("perfect") case(point<8)&&(point>3): fmt.Println("awesome") default: { fmt.Println("notbad") fmt.Println("youneedtolearnmore") } } PenggunaanKeyword fallthroughDalam switch Sepertiyangkitasudahsinggungdiatas,bahwaswitchpadaGolangmemilikibeberapa perbedaandenganbahasalain.Ketikasebuah caseterpenuhi,pengecekkankondisitidak akanditeruskankecase-casesetelahnya. Keyword fallthroughdigunakanuntukmemaksaprosespengecekkanditeruskanke case selanjutnya.Contohberikutmerupakanpenerapankeywordini. varpoint=6 switch{ casepoint==8: fmt.Println("perfect") case(point<8)&&(point>3): fmt.Println("awesome") fallthrough casepoint<5: fmt.Println("youneedtolearnmore") default: { fmt.Println("notbad") fmt.Println("youneedtolearnmore") } } 46 SeleksiKondisi Setelahpengecekkan case(point<8)&&(point>3)selesai,akandilanjutke pengecekkan casepoint<5,karenaada fallthroughdisitu. SeleksiKondisiBersarang Seleksikondisibersarangadalahseleksikondisi,yangberadadalamseleksikondisi,yang mungkinjugaberadadalamseleksikondisi,danseterusnya.Nestedloopatauseleksi kondisibersarangbisadilakukanpada if- else, switch,ataupunkombinasikeduanya. Contohnya: varpoint=10 ifpoint>7{ switchpoint{ case10: fmt.Println("perfect!") default: fmt.Println("nice!") } }else{ ifpoint==5{ fmt.Println("notbad") }elseifpoint==3{ fmt.Println("keeptrying") }else{ fmt.Println("youcandoit") ifpoint==0{ fmt.Println("tryharder!") } } } 47 Perulangan Perulangan Perulanganmerupakanprosesmengulang-ulangeksekusiblokkodetanpahenti,selama kondisiyangdijadikanacuanterpenuhi.Biasanyadisiapkanvariabeluntukiterasiatau variabelpenandakapanperulanganakandiberhentikan. DiGolangkeywordperulanganhanyaforsaja,tetapimeskidemikian,kemampuannya merupakangabungan for, foreach,dan whileibaratbahasapemrogramanlain. PerulanganMenggunakanKeyword for Adabeberapacarastandarmenggunakan for.Carapertamadenganmemasukkan variabelcounterperulanganbesertakondisinyasetelahkeyword.Agarlebihmudah dipahami,cobaperhatikandanpraktekankodeberikut. fori:=0;i<5;i++{ fmt.Println("Angka",i) } Perulangandiatashanyaakanberjalanketikavariabel ibernilaidibawah 5,dengan ketentuansetiapkaliperulangan,nilaivariabel iakandi-iterasiatauditambahkan1( i++ artinyaditambahsatu,samaseperti i=i+1).Karena ipadaawalnyabernilai0,maka perulanganakanberlangsung5kali,yaituketika ibernilai0,1,2,3,dan4. PenggunaanKeyword forDenganArgumen HanyaKondisi Carake-2adalahdenganmenuliskankondisisetelahkeyword for(hanyakondisi). Deklarasidaniterasivariabelcountertidakperludituliskan.Konsepnyamiripseperti while milikbahasapemrogramanlain. Kodeberikutadalahcontohpenerapannya.Outputyangdihasilkansamasepertipada penerapanformenggunakancarapertama. 48 Perulangan vari=0 fori<5{ fmt.Println("Angka",i) i++ } PenggunaanKeyword forTanpaArgumen Carake-3adalah forditulistanpakondisi.Denganiniakandihasilkanperulangantanpa henti(samadengan fortrue).Pemberhentianperulanganbisadilakukandengan menggunakankeyword break.Contohpenerapannyabisadilihatdikodeberikut. vari=0 for{ fmt.Println("Angka",i) i++ ifi==5{ break } } Dalamperulangantanpahentidiatas,variabel iyangnilaiawalnya 0di-inkrementasi. Ketikanilai isudahmencapai 5,keyword breakdigunakan,danperulanganakan berhenti. PenggunaanKeyword for- range Carake-4adalahperulangandenganmenggunakankombinasikeyword fordan range. Carainibiasadigunakanuntukme-loopingdatabertipearray.Detailnyaakandibahasdalam babselanjutnya(bab14). PenggunaanKeyword break& continue Keyword breakdigunakanuntukmenghentikansecarapaksasebuahperulangan, sedangkan continuedigunakanuntukmemaksamajukeperulanganberikutnya. 49 Perulangan Kodeberikutadalahcontohpenerapan continuedan break.Keduakeywordtersebut dimanfaatkanuntukmenampilkanangkagenapberurutanyanglebihbesardari0dan dibawah8. fori:=1;i<=10;i++{ ifi%2==1{ continue } ifi>8{ break } fmt.Println("Angka",i) } Kodediatas,sayakiraakanlebihmudahdicernajikadijelaskansecaraberurutan.Berikut adalahpenjelasannya. 1. Dilakukanperulanganmulaiangka1hingga10dengan isebagaivariabeliterasi 2. Ketika iadalahganjil(dapatdiketahuidari i%2,jikahasilnya 1,berartiganjil), makaakandipaksalanjutkeperulanganberikutnya 3. Ketika ilebihbesardari8,makaperulanganakanberhenti 4. Nilai mditampilkan PerulanganBersarang Takhanyaseleksikondisiyangbisabersarang,perulanganjugabisa.Cara pengaplikasiannyakuranglebihsama,tinggaltulisperulangandidalamperulangan. Contohnyabisadilihatdikodeberikut. fori:=0;i<5;i++{ forj:=i;j<5;j++{ fmt.Print(j,"") } fmt.Println() } 50 Perulangan Dikodeini,untukpertamakalinyafungsi fmt.Println()dipanggiltanpadisisipkan parameter.Carasepertiinidigunakanuntukmenampilkanbarisbaru.Kegunaannyasama sepertioutputdaristatement fmt.Print("\n"). PemanfaatanLabelDalamPerulangan Diperulanganbersarang, breakdan continueakanberlakupadablokperulangandimana iadigunakansaja.Adacaraagarkeduakeywordinibisatertujupadaperulanganterluar atauperulangantertentu,yaitudenganmemanfaatkanteknikpemberianlabel. Programuntukmemunculkanmatriksberikutmerupakancontohpenerapannya. outerLoop: fori:=0;i<5;i++{ forj:=0;j<5;j++{ ifi==3{ breakouterLoop } fmt.Print("matriks[",i,"][",j,"]","\n") } } Tepatsebelumkeyword forterluar,terdapatbariskode outerLoop:.Maksuddarikodeitu adalahdisiapkansebuahlabelbernama outerLoopuntukfordibawahnya.Namalabelbisa digantidengannamalain(danharusdiakhiridengantandatitikduaataucolon( :)). Padaforbagiandalam,terdapatseleksikondisiuntukpengecekannilai i.Ketikanilai tersebutsamadengan 3,maka breakdipanggildengantargetadalahforyanglabel-nya adalah outerLoop.Perulanganyangmemilikilabeltersebutakandiberhentikan. 51 Perulangan 52 Array Array Arrayadalahkumpulandatabertipesama,yangdisimpandalamsebuahvariabel.Array memilikikapasitasyangnilainyaditentukanpadasaatpembuatan,menjadikanelemen/data yangdisimpandiarraytersebutjumlahnyatidakbolehmelebihiyangsudahdialokasikan. Defaultnilaitiapelemenarraypadaawalnyatergantungdaritipedatanya.Jika intmaka defaultnya 0,jika boolmakadefault-nya false,dantipedatalain.Setiapelemenarray memilikiindeksberupaangkayangmerepresentasikanposisiurutanelementersebut. Indeksarraydimulaidari0. Contohpenerapanarray: varnames[4]string names[0]="trafalgar" names[1]="d" names[2]="water" names[3]="law" fmt.Println(names[0],names[1],names[2],names[3]) Variabel namesdideklarasikansebagai arraystringdenganalokasielemen 4slot.Cara mengisislotelemenarraybisadilihatdikodediatas,yaitudenganlangsungmengakses elemenmenggunakanindeks,lalumengisinya. InisialisasiNilaiAwalArray Pengisianelemenarraybisadilakukanpadasaatdeklarasivariabel.Caranyadengan menuliskandataelemendalamkurungkurawalsetelahtipedata,denganpembatasantar elemenadalahtandakoma( ,).Berikutmerupakancontohnya. varfruits=[4]string{"apple","grape","banana","melon"} fmt.Println("Jumlahelement\t\t",len(fruits)) fmt.Println("Isisemuaelement\t",fruits) 53 Array Penggunaanfungsi fmt.Println()padadataarraytanpamengaksesindekstertentu,akan menghasilkanoutputdalambentukstringdarisemuaarrayyangada.Teknikinibiasa digunakanuntukdebuggingdataarray. Fungsi len()digunakanuntukmenghitungjumlahelemensebuaharray. InisialisasiNilaiArrayDenganGayaVertikal Elemenarraybisadituliskandalambentukhorizontal(sepertiyangsudahdicontohkandi atas)ataupundalambentukvertikal.Contohnyabisadilihatdikodeberikut. varfruits[4]string //carahorizontal fruits=[4]string{"apple","grape","banana","melon"} //caravertikal fruits=[4]string{ "apple", "grape", "banana", "melon", } Perludiperhatikan,khususdeklarasimenggunakancaravertikal,perludituliskantanda komapadaakhirelementerakhir.Jikatidakditulisakanmunculerror. InisialisasiNilaiAwalArrayTanpaJumlah Elemen Deklarasiarrayyangnilainyadisetdiawal,bolehtidakdituliskanjumlahlebararray-nya, cukupgantidengantanda3titik( ...).Jumlahelemenakandikalkulasisecaraotomatis menyesuaikandataelemenyangdiisikan. varnumbers=[...]int{2,3,2,4,3} fmt.Println("dataarray\t:",numbers) fmt.Println("jumlahelemen\t:",len(numbers)) 54 Array Variabel numbersakansecaraajaibditentukanjumlahalokasinyayaitu 5,karenapada saatdeklarasidisiapkan5buahelemen. ArrayMultidimensi Arraymultidimensiadalaharrayyangtiapelemennyajugaberupaarray(danbisa seterusnya,tergantungjumlahdimensinya). Caradeklarasiarraymultidimensisecaraumumsamadengancaradeklarasiarraybiasa. Cukupmasukandataarrayyangmerupakandimensiselanjutnya,sebagaielemenarray dimensisebelumnya. Khususuntukarrayyangmerupakansubdimensiatauelemen,bolehtidakdituliskanjumlah datanya.Contohnyabisadilihatpadadeklarasivariabel numbers2dikodeberikut. varnumbers1=[2][3]int{[3]int{3,2,3},[3]int{3,4,5}} varnumbers2=[2][3]int{{3,2,3},{3,4,5}} fmt.Println("numbers1",numbers1) fmt.Println("numbers2",numbers2) Keduaarraydiatasadalahsamanilainya. PerulanganElemenArrayMenggunakan Keyword for Keyword fordanarraymemilikihubunganyangsangaterat.Denganmemanfaatkan perulanganmenggunakankeywordini,elemen-elemendalamarraybisadidapat. Adabeberapacarayangbisadigunakanuntukme-loopingdataarray,ygpertamaadalah denganmemanfaatkanvariabeliterasiperulanganuntukmengakseselemenberdasarkan indeks-nya.Contoh: 55 Array varfruits=[4]string{"apple","grape","banana","melon"} fori:=0;i<len(fruits);i++{ fmt.Printf("elemen%d:%s\n",i,fruits[i]) } Perulangandiatasdijalankansebanyakjumlahelemenarray fruits(bisadiketahuidari kondisi i<len(fruits).Ditiapperulangan,elemenarraydiaksesdenganmemanfaatkan variabeliterasi i. PerulanganElemenArrayMenggunakan Keyword for- range Adacarayanglebihmudahyangbisadimanfaatkanuntukme-loopingsebuahdataarray, yaitumenggunakankeyword for- range.Contohpengaplikasiannyabisadilihatdikode berikut. varfruits=[4]string{"apple","grape","banana","melon"} fori,fruit:=rangefruits{ fmt.Printf("elemen%d:%s\n",i,fruit) } Array fruitsdiambilelemen-nyasecaraberurutan.Nilaitiapelemenditampungvariabel oleh fruit(tanpahurufs),sedangkanindeksnyaditampungvariabel i. Outputprogramdiatas,samadenganoutputprogramsebelumnya,hanyacarayang digunakanberbeda. PenggunaanVariabelUnderscore _Dalam for- range Kadangkalaketikaloopingmenggunakan for- range,adakemungkinandimanadata yangdibutuhkanadalahelemen-nyasaja,indeks-nyatidak.Sedangkansepertidikodedi atas, rangemengembalikan2data,yaituindeksdanelemen. 56 Array Sepertiyangsudahdiketahui,bahwadiGolangtidakmemperbolehkanadanyavariabel yangmenagguratautidakdipakai.Jikadipaksakan,errorakanmuncul. Disinilahsalahsatukegunaanvariabelpengangguran,atauunderscore( _).Tampungsaja nilaiyangtidakingindigunakankeunderscore. varfruits=[4]string{"apple","grape","banana","melon"} for_,fruit:=rangefruits{ fmt.Printf("namabuah:%s\n",fruit) } Padakodediatas,yangsebelumnyaadalahvariabel idigantidengan _,karena kebetulanvariabel itidakdigunakan. Jikayangdibutuhkanhanyaindekselemen-nyasaja,bisagunakan1buahvariabelsetelah keyword for.Contoh: fori:=rangefruits{} //atau fori,_:=rangefruits{} AlokasiElemenArrayMenggunakanKeyword make Deklarasisekaligusalokasidataarraybisadilakukanlewatkeyword make.Contohnyabisa dilihatpadakodeberikut. varfruits=make([]string,2) fruits[0]="apple" fruits[1]="manggo" fmt.Println(fruits)//[applemanggo] 57 Array Parameterpertamakeywordtersebutdiisidengantipedataarrayyangakandibuat, parameterkeduaadalahjumlahelemennya.Padakodediatas,variabel fruitstercetak sebagaiarraystringdenganalokasi2slot. 58 Slice Slice Sliceadalahreferensielemenarray.Slicebisadibuat,ataubisajugadihasilkandari manipulasisebuaharrayataupunslicelainnya.Karenamerupakanreferensi,menjadikan perubahandataditiapelemensliceakanberdampakpadaslicelainyangmemilikialamat memoriyangsama. InisialisasiSlice Caramembuatslicemiripsepertipadaarray,bedanyatidakperlumendefinisikanjumlah elemenketikaawaldeklarasi.Pengaksesannilaielemen-nyajugasama.Kodeberikut adalahcontohpembuatanslice. varfruits=[]string{"apple","grape","banana","melon"} fmt.Println(fruits[0])//"apple" Salahsatuperbedaanslicedanarraybisadiketahuipadasaatdeklarasivariabel-nya,jika jumlahelementidakdituliskan,makavariabeltersebutadalahslice. varfruitsA=[]string{"apple","grape"}//slice varfruitsB=[2]string{"banana","melon"}//array varfruitsC=[...]string{"papaya","grape"}//array HubunganSliceDenganArray&OperasiSlice Kalauperbedannyahanyadipenentuanalokasipadasaatinisialisasi,kenapatidak menggunakansatuistilahsaja?atauadakahperbedaanlainnya? Sebenarnyaslicedanarraytidakbisadibedakankarenamerupakansebuahkesatuan. Arrayadalahkumpulannilaiatauelemen,sedangsliceadalahreferensitiapelemen tersebut. Slicebisadibentukdariarrayyangsudahdidefinisikan,caranyadenganmemanfaatkan teknik2indexuntukmengambilelemen-nya.Contohbisadilihatpadakodeberikut. 59 Slice varfruits=[]string{"apple","grape","banana","melon"} varnewFruits=fruits[0:2] fmt.Println(newFruits)//["apple","grape"] Kode fruits[0:2]maksudnyaadalahpengaksesanelemendalamslice fruitsyang dimulaidariindekske-0,hinggasebelumindekske-2.Elemenyangmemenuhikriteria tersebutkemudiandikembalikan,untukdisimpanpadavariabelsebagaislicebaru.Pada contohdiatas, newFruitsadalahslicebaruyangtercetakdarislice fruits,denganisi2 elemen,yaitu "apple"dan "grape". Ketikamengakseselemenarraymenggunakansatubuahindeks(seperti data[2]),nilai yangdidapatmerupakanhasilcopydarireferensiaslinya.Pengaksesanelemenlewat2 buahindeks(seperti data[0:2]),mengembalikansliceatauelemenreferensi. Tabelberikutadalahlistoperasioperasimenggunakanteknik2indeksyangbisadilakukan. varfruits=[]string{"apple","grape","banana","melon"} Kode Output Penjelasan fruits[0:2] [apple,grape] semuaelemenmulaiindekske-0, hinggasebelumindekske-2 fruits[0:4] [apple,grape,banana,melon] semuaelemenmulaiindekske-0, hinggasebelumindekske-4 fruits[0:0] [] menghasilkanslicekosong,karena tidakadaelemensebelumindeks ke-0 fruits[4:4] [] menghasilkanslicekosong,karena tidakadaelemenyangdimulaidari indekske-4 fruits[4:0] [] error,padapenulisan fruits[a,b] nilai aharuslebihbesaratau samadengan b fruits[:] [apple,grape,banana,melon] semuaelemen fruits[2:] [banana,melon] semuaelemenmulaiindekske-2 fruits[:2] [apple,apple] semuaelemenhinggasebelum indekske-2 60 Slice SliceMerupakanTipeDataReference Slicemerupakantipereference.Artinyajikaadaslicebaruyangterbentukdarislicelama, makaelemenslicebarumemilikireferensiyangsamadenganelemenslicelama.Setiap perubahanyangterjadidielemenslicebaru,akanberdampakjugapadaelemenslicelama yangmemilikireferensiyangsama. Programberikutmerupakanpembuktiantentangteoriyangbarukitabahas.Kitaakan mencobamengubahdataelemenslicebaru,yangterbentukdarislicelama. varfruits=[]string{"apple","grape","banana","melon"} varaFruits=fruits[0:3] varbFruits=fruits[1:4] varaaFruits=aFruits[1:2] varbaFruits=bFruits[0:1] fmt.Println(fruits)//[applegrapebananamelon] fmt.Println(aFruits)//[applegrapebanana] fmt.Println(bFruits)//[grapebananamelon] fmt.Println(aaFruits)//[grape] fmt.Println(baFruits)//[grape] //Buah"grape"diubahmenjadi"pinnaple" baFruits[0]="pinnaple" fmt.Println(fruits)//[applepinnaplebananamelon] fmt.Println(aFruits)//[applepinnaplebanana] fmt.Println(bFruits)//[pinnaplebananamelon] fmt.Println(aaFruits)//[pinnaple] fmt.Println(baFruits)//[pinnaple] Variabel aFruits, bFruitsmerupakanslicebaruyangterbentukdarivariabel fruits. Denganmenggunakanduaslicebarutersebut,diciptakanlagislicelainnya,yaitu aaFruits, dan baFruits.Kelimaslicetersebutditampilkannilainya. Selanjutnya,nilaidari baFruits[0]diubah,dan5slicetadiditampilkanlagi.Hasilnyaakan adabanyaksliceyangelemennyaikutberubah.Yaituelemen-elemenyangreferensi-nya samadenganreferensielemen baFruits[0]. 61 Slice Bisadilihatpadaoutputdiatas,elemenyangsebelumnyabernilai "grape"padavariabel fruits, aFruits, bFruits, aaFruits,dan baFruits;kesemuanyaberubahmenjadi "pinnaple",karenamemilikireferensiyangsama. AdabeberapabuiltinfunctionbawaanGolang,yangbisadimanfaatkanuntukkeperluan operasislice.Berikutadalahpembahasanmengenaifungsi-fungsitersebut. Fungsi len() Fungsi len()digunakanuntukmenghitunglebarsliceyangada.Sebagaicontohjika sebuahvariabeladalahslicedengandata4buah,makafungsiinipadavariabeltersebut akanmengembalikanangka4,yangangkatersebutdidapatdarijumlahelemenyangada. Contohpenerapannyabisadilihatdikodeberikut varfruits=[]string{"apple","grape","banana","melon"} fmt.Println(len(fruits))//4 Fungsi cap() Fungsi cap()digunakanuntukmenghitunglebarmaksimum/kapasitasslice.Nilai kembalianfungsiiniawalnyasamadengan len,tapibisaberubahtergantungdarioperasi sliceyangdilakukan.Agarlebihjelas,silakandisimakkodeberikut. 62 Slice varfruits=[]string{"apple","grape","banana","melon"} fmt.Println(len(fruits))//len:4 fmt.Println(cap(fruits))//cap:4 varaFruits=fruits[0:3] fmt.Println(len(aFruits))//len:3 fmt.Println(cap(aFruits))//cap:4 varbFruits=fruits[1:4] fmt.Println(len(bFruits))//len:3 fmt.Println(cap(bFruits))//cap:3 Variabel fruitsdisiapkandiawaldenganjumlahelemen4.Makafungsi len(fruits)dan cap(fruits)akanmenghasilkanangka4. Variabel aFruitsdan bFruitsmerupakanslicebaruberisikan3buahelemenmilikslice fruits.Variabel aFruitsmengambilelemenindex0,1,2;sedangkan bFruits1,2,3. Fungsi len()menghasilkanangka3,karenajumlahelemenkeduasliceiniadalah3. Tetapi cap(aFruits)menghasilkanangkayangberbeda,yaitu4untuk aFruitsdan3 untuk bFruits.kenapa?jawabannyabisadilihatpadatabelberikut. Kode Output fruits[0:4] len() cap() [ buah buah buah buah] 4 4 aFruits[0:3] [ buah buah buah ----] 3 4 bFruits[1:3] ----[ buah buah buah] 3 3 Slicingyangdimulaidariindeks0hinggaxakanmengembalikanelemen-elemenmulai indeks0hinggasebelumindeksx,denganlebarkapasitasadalahsamadenganslice aslinya.Sedangkanslicingyangdimulaidariindeksy,yangdimananilaiyadalahlebihdari 0,membuatelemenke-ysliceyangdiambilmenjadielemenke-0slicebaru.Halinilahyang membuatkapasitassliceberubah. Fungsi append() Fungsi append()digunakanuntukmenambahkanelemenpadaslice.Elemenbarutersebut diposisikansetelahindekspalingakhir.Nilaibalikfungsiiniadalahsliceyangsudah ditambahkannilaibarunya.Contohpenggunaannyabisadilihatdikodeberikut. 63 Slice varfruits=[]string{"apple","grape","banana"} varcFruits=append(fruits,"papaya") fmt.Println(fruits)//["apple","grape","banana"] fmt.Println(cFruits)//["apple","grape","banana","papaya"] Ada3halyangperludiketahuidalampenggunaanfungsiini. Ketikajumlahelemendanlebarkapasitasadalahsama( len(fruits)==cap(fruits)), makaelemenbaruhasil append()merupakanreferensibaru. Ketikajumlahelemenlebihkecildibandingkapasitas( len(fruits)<cap(fruits)), elemenbarutersebutditempatkankedalamcakupankapasitas,menjadikansemua elemenslicelainyangreferensi-nyasamaakanberubahnilainya. Agarlebihjelassilakanperhatikancontohberikut. varfruits=[]string{"apple","grape","banana"} varbFruits=fruits[0:2] fmt.Println(cap(bFruits))//3 fmt.Println(len(bFruits))//2 fmt.Println(fruits)//["apple","grape","banana"] fmt.Println(bFruits)//["apple","grape"] varcFruits=append(bFruits,"papaya") fmt.Println(fruits)//["apple","grape","papaya"] fmt.Println(bFruits)//["apple","grape"] fmt.Println(cFruits)//["apple","grape","papaya"] Padacontohdiatasbisadilihat,elemenindekske-2slice fruitsnilainyaberubahsetelah adapenggunaankeyword append()pada bFruits.Slice bFruitskapasitasnyaadalah3 sedangjumlahdatanyahanya2.Karena len(bFruits)<cap(bFruits),makaelemenbaru yangdihasilkan,terdeteksisebagaiperubahannilaipadareferensiyanglama(referensi elemenindekske-2slice fruits),membuatelemenyangreferensinyasama,nilainya berubah. Fungsi copy() Fungsi copy()digunakanuntukmen-copyelemenslicetujuan(parameterke-2),untuk digabungkandenganslicetarget(parameterke-1).Fungsiinimengembalikanjumlah elemenyangberhasildi-copy(yangnilaitersebutmerupakannilaiterkecilantara len(sliceTarget)dan len(sliceTujuan)).Berikutmerupakancontohpenerapannya. 64 Slice varfruits=[]string{"apple"} varaFruits=[]string{"watermelon","pinnaple"} varcopiedElemen=copy(fruits,aFruits) fmt.Println(fruits)//["apple","watermelon","pinnaple"] fmt.Println(aFruits)//["watermelon","pinnaple"] fmt.Println(copiedElemen)//1 PengaksesanElemenSliceDengan3Indeks 3indexadalahteknikslicingelemenyangsekaligusmenentukankapasitasnya.Cara menggunakannnyayaitudenganmenyisipkanangkakapasitasdibelakang,seperti fruits[0:1:1].Angkakapasitasyangdiisikantidakbolehmelebihikapasitassliceyang akandislicing. Berikutmerupakancontohpenerapannya. varfruits=[]string{"apple","grape","banana"} varaFruits=fruits[0:2] varbFruits=fruits[0:2:2] fmt.Println(fruits)//["apple","grape","banana"] fmt.Println(len(fruits))//len:3 fmt.Println(cap(fruits))//cap:3 fmt.Println(aFruits)//["apple","grape"] fmt.Println(len(aFruits))//len:2 fmt.Println(cap(aFruits))//cap:3 fmt.Println(bFruits)//["apple","grape"] fmt.Println(len(bFruits))//len:2 fmt.Println(cap(bFruits))//cap:2 65 Map Map MapadalahtipedataasosiatifyangadadiGolang.Bentuknyakey-value,artinyasetiapdata (atauvalue)yangdisimpan,disiapkanjugakey-nya.Keytersebutharusunik,karena digunakansebagaipenanda(atauidentifier)untukpengaksesandataatauitemyang tersimpan. Kalaudilihat,mapmiripsepertislice,hanyasajaindeksyangdigunakanuntukpengaksesan bisaditentukansendiritipe-nya(indekstersebutadalahkey). PenggunaanMap Caramenggunakanmapadalahdenganmenuliskankeyword mapdiikutitipedatakeydan value-nya.Agarlebihmudahdipahami,silakanperhatikancontohdibawahini. varchickenmap[string]int chicken=map[string]int{} chicken["januari"]=50 chicken["februari"]=40 fmt.Println("januari",chicken["januari"])//januari50 fmt.Println("mei",chicken["mei"])//mei0 Variabel chickendideklarasikansebagaimap,dengantipedatakeyadalah stringdan value-nya int.Darikodetersebutbisadilihatbagaimanacarapenggunaankeyword map. map[string]intmaknanyaadalahtipedata mapdengankeybertipe stringdanvalue bertipe int. Defaultnilaivariabel mapadalah nil.Olehkarenaituperludilakukaninisialisasinilai defaultdiawal,caranyacukupdengantambahkankurungkurawalpadaakhirtipe,contoh sepertipadakodediatas: map[string]int{}. Caramenge-setnilaivariabelmapcukupmudah,tinggalpanggilvariabel-nya,sisipkan key padakurungsikuvariabel(miripseperticarapengaksesanelemenslice),laluisinilainya, contohnyaseperti chicken["februari"]=40.Sedangkancarapengambilanvalueadalah cukupdenganmenyisipkan keypadakurungsikuvariabel. Pengisiandatapadamapbersifatoverwrite,ketikavariabelsudahmemilikiitemdengan keyyangsama,makavalue-nyaakanditimpadenganyangbaru. 66 Map Padapengaksesanitemmenggunakankeyyangbelumtersimpandimap,akan dikembalikannilaidefaulttipedatavalue-nya.Contohnyasepertipadakodediatas, chicken["mei"]menghasilkannilai0(nilaidefaulttipe int),karenabelumadaitemyang tersimpanmenggunakankey "mei". InisialisasiNilaiMap Nilaivariabelbertipemapbisadidefinisikandiawal,caranyadenganmenambahkankurung kurawalsetelahtipedata,lalumenuliskankeydanvaluedidalamnya.Carainisekilasmirip dengandefinisinilaiarray/slicenamundalambentukkey-value. //caravertikal varchicken1=map[string]int{"januari":50,"februari":40} //carahorizontal varchicken2=map[string]int{ "januari":50, "februari":40, } Keydanvaluedituliskandenganpembatastandatitikdua( :).Sedangkantiapitemnya dituliskandenganpembatastandakoma( ,).Khususdeklarasidengangayavertikal, tandakomaperludituliskansetelahitemterakhir. Variabelmapbisadiinisialisasidengantanpanilaiawal,caranyacukupmenggunakantanda kurungkurawal,contoh: map[string]int{}.Ataubisajugadenganmenggunakankeyword makedan new.Contohnyabisadilihatpadakodeberikut.Ketigacaradibawahiniintinya adalahsama. varchicken3=map[string]int{} varchicken4=make(map[string]int) varchicken5=*new(map[string]int) Khususinisialisasidatamenggunakankeyword new,yangdihasilkanadalahdatapointer. Untukmengambilnilaiaslinyabisadenganmenggunakantandaasterisk( *).Topikpointer akandibahaslebihdetailketikasudahmasukbab22. IterasiItemMapMenggunakan for- range 67 Map Itemvariabel mapbisadiiterasimenggunakan for- range.Carapenerapannyamasih samasepertipadaslice,pembedanyadatayangdikembalikanditiapperulanganadalahkey danvalue,bukanindeksdanelemen.Contohnyabisadilihatdikodeberikut. varchicken=map[string]int{ "januari":50, "februari":40, "maret":34, "april":67, } forkey,val:=rangechicken{ fmt.Println(key,"\t:",val) } MenghapusItemMap Fungsi delete()digunakanuntukmenghapusitemdengankeytertentupadavariabelmap. Carapenggunaannya,denganmemasukanobjekmapdankeyitemyangingindihapus sebagaiparameter. varchicken=map[string]int{"januari":50,"februari":40} fmt.Println(len(chicken))//2 fmt.Println(chicken) delete(chicken,"januari") fmt.Println(len(chicken))//1 fmt.Println(chicken) Itemyangmemilikikey "januari"dalamvariabel chickenakandihapus. Fungsi len()jikadigunakanpadamapakanmengembalikanjumlahitem. 68 Map DeteksiKeberadaanItemDenganKeyTertentu Adacarauntukmengetahuiapakahdalamsebuahvariabelmapterdapatitemdengankey tertentuatautidak,yaitudenganmemanfaatkan2variabelsebagaipenampungnilai kembalianpengaksesanitem.Variabelke-2akanberisikannilai boolyangmenunjukkan adaatautidaknyaitemyangdicari. varchicken=map[string]int{"januari":50,"februari":40} varvalue,isExist=chicken["mei"] ifisExist{ fmt.Println(value) }else{ fmt.Println("itemisnotexists") } KombinasiSlice&Map Slicedan mapbisadikombinasikan,danseringdigunakanpadabanyakkasus,contohnya sepertidataarrayyangberisikaninformasisiswa,danbanyaklainnya. Caramenggunakannyacukupmudah,contohnyaseperti []map[string]int,artinyaslice yangtipetiapelemen-nyaadalah map[string]int. Agarlebihjelas,silakanpraktekancontohberikut. varchickens=[]map[string]string{ map[string]string{"name":"chickenblue","gender":"male"}, map[string]string{"name":"chickenred","gender":"male"}, map[string]string{"name":"chickenyellow","gender":"female"}, } for_,chicken:=rangechickens{ fmt.Println(chicken["gender"],chicken["name"]) } Variabel chickensdiatasberisikaninformasibertipe map[string]string,yangkebetulan tiapelemenmemiliki2keyyangsama. Jikaandamenggunakanversigoterbaru,caradeklarasislice-mapbisadipersingkat,tipe tiapelementidakwajibuntukdituliskan. 69 Map varchickens=[]map[string]string{ {"name":"chickenblue","gender":"male"}, {"name":"chickenred","gender":"male"}, {"name":"chickenyellow","gender":"female"}, } Dalam []map[string]string,tiapelemenbisasajamemilikikeyyangberbeda-beda, sebagaicontohsepertikodeberikut. vardata=[]map[string]string{ {"name":"chickenblue","gender":"male","color":"brown"}, {"address":"manggastreet","id":"k001"}, {"community":"chickenlovers"} } 70 Fungsi Fungsi Fungimerupakanaspekpentingdalampemrograman.Definisifungsisendiriadalah sekumpulanblokkodeyangdibungkusdengannamatertentu.Penerapanfungsiyangtepat akanmenjadikankodelebihmodulardanjugadry(kependekandaridon'trepeatyourself), karenatakperlumenuliskanbanyakprosesberkali-kali,cukupsekalisajadantinggal panggiljikadibutuhkan. DibabinikitaakanbelajartentangpenggunaanfungsidiGolang. PenerapanFungsi Sebenarnyatanpasadar,kitasudahmenerapkanfungsidibab-babsebelumini,yaitupada fungsi main.Fungsi mainmerupakanfungsiyangpalingutamapadaprogramGolang. Caramembuatfungsicukupmudah,yaitudenganmenuliskankeyword func,diikuti setelahnyanamafungsi,kurungyangberisikanparameter,dankurungkurawaluntuk membungkusblokkode. Parametersendiriadalahvariabelyangdisisipkanpadasaatpemanggilanfungsi. Berikutadalahcontohpenerapanfungsi. packagemain import"fmt" import"strings" funcmain(){ varnames=[]string{"John","Wick"} printMessage("halo",names) } funcprintMessage(messagestring,arr[]string){ varnameString=strings.Join(arr,"") fmt.Println(message,nameString) } Padakodediatas,fungsibarudibuatdengannama printMessagememiliki2buah parameteryaitustring messagedanslicestring arr. 71 Fungsi Fungsitersebutdipanggildalam main,dengandisisipkan2buahdatasebagaiparameter, datapertamaadalahstring "hallo"yangditampungparameter message,danslicestring namesyangnilainyaditampungolehparameter arr. Didalam printMessage,nilai arryangmerupakanslicestringdigabungkanmenjadi sebuahstringdenganpembatasadalahkarakterspasi.Penggabunganslicedapat dilakukandenganmemanfaatkanfungsi strings.Join().Fungsiiniberadadidalam package strings. FungsiDenganReturnValue/NilaiBalik Sebuahfungsibisadidesaintidakmengembalikanapa-apa(void),ataubisamengembalikan suatunilai.Fungsiyangmemilikinilaikembalian,harusditentukantipedatanilaibaliknya padasaatdeklarasi. Programberikutmerupakancontohpenerapanfungsiyangmemilikireturnvalue. packagemain import( "fmt" "math/rand" "time" ) funcmain(){ rand.Seed(time.Now().Unix()) varrandomValueint randomValue=randomWithRange(2,10) fmt.Println("randomnumber:",randomValue) randomValue=randomWithRange(2,10) fmt.Println("randomnumber:",randomValue) randomValue=randomWithRange(2,10) fmt.Println("randomnumber:",randomValue) } funcrandomWithRange(min,maxint)int{ varvalue=rand.Int()%(max-min+1)+min returnvalue } 72 Fungsi Didalamfungsi randomWithRangeterdapatprosesgenerateangkaacak,yangangka tersebutkemudiandigunakansebagainilaikembalian. Caramenentukantipedatanilaibalikfungsiadalahdenganmenuliskantipedatayang diinginkansetelahkurungparameter.Bisadilihatpadakodediatas,bahwa int merupakantipedatanilaibalikfungsi randomWithRange. funcrandomWithRange(min,maxint)int Sedangkancarauntukmengembalikannilainyaadalahdenganmenggunakankeyword returndiikutidatayangingindikembalikan.Padacontohdiatas, returnvalueartinya nilaivariabel valuedijadikannilaikembalianfungsi. Eksekusikeyword returnakanmenjadikanprosesdalamblokfungsiberhentipadasaatitu juga.Semuastatementsetelahkeywordtersebuttidakakandieksekusi. Darikodediatasmungkinadabeberapastatementyangmasihterasaasing,berikut merupakanpembahasannya. PenggunaanFungsi rand.Seed() Fungsiinidiperlukanuntukmemastikanbahwaangkarandomyangakandi-generatebenarbenaracak.Kitabisagunakanangkaapasajasebagainilaiparameterfungsiini(umumnya diisi time.Now().Unix()). rand.Seed(time.Now().Unix()) Fungsi rand.Seed()beradadalampackage math/rand,yangharusdi-importterlebih dahulusebelumbisadimanfaatkan. Package timejugaperludi-importkarenakitamenggunakanfungsi (time.Now().Unix()) disitu. ImportBanyakPackage 73 Fungsi Penulisankeyword importuntukbanyakpackagebisadilakukandenganduacara,dengan menuliskannyaditiappackage,ataucukupsekalisaja.Contohnyabisadilihatdikode berikut. import"fmt" import"math/rand" import"time" //atau import( "fmt" "math/rand" "time" ) Pilihcarayangterasanyamandihati. DeklarasiParameterBertipeDataSama Khususuntukfungsiyangtipedataparameternyasama,bisaditulisdengangayayangunik. Tipedatanyadituliskancukupsekalisajadiakhir.Contohnyabisadilihatpadakodeberikut. funcnameOfFunc(paramAtype,paramBtype,paramCtype)returnType funcnameOfFunc(paramA,paramB,paramCtype)returnType funcrandomWithRange(minint,maxint)int funcrandomWithRange(min,maxint)int PenggunaanKeyword returnUntuk MenghentikanProsesDalamFungsi Selainsebagaipenandanilaibalik,keyword returnjugabisadimanfaatkanuntuk menghentikanprosesdalamblokfungsidimanaiadipakai.Contohnyabisadilihatpada kodeberikut. 74 Fungsi packagemain import"fmt" funcmain(){ divideNumber(10,2) divideNumber(4,0) divideNumber(8,-4) } funcdivideNumber(m,nint){ ifn==0{ fmt.Printf("invaliddivider.%dcannotdividedby%d\n",m,n) return } varres=m/n fmt.Printf("%d/%d=%d\n",m,n,res) } Fungsi divideNumberdidesaintidakmemilikinilaibalik.Fungsiinidibuatuntuk membungkusprosespembagian2bilangan,lalumenampilkanhasilnya. Didalamnyaterdapatprosesvalidasinilaivariabelpembagi,jikanilainyaadalah0,maka akanditampilkanpesanbahwapembagiantidakbisadilakukan,laluprosesdihentikanpada saatitujuga(denganmemanfaatkankeyword return).Jikanilaipembagivalid,maka prosespembagianditeruskan. 75 FungsiMultipleReturn FungsiMultipleReturn Umumnyafungsihanyamemilikisatubuahnilaibaliksaja.Jikaadakebutuhandimanadata yangdikembalikanharusbanyak,biasanyadigunakanlahtipeseperti map,slice,atau structsebagainilaibalik. Golangmenyediakankapabilitasbagiprogrammeruntukmembuatfungsimemilikibanyak nilaibalik.Dibabiniakandibahasbagaimanapenerapannya. PenerapanFungsiMultipleReturn Caramembuatfungsiyangmemilikibanyaknilaibaliktidaklahsulit.Tinggaltulissajapada saatdeklarasifungsisemuatipedatanilaiyangdikembalikan,danpadakeyword return tulissemuadatayangingindikembalikan.Contohbisadilihatpadaberikut. packagemain import"fmt" import"math" funccalculate(dfloat64)(float64,float64){ //hitungluas vararea=math.Pi*math.Pow(d/2,2) //hitungkeliling varcircumference=math.Pi*d //kembalikan2nilai returnarea,circumference } Fungsi calculate()diatasmenerimasatubuahparameter( diameter)yangdigunakan dalamprosesperhitungan.Didalamfungsitersebutada2halyangdihitung,yaitunilai kelilingdanlingkaran.Keduanilaitersebutkemudiandijadikansebagaireturnvaluefungsi. Carapendefinisianbanyaknilaibalikbisadilihatpadakodediatas,yaitudenganlangsung menuliskantipe-tipedatanilaibalikdenganpemisahtandakoma,danditambahkankurung diantaranya. funccalculate(dfloat64)(float64,float64) 76 FungsiMultipleReturn Taklupadibagianpenulisankeyword returnharusdituliskanjugasemuadatayang dijadikannilaibalik(denganpemisahtandakoma). returnarea,circumference Implementasidarifungsi calculate()diatas,bisadilihatpadakodeberikut. funcmain(){ vardiameterfloat64=15 vararea,circumference=calculate(diameter) fmt.Printf("luaslingkaran\t\t:%.2f\n",area) fmt.Printf("kelilinglingkaran\t:%.2f\n",circumference) } Outputprogram: Karenafungsitersebutmemilikibanyaknilaibalik,makapadapemanggilannyaharus disiapkanjugabanyakvariabeluntukmenampungnilaikembalianyangada(sesuaijumlah nilaibalikfungsi). vararea,circumference=calculate(diameter) Adabeberapahalbarudarikodediatasyangperludibahas,seperti math.Pow()dan math.Pi.Berikutadalahpenjelasannya. PenggunaanFungsi math.Pow() Fungsi math.Pow()digunakanuntukmemangkatnilai. math.Pow(2,3)berarti2pangkat3, hasilnya8.Fungsiiniberadadalampackage math. PenggunaanKonstanta math.Pi math.Piadalahkonstantabawaan packagemathyangmerepresentasikanPiatau22/7. 77 FungsiMultipleReturn 78 FungsiVariadic FungsiVariadic Golangmengadopsikonsepvariadicfunctionataupembuatanfungsidenganparameter sejenisyangtakterbatas.Maksudtakterbatasdisiniadalahjumlahparameteryang disisipkanketikapemanggilanfungsibisaberapasaja. Parametervariadicmemilikisifatyangmiripdenganslice.Nilaiparameter-parameteryang disisipkanmemilikitipedatayangsama,danakanditampungolehsebuahvariabelsaja. Carapengaksesantiapdatanyajugasama,denganmenggunakanindeks. Dibabinikitaakanbelajarmengenaicarapenerapanfungsivariadic. PenerapanFungsiVariadic Deklarasiparametervariadicsamadengancaradeklarasivariabelbiasa,pembedanyapada parameterjenisiniditambahkantanda3titik( ...)setelahpenulisanvariabel(sebelumtipe data).Nantinyasemuanilaiyangdisisipkansebagaiparameterakanditampungoleh variabeltersebut. Berikutmerupakancontohpenerepannya. packagemain import"fmt" funcmain(){ varavg=calculate(2,4,3,5,4,3,3,5,5,3) varmsg=fmt.Sprintf("Rata-rata:%.2f",avg) fmt.Println(msg) } funccalculate(numbers...int)float64{ vartotalint=0 for_,number:=rangenumbers{ total+=number } varavg=float64(total)/float64(len(numbers)) returnavg } Outputprogram: 79 FungsiVariadic Bisadilihatpadafungsi calculate(),parameter numbersdideklarasikandengandisisipkan tanda3titik( ...)sebelumpenulisantipedata-nya.Menandakanbahwa numbersadalah sebuahparametervariadicdengantipedata int. funccalculate(numbers...int)float64{ Padapemanggilanfungsidisisipkanbanyakparametersesuaikebutuhan. varavg=calculate(2,4,3,5,4,3,3,5,5,3) Nilaitiapparameterbisadiaksesseperticarapengaksesantiapelemenslice.Padacontoh diatasmetodeyangdipilihadalah for- range. for_,number:=rangenumbers{ Berikutmerupakanpenjelasantambahanmengenaibeberapakodediatas. PenggunaanFungsi fmt.Sprintf() Fungsi fmt.Sprintf()padadasarnyasamadengan fmt.Printf(),hanyasajafungsiini tidakmenampilkannilai,melainkanmengembalikannilainyadalambentukstring.Pada kasusdiatas,nilaihasil fmt.Sprintf()ditampungolehvariabel msg. Selain fmt.Sprintf(),adajuga fmt.Sprint()dan fmt.Sprintln(). PenggunaanFungsi float64() Sebelumnyasudahdibahasbahwa float64merupakantipedata.Tipedatajikaditulis sebagaifungsi(penandanyaadatandakurungnya)bergunauntukcasting.Castingsendiri adalahteknikuntukkonversitipesebuahdataketipelain.Hampirsemuajenistipedata dasaryangtelahdipelajaridibab9bisadigunakanuntukcasting.Dancarapenerepannya jugasama,cukuppanggilsebagaifungsi,lalumasukandatayangingindikonversisebagai parameter. Padacontohdiatas,variabel totalyangtipenyaadalah int,dikonversimenjadi float64,begitujuga len(numbers)yangmenghasilkan intdikonversike float64. 80 FungsiVariadic Variabel avgperludijadikan float64karenapenghitunganrata-ratalebihsering menghasilkannilaidesimal. Operasibilangan(perkalian,pembagian,danlainnya)diGolanghanyabisadilakukanjika tipedatanyasejenis.Makadariitulahperluadanyacastingketipe float64padatiap operand. PengisianFungsiVariadicMenggunakanData Slice Slicebisadigunakansebagaiparametervariadic.Caranyacukupmudah,yaitudengan menambahkantanda3titiksetelahnamavariabelketikamemasukannyakeparameter. Contohnyabisadilihatpadakodeberikut. varnumbers=[]int{2,4,3,5,4,3,3,5,5,3} varavg=calculate(numbers...) varmsg=fmt.Sprintf("Rata-rata:%.2f",avg) fmt.Println(msg) Padakodediatas,variabel numbersyangmerupakansliceint,disisipkankefungsi calculate()sebagaiparametervariadic(bisadilihattanda3titiksetelahpenulisan variabel).Teknikinisangatbergunaketikasebuahdatasliceingindifungsikansebagai parametervariadic. Perhatikanjugakodeberikutini.Intinyaadalahsama,hanyacaranyayangberbeda. varnumbers=[]int{2,4,3,5,4,3,3,5,5,3} varavg=calculate(numbers...) //atau varavg=calculate(2,4,3,5,4,3,3,5,5,3) Padadeklarasiparameterfungsivariadic,tanda3titik( ...)dituliskansebelumtipedata parameter.Sedangkanpadapemanggilanfungsidenganmenyisipkanparameterarray, tandatersebutdituliskandibelakangvariabelnya. FungsiDenganParameterBiasa&Variadic 81 FungsiVariadic Parametervariadicbisadikombinasikandenganparameterbiasa,dengansyaratparameter variadic-nyaharusdiposisikandiakhir.Contohnyabisadilihatpadakodeberikut. import"fmt" import"strings" funcyourHobbies(namestring,hobbies...string){ varhobbiesAsString=strings.Join(hobbies,",") fmt.Printf("Hello,mynameis:%s\n",name) fmt.Printf("Myhobbiesare:%s\n",hobbiesAsString) } Nilaiparameterpertamafungsi yourHobbies()akanditampungoleh name,sedangkannilai parameterkeduadanseterusnyaakanditampungoleh hobbiessebagaislice. Carapemanggilannyamasihsamaseperipadafungsibiasa.Contohnyabisadilihatpada kodeberikut. funcmain(){ yourHobbies("wick","sleeping","eating") } Jikaparameterkeduadanseterusnyaingindiisidengandatadarislice,makagunakan tanda3titik.Contoh: funcmain(){ varhobbies=[]string{"sleeping","eating"} yourHobbies("wick",hobbies...) } Outputprogram: 82 FungsiClosure FungsiClosure DefinisitermudahClosureadalahsebuahfungsiyangbisadisimpandalamvariabel. Denganmenerapkankonseptersebut,sangatmungkinuntukmembuatfungsididalam fungsi,ataubahkanmembuatfungsiyangmengembalikanfungsi. Closuremerupakananonymousfunctionataufungsitanpanama.Biasadimanfaatkanuntuk membungkussuatuprosesyanghanyadipakaisekaliataudipakaipadabloktertentusaja. ClosureDisimpanSebagaiVariabel Sebuahfungsitanpanamabisadisimpandalamvariabel.Variabelyangmenyimpanclosure memilikisifatsepertifungsiyangdisimpannya.Dibawahiniadalahcontohprogram sederhanauntukmencarinilaiterendahdantertinggidarisuatuarray.Logikapencarian dibungkusdalamclosureyangditampungolehvariabel getMinMax. packagemain import"fmt" funcmain(){ vargetMinMax=func(n[]int)(int,int){ varmin,maxint fori,e:=rangen{ switch{ casei==0: max,min=e,e casee>max: max=e casee<min: min=e } } returnmin,max } varnumbers=[]int{2,3,4,3,4,2,3} varmin,max=getMinMax(numbers) fmt.Printf("data:%v\nmin:%v\nmax:%v\n",numbers,min,max) } 83 FungsiClosure Bisadilihatpadakodediatasbagiamanacaraclosuredibuatdandipanggil.Sedikitberbeda memangdibandingpembuatanfungsibiasa.Fungsiditulistanpanama,laluditampung dalamvariabel. vargetMinMax=func(n[]int)(int,int){ //... } Carapemanggilannya,denganmenuliskannamavariabeltersebutsebagaifungsi(seperti pemanggilanfungsibiasa). varmin,max=getMinMax(numbers) Outputprogram: Berikutadalahpenjelasantambahanmengenaikodediatas PenggunaanTemplateString %v Template %vdigunakanuntukmenampilkansegalajenisdata.Bisaarray,int,float,bool, danlainnya. fmt.Printf("data:%v\nmin:%v\nmax:%v\n",numbers,min,max) Bisadilihatpadastatementdiatas,databertipearraydannumerikditampilkan menggunakan %v.Templateinibiasadimanfaatkanuntukmenampilkansebuahdatayang tipenyabisadinamisataubelumdiketahui.Sangattepatjikadigunakanpadadatabertipe interface{}yangnantinyaakandibahaspadabab27. Immediately-InvokedFunctionExpression (IIFE) 84 FungsiClosure Closurejenisinidieksekusilangsungpadasaatdeklarasinya.Biasadigunakanuntuk membungkusprosesyanghanyadilakukansekali,bisamengembalikannilai,bisajuga tidak. DibawahinimerupakancontohsederhanapenerapanmetodeIIFEuntukfilteringdata array. packagemain import"fmt" funcmain(){ varnumbers=[]int{2,3,0,4,3,2,0,4,2,0,3} varnewNumbers=func(minint)[]int{ varr[]int for_,e:=rangenumbers{ ife<min{ continue } r=append(r,e) } returnr }(3) fmt.Println("originalnumber:",numbers) fmt.Println("filterednumber:",newNumbers) } Outputprogram: CirikhasIIFEadalahadanyakurungparametertepatsetelahdeklarasiclosureberakhir.Jika adaparameter,bisajugadituliskandalamkurungparameternya. varnewNumbers=func(minint)[]int{ //... }(3) PadacontohdiatasIIFEmenghasilkannilaibalikyangkemudianditampung newNumber. Perludiperhatikanbahwayangditampungadalahnilaikembaliannyabukanclosure-nya. 85 FungsiClosure Closurebisajugadengangayamanifesttyping,caranyadenganmenuliskanskema closure-nyasebagaitipedata.Contoh: varclosure(func(string,int,[]string)int) closure=func(astring,bint,c[]string)int{ //.. } ClosureSebagaiNilaiKembalian Salahsatukeunikanclosurelainnyaadalahbisadijadikansebagainilaibalikfungsi,cukup anehmemang,tapipadasuatukondisiteknikinisangatmembantu.Dibawahinidisiapkan sebuahfungsibernama findMax()yangmemilikisalahsatunilaikembalianberupaclosure. packagemain import"fmt" funcfindMax(numbers[]int,maxint)(int,func()[]int){ varres[]int for_,e:=rangenumbers{ ife<=max{ res=append(res,e) } } returnlen(res),func()[]int{ returnres } } Nilaikembalianke-2padafungsidiatasadalahclosuredenganskema func()[]int.Bisa dilihatdibagianakhir,adafungsitanpanamayangdikembalikan. returnlen(res),func()[]int{ returnres } Fungsitanpanamayangakandikembalikanbolehdisimpanpadavariabelterlebih dahulu.Contohnya: vargetNumbers=func()[]int{ returnres } returnlen(res),getNumbers 86 FungsiClosure Sedikittentangfungsi findMax(),fungsiinidigunakanuntukmencaribanyaknyaangkaangkayangnilainyadibawahatausamadenganangkatertentu.Nilaikembalianpertama adalahjumlahangkanya.Nilaikembaliankeduaberupaclosureyangmengembalikan angka-angkayangdicari.Berikutmerupakancontohimplementasifungsitersebut. funcmain(){ varmax=3 varnumbers=[]int{2,3,0,4,3,2,0,4,2,0,3} varhowMany,getNumbers=findMax(numbers,max) vartheNumbers=getNumbers() fmt.Println("numbers\t:",numbers) fmt.Printf("find\t:%d\n\n",max) fmt.Println("found\t:",howMany)//9 fmt.Println("value\t:",theNumbers)//[230320203] } Outputprogram: 87 FungsiSebagaiparameter FungsiSebagaiparameter Setelahdibabsebelumnyakitabelajarmengenaifungsiyangmengembalikannilaibalik berupafungsi,kaliinitopiknyatidakkalahunik,yaitufungsiyangdigunakansebagai parameter. DiGolang,fungsibisadijadikansebagaitipedatavariabel.Darisitusangatmemungkinkan untukmenjadikannyasebagaiparameterjuga. PenerapanFungsiSebagaiParameter Caramembuatparameterfungsiadalahdenganlangsungmenuliskanskemafungsinya sebagaitipedata.Contohnyabisadilihatpadakodeberikut. packagemain import"fmt" import"strings" funcfilter(data[]string,callbackfunc(string)bool)[]string{ varresult[]string for_,each:=rangedata{ iffiltered:=callback(each);filtered{ result=append(result,each) } } returnresult } Parameter callbackmerupakansebuahclosureyangdideklarasikanbertipe func(string) bool.Closuretersebutdipanggilditiapperulangandalamfungsi filter(). Fungsi filter()sendiridigunakanuntukfilteringdataarray(yangdatanyadidapatdari parameterpertama),dengankondisifilterbisaditentukansendiri.Dibawahiniadalah contohpemanfaatanfungsitersebut. 88 FungsiSebagaiparameter funcmain(){ vardata=[]string{"wick","jason","ethan"} vardataContainsO=filter(data,func(eachstring)bool{ returnstrings.Contains(each,"o") }) vardataLenght5=filter(data,func(eachstring)bool{ returnlen(each)==5 }) fmt.Println("dataasli\t\t:",data) //dataasli:[wickjasonethan] fmt.Println("filteradahuruf\"i\"\t:",dataContainsO) //filteradahuruf"i":[wick] fmt.Println("filterjumlahhuruf\"5\"\t:",dataLenght5) //filterjumlahhuruf"5":[jasonethan] } Adacukupbanyakhalyangterjadididalamtiappemanggilanfungsi filter()diatas. Berikutmerupakanpenjelasannya. 1. Dataarray(yangdidapatdariparameterpertama)akandi-looping 2. Ditiapperulangannya,closure callbackdipanggil,dengandisisipkandatatiapelemen perulangansebagaiparameter 3. Closure callbackberisikankondisifiltering,denganhasilbertipe boolyang kemudiandijadikannilaibalikdikembalikan. 4. Didalamfungsi filter()sendiri,adaprosesseleksikondisi(yangnilainyadidapat darihasileksekusiclosure callback).Ketikakondisinyabernilai true,makadata elemenyangsedangdiulangdinyatakanlolosprosesfiltering 5. Datayanglolosditampungvariabel result.Variabeltersebutdijadikansebagainilai balikfungsi filter() Pada dataContainsO,parameterkeduafungsi filter()berisikanstatementuntukdeteksi apakahterdapatsubstring "i"didalamnilaivariabel each(yangmerupakandatatiap elemen),jikaiya,makakondisifilterbernilai true,dansebaliknya. padacontohke-2( dataLength5),closure callbackberisikanstatementuntukdeteksi jumlahkaraktertiapelemen.Jikaadaelemenyangjumlahkarakternyaadalah5,berarti elementersebutlolosfilter. 89 FungsiSebagaiparameter Memangbutuhusahaekstrauntukmemahamipemanfaatanclosuresebagaiparameter fungsi.Tapisetelahtauapamanfaatnya,penerapanteknikinipadakondisiyangtepatakan sangatmembantuprosespembuatanaplikasi. AliasSkemaClosure Sepertiyangsudahdipelajaridiatas,bahwaclosurebisadimanfaatkansebagaitipe parameter,contohnyasepertipadafungsi filter()diatas.Padafungsitersebutkebetulan skematipeparameterclosure-nyatidakterlalupanjang,hanyaadasatubuahparameter dansatubuahnilaibalik. Padaskemafungsiyangcukuppanjang,akanlebihbaikjikadigunakanalias,apalagiketika adaparameterfungsilainyangjugamenggunakanskemayangsama.Membuataliasfungsi berartimenjadikanskemafungsitersebutmenjaditipedatabaru.Caranyadengan menggunakankeyword type.Contoh: typeFilterCallbackfunc(string)bool funcfilter(data[]string,callbackFilterCallback)[]string{ //... } Skema func(string)booldiubahmenjaditipedengannama FilterCallback.Tipe tersebutkemudiandigunakansebagaitipedataparameter callback. Dibawahinimerupakanpenjelasantambahanmengenaifungsi strings.Contains(). PenggunaanFungsi string.Contains() Intidarifungsiiniadalahuntukdeteksiapakahsebuahsubstringadalahbagiandaristring, jikaiyamakaakanbernilai true,dansebaliknya.Contohpenggunaannya: varresult=strings.Contains("Golang","ang") //true Variabel resultbernilai truekarenastring "ang"merupakanbagiandaristring "Golang". 90 FungsiSebagaiparameter 91 Pointer Pointer Pointeradalahreferensiataualamatmemory.Variabelpointerberartivariabelyang menampungalamatmemorisuatunilai.Sebagaicontohsebuahvariabelbertipeinteger memilikinilai4,makayangdimaksudpointeradalahalamatmemoridimananilai4 disimpan,bukannilai4nyasendiri. Variabel-variabelyangmemilikireferensiataualamatpointeryangsama,saling berhubungansatusamalaindannilainyapastisama.Ketikaadaperubahannilai,maka akanmemberikanefekkepadavariabellain(yangreferensi-nyasama)yaitunilainyaikut berubah. PenerapanPointer Variabelbertipepointerditandaidenganadanyatandaasterisk( *)tepatsebelum penulisantipedataketikadeklarasi. varnumber*int varname*string Nilaidefaultvariabelpointeradalah nil(kosong).Variabelpointertidakbisamenampung nilaiyangbukanpointer,dansebaliknyavariabelbiasatidakbisamenampungnilaipointer. Variabelbiasasebenarnyajugabisadiambilnilaipointernya,caranyadengan menambahkantandaampersand( &)tepatsebelumnamavariabel.Metodeinidisebut denganreferencing. Dansebaliknya,nilaiaslivariabelpointerjugabisadiambil,dengancaramenambahkan tandaasterisk( *)tepatsebelumnamavariabel.Metodeinidisebutdengan dereferencing. OK,langsungsajakitapraktekan.Berikutadalahcontohpenerapanpointer. varnumberAint=4 varnumberB*int=&numberA fmt.Println("numberA(value):",numberA)//4 fmt.Println("numberA(address):",&numberA)//0xc20800a220 fmt.Println("numberB(value):",*numberB)//4 fmt.Println("numberB(address):",numberB)//0xc20800a220 92 Pointer Variabel numberBdideklarasikanbertipepointer intdengannilaiawaladalahreferensi variabel numberA(bisadilihatpadakode &numberA).Denganini,variabel numberAdan numberBmenampungdatadenganreferensialamatmemoriyangsama. Variabelpointerjikadi-printakanmenghasilkanstringalamatmemori(dalamnotasi heksadesimal),contohnyaseperti numberByangdiprintmenghasilkan 0xc20800a220.Nilai aslipointerbisaditampilkandengancaravariabeltersebutharusdi-dereferenceterlebih dahulu(bisadilihatpadakode *numberB). EfekPerubahanNilaiPointer Ketikasalahsatuvariabelpointerdiubahnilainya,sedangadavariabellainyangmemiliki referensimemoriyangsama,makanilaivariabellaintersebutjugaakanberubah.Contoh: varnumberAint=4 varnumberB*int=&numberA fmt.Println("numberA(value):",numberA) fmt.Println("numberA(address):",&numberA) fmt.Println("numberB(value):",*numberB) fmt.Println("numberB(address):",numberB) fmt.Println("") numberA=5 fmt.Println("numberA(value):",numberA) fmt.Println("numberA(address):",&numberA) fmt.Println("numberB(value):",*numberB) fmt.Println("numberB(address):",numberB) Variabel numberAdan numberBmemilikireferensimemoriyangsama.Perubahanpada salahsatunilaivariabeltersebutakanmemberikanefekpadavariabellainnya.Padacontoh diatas, numberAnilainyadiubahmenjadi 5.membuatnilaiaslivariabel numberBikut berubahmenjadi 5. 93 Pointer ParameterPointer Parameterbisajugadidesainsebagaipointer.Carapenerapannyakuranglebihsama. Tinggaldeklarasikanparametertersebutsebagaipointer. packagemain import"fmt" funcmain(){ varnumber=4 fmt.Println("before:",number)//4 change(&number,10) fmt.Println("after:",number)//10 } funcchange(original*int,valueint){ *original=value } Fungsi change()memiliki2parameter,yaitu originalyangtipenyaadalahpointer int, dan value.Didalamfungsitersebutnilaiasliparameterpointer originaldiubah. Fungsi change()kemudiandiimplementasikandi main.Variabel numberyangnilai awalnyaadalah 4diambilreferensi-nyalaludigunakansebagaiparameterpada pemanggilanfungsi change(). Nilaivariabel numberberubahmenjadi 10karenaperubahanyangterjadididalamfungsi changeadalahpadavariabelpointer. 94 Pointer 95 Struct Struct Structadalahkumpulandefinisivariabel(atauproperty)danataufungsi(ataumethod),yang dibungkusdengannamatertentu. Propertydalamstruct,tipedatanyabisabervariasi.Miripseperti map,hanyasajakey-nya sudahdidefinisikandiawal,dantipedatatiapitemnyabisaberbeda. Denganmemanfaatkanstruct,dataakanterbungkuslebihrapidanmudahdi-maintain. Structmerupakancetakan,digunakanuntukmencetakvariabelobjek(istilahuntukvariabel yangmemilikiproperty).Variabelobjekmemilikibehaviouratausifatyangsamasesuai structpencetaknya.Konsepinisamadengankonsepclasspadapemrogramanberbasis objek.Sebuahbuahstructbisadimanfaatkanuntukmencetakbanyakobjek. DeklarasiStruct Keyword typedigunakanuntukdeklarasistruct.Dibawahinimerupakancontohcara penggunaannya. typestudentstruct{ namestring gradeint } Struct studentdideklarasikanmemiliki2property,yaitu namedan grade.Objekyang dicetakdenganstructininantinyaakanmemilikisifatyangsama. PenerapanStruct Struct studentyangsudahdisiapkandiatasakankitamanfaatkanuntukmencetaksebuah variabelobjek.Propertyvariabeltersebutnantinyadiisikemudianditampilkan. 96 Struct funcmain(){ vars1student s1.name="johnwick" s1.grade=2 fmt.Println("name:",s1.name) fmt.Println("grade:",s1.grade) } Caramembuatvariabelobjeksamasepertipembuatanvariabelbiasa.Tinggaltulissaja namavariabeldiikutinamastruct,contoh: vars1student. Semuapropertyvariabelobjekpadaawalnyamemilikinilaidefaultsesuaitipedatanya. Propertyvariabelobjekbisadiaksesnilainyamenggunakannotasititik,contohnya s1.name. Nilaiproperty-nyajugabisadiubah,contohnyapadakode s1.grade=2. InisialisasiObjectStruct Carainisialisasivariabelobjekadalahdenganmenambahkankurungkurawalsetelahnama struct.Nilaimasing-masingpropertybisadiisipadasaatinisialisasi. Padacontohberikut,terdapat3buahvariabelobjekyangdideklarasikandengancara berbeda. vars1=student{} s1.name="wick" s1.grade=2 vars2=student{"ethan",2} vars3=student{name:"jason"} fmt.Println("student1:",s1.name) fmt.Println("student2:",s2.name) fmt.Println("student3:",s3.name) Padakodediatas,variabel s1menampungobjekcetakan student.Vartiabeltersebut kemudiandi-setnilaiproperty-nya. 97 Struct Variabelobjek s2dideklarasikandenganmetodeyangsamadengan s1,pembedanyadi s2nilaipropertinyadiisilangsungketikadeklarasi.Nilaipertamaakanmenjadinilai propertypertama(yaitu name),danselanjutnyaberurutan. Padadeklarasi s3,dilakukanjugapengisianpropertyketikapencetakanobjek.Hanya saja,yangdiisihanya namesaja.Carainicukupefektifjikadigunakanuntukmembuat objekbaruyangnilaiproperty-nyatidaksemuaharusdisiapkandiawal.Keistimewaanlain menggunakancarainiadalahpenentuannilaipropertybisadilakukandengantidak berurutan.Contohnya: vars4=student{name:"wayne",grade:2} vars5=student{grade:2,name:"bruce"} VariabelObjekPointer Objekhasilcetakanstructbisadiambilnilaipointer-nya,danbisadisimpanpadavariabel objekyangbertipestructpointer.Contohpenerapannya: vars1=student{name:"wick",grade:2} vars2*student=&s1 fmt.Println("student1,name:",s1.name) fmt.Println("student4,name:",s2.name) s2.name="ethan" fmt.Println("student1,name:",s1.name) fmt.Println("student4,name:",s2.name) s2adalahvariabelpointerhasilcetakanstruct student. s2menampungnilaireferensi s1,mengakibatkansetiapperubahanpadapropertyvariabeltersebut,akanjuga berpengaruhpadavariabelobjek s1. Meskipun s2bukanvariabelasli,propertynyatetapbisadiaksessepertibiasa.Inilah keunikanvariabelobjekpointer,tanpaperludi-dereferensinilaiaslipropertytetapbisa diakses.Pengisiannilaipadapropertytersebutjugabisalangsungmenggunakannilaiasli, contohnyaseperti s2.name="ethan". 98 Struct EmbeddedStruct Embeddedstructadalahpenurunanpropertidarisatustructkestructlain,sehinggaproperti structyangditurunkanbisadigunakan.Agarlebihmudahdipahami,marikitabahaskode berikut. packagemain import"fmt" typepersonstruct{ namestring ageint } typestudentstruct{ gradeint person } funcmain(){ vars1=student{} s1.name="wick" s1.age=21 s1.grade=2 fmt.Println("name:",s1.name) fmt.Println("age:",s1.age) fmt.Println("age:",s1.person.age) fmt.Println("grade:",s1.grade) } Padakodediatas,disiapkanstruct persondenganpropertiyangtersediaadalah name dan age.Disiapkanjugastruct studentdenganproperty grade.Struct persondi-embed kedalamstruct student.Caranyacukupmudah,yaitudenganmenuliskannamastruct yangingindi-embedkedalambody structtarget. Embeddedstructadalahmutable,nilaiproperty-nyanyabisadiubah. Khususuntukpropertiyangbukanpropertiasli(propertiturunandaristructlain),bisa diaksesdengancaramengaksesstructparent-nyaterlebihdahulu.Contoh s1.person.age. Nilaiyangdikembalikanmemilikireferensiyangsamadengan s1.age. EmbeddedStructDenganNamaPropertyYang Sama 99 Struct Jikasalahsatunamapropertisebuahstructmemilikikesamaandenganpropertimilikstruct lainyangdi-embed,makapengaksesanproperty-nyaharusdilakukandenganjelas.Contoh bisadilihatdikodeberikut. packagemain import"fmt" typepersonstruct{ namestring ageint } typestudentstruct{ person ageint gradeint } funcmain(){ vars1=student{} s1.name="wick" s1.age=21//ageofstudent s1.person.age=22//ageofperson fmt.Println(s1.name) fmt.Println(s1.age) fmt.Println(s1.person.age) } Struct persondi-embedkedalamstruct student,dankeduastructtersebutkebetulan salahsatunamaproperty-nyaadaygsama,yaitu age.Caramengaksesproperty age milikstruct personlewatobjekstruct student,adalahdenganmenuliskannamastructyg di-embedkemudiannamaproperty-nya,contohnya: s1.person.age=22. PengisianNilaiSub-Struct Pengisiannilaipropertysub-structbisadilakukandenganlangsungmemasukkanvariabel objekyangtercetakdaristructyangsama. varp1=person{name:"wick",age:21} vars1=student{person:p1,grade:2} fmt.Println("name:",s1.name) fmt.Println("age:",s1.age) fmt.Println("grade:",s1.grade) 100 Struct Padadeklarasi s1,property persondiisivariabelobjek p1. AnonymousStruct Anonymousstructadalahstructyangtidakdideklarasikandiawal,melainkanketika dibutuhkansaja,langsungpadasaatpenciptaanobjek.Teknikinicukupefisienuntuk pembuatanvariabelobjekyangstructnyahanyadipakaisekali. packagemain import"fmt" typepersonstruct{ namestring ageint } funcmain(){ vars1=struct{ person gradeint }{} s1.person=person{"wick",21} s1.grade=2 fmt.Println("name:",s1.person.name) fmt.Println("age:",s1.person.age) fmt.Println("grade:",s1.grade) } Padakodediatas,variabel s1langsungdiisiobjekanonymousstructyangmemiliki sebuahproperty grade,danpropertylainyangditurunkandaristruct person. Salahsatuaturanyangperludiingatdalampembuatananonymousstructadalah,deklarasi harusdiikutidenganinisialisasi.Bisadilihatpada s1setelahdeklarasistrukturstruct, terdapatkurungkurawaluntukinisialisasiobjek.Meskipunnilaitidakdiisikandiawal,kurung kurawaltetapharusditulis. 101 Struct //anonymousstructtanpainisialisasi vars1=struct{ person gradeint }{} //anonymousstructdenganinisialisasi vars2=struct{ person gradeint }{ person:person{"wick",21}, grade:2, } KombinasiSlice&Struct Slicedan structbisadikombinasikansepertipadaslicedan map,caranyapunmirip, cukuptambahkantanda []sebelumtipedatapadasaatdeklarasi. typepersonstruct{ namestring ageint } varallStudents=[]person{ {name:"Wick",age:23}, {name:"Ethan",age:23}, {name:"Bourne",age:22}, } for_,student:=rangeallStudents{ fmt.Println(student.name,"ageis",student.age) } InisialisasiLangsungSliceAnonymousStruct Anonymousstructbisadijadikansebagaitipesebuahslice.Dannilaiawalnyajugabisa diinisialisasilangsungpadasaatdeklarasi.Berikutadalahcontohnya: 102 Struct varallStudents=[]struct{ person gradeint }{ {person:person{"wick",21},grade:2}, {person:person{"ethan",22},grade:3}, {person:person{"bond",21},grade:3}, } for_,student:=rangeallStudents{ fmt.Println(student) } DeklarasiAnonymousStructMenggunakan Keywordvar Caralainuntukdeklarasianonymousstructadalahdenganmenggunakankeyword var. varstudentstruct{ person gradeint } student.person=person{"wick",21} student.grade=2 Statement typestudentstructadalahcontohbagaimanastructdideklrasikan.Maknanya akanberbedaketikakeyword typedisitudiganti var,sepertipadacontohdiatas var studentstruct,yangartinyaakandicetaksebuahobjekdarianonymousstructdan disimpanpadavariabelbernama student. Kelemahanmetodeini,nilaitidakbisadiinisialisasilangsungpadasaatdeklarasi. Contohnyabisadilihatpadakodedibawahini. //dekalrasisaja varstudentstruct{ gradeint } //dekalrasisekaligusinisialisasi varstudent=struct{ gradeint }{ 12 } 103 Struct Nestedstruct Nestedstructadalahanonymousstructyangdi-embedkesebuahstruct.Deklarasinya langsungdidalamstructpeng-embed.Contoh: typestudentstruct{ personstruct{ namestring ageint } gradeint hobbies[]string } Teknikinibiasadigunakanketikadecodingdatajsonyangstrukturdatanyacukupkompleks denganprosesdecodehanyasekali. DeklarasiDanInisialisasiStructSecara Horizontal Deklarasistructbisadituliskansecarahorizontal,caranyabisadilihatpadakodeberikut: typepersonstruct{namestring;ageint;hobbies[]string} Tandasemi-colon( ;)digunakansebagaipembatasdeklarasipopertyyangdituliskan secarahorizontal.Inisialisasinilaijugabisadituliskandenganmetodeini.Contohnya: varp1=struct{namestring;ageint}{age:22,name:"wick"} varp2=struct{namestring;ageint}{"ethan",23} BagipenggunaeditorSublimeyangterinstalpluginGoSublimedidalamnya,dekalrasi dengancarainitidakbisadilakukan,karenasetiapkalisaveisifileprogramakandirapikan. Jadiuntukmengetesnyabisadenganmenggunakaneditorlain. Tagpropertydalamstruct Tagmerupakaninformasiopsionalyangbisaditambahkanpadamasing-masingproperty struct.Carapenggunaannya: 104 Struct typepersonstruct{ namestring`tag1` ageint`tag2` } Tagbiasadimanfaatkanuntukkeperluanencode/decodedatajson.Informasitagjugabisa diakseslewatreflect.Nantinyaakanadapembahasanyanglebihdetailmengenai pemanfaatantagdalamstruct,yaituketikasudahmasukbabjson. 105 Method Method Methodadalahfungsiyanghanyabisadiakseslewatvariabelobjek.Methodmerupakan bagiandari struct. Keunggulanmethoddibandingfungsibiasaadalahmemilikiakseskepropertystructhingga levelprivate(levelaksesnantinyaakandibahaslebihdetailpadababselanjutnya).Dan juga,denganmenggunakanmethodsebuahprosesbisadi-enkapsulasidenganbaik. PenerapanMethod Caramenerapkanmethodsedikitberbedadibandingpenggunaanfungsi.Ketikadeklarasi, ditentukanjugasiapapemilikmethodtersebut.Contohnyabisadilihatpadakodeberikut: packagemain import"fmt" import"strings" typestudentstruct{ namestring gradeint } func(sstudent)sayHello(){ fmt.Println("halo",s.name) } func(sstudent)getNameAt(iint)string{ returnstrings.Split(s.name,"")[i-1] } Caradeklarasimethodsamasepertifungsi,hanyasajaperluditambahkandeklarasivariabel objekdisela-selakeyword funcdannamafungsi.Structyangdigunakanakanmenjadi pemilikmethod. func(sstudent)sayHello()maksudnyaadalahfungsi sayHellodideklarasikansebagai methodmilikstruct student.Padacontohdiatasstruct studentmemilikiduabuah method,yaitu sayHello()dan getNameAt(). Contohpemanfaatanmethodbisadilihatpadakodeberikut. 106 Method funcmain(){ vars1=student{"johnwick",21} s1.sayHello() varname=s1.getNameAt(2) fmt.Println("namapanggilan:",name) } Output: Caramengaksesmethodsamasepertipengaksesanpropertiberupavariabel.Tinggal panggilsajamethodnya. s1.sayHello() varname=s1.getNameAt(2) Methodmemilikisifatyangsamapersisdenganfungsibiasa.Sepertibisaberparameter, memilikinilaibalik,danlainnya.Darisegisintaks,pembedanyahanyaketikapengaksesan dandeklarasi.Bisadilihatdikodeberikut,sekilasperbandinganpenulisanfungsidan method. funcsayHello(){ func(sstudent)sayHello(){ funcgetNameAt(iint)string{ func(sstudent)getNameAt(iint)string{ MethodPointer Methodpointeradalahmethodyangvariabelobjeknyadideklarasikandalambentukpointer. Kelebihanmethodjenisiniadalahmanipulasidatapointerpadapropertymilikvariabel tersebutbisadilakukan. Pemanggilanmethodpointersamasepertimethodbiasa.Contohnyabisadilihatdikode berikut. 107 Method func(s*student)sayHello(){ fmt.Println("halo",s.name) } funcmain(){ vars1=student{"johnwick",21} s1.sayHello() } Methodpointertetapbisadiakseslewatvariabelobjekbiasa(bukanpointer)dengancara yangnyamasihsama.Contoh: //pengaksesanmethoddarivariabelobjekbiasa vars1=student{"johnwick",21} s1.sayHello() //pengaksesanmethoddarivariabelobjekpointer vars2=&student{"ethanhunt",22} s2.sayHello() Berikutadalahpenjelasantambahanmengenaifungsisplit. PenggunaanFungsi strings.Split() Dibabiniadafungsibaruyangkitagunakan: strings.Split().Fungsiinidigunakanuntuk memisahstringmenggunakanpemisahtertentu.Hasilnyaadalaharrayberisikankumpulan substringyangtelahdipisah. strings.Split("ethanhunt","") //["ethan","hunt"] Padacontohdiatas,string "ethanhunt"dipisahmenggunakanseparatorspasi "". Makahasilnyaterbentukarrayberisikan2data, "ethan"dan "hunt". Apakah fmt.Println()& strings.Split() JugaMerupakanMethod? Setelahtahuapaitumethoddanbagaimanapenggunaannya,mungkinakanmunculdi benakkitabahwakodeseperti fmt.Println(), strings.Split()danlainnya-yang-beradapada-package-lainjugamerupakanfungsi. 108 Method Tapisayangnyabukan. fmtdisitubukanlahvariabelobjek,dan Println()bukan merupakanmethod-nya. fmtadalahnamapackageyangdi-import(bisadilihatpadakode import"fmt"). Sedangkan Println()adalahnamafungsi.Untukmengaksesfungsiyangberadapada packagelain,harusdituliskannamapackage-nya.Haliniberlakujugadidalampackage main.Jikaadafungsidalampackagemainyangdiaksesdaripackagelainyangberbeda, makapenulisannya main.NamaFungsi(). Lebihdetailnyaakandibahasdibabselanjutnya. 109 PropertyPublic&Private PropertyPublicDanPrivate BabinimembahasmengenaimodifierpublicdanprivatedalamGolang.Kapansebuah struct,fungsi,ataumethodbisadiaksesdaripackagelaindankapantidak. PackagePublic&Private Pengembanganaplikasidalamrealdevelopmentpastimembutuhkanbanyaksekalifile program.Dantidakmungkinsemuanyadisetsebagaipackage main.Dengan pertimbangantersebutbiasanyafile-filetersebutdipisahsebagaipackagebaru. Folderproyekselainberisikanfile-file .gojugabisaberisikanfolder.Subfoldertersebut nantinyaakanmenjadipackagebaru.DiGolang,1subfolderadalah1package(kecuali packagemainyangberadalangsungdidalamfolderproyek).Menjadikanfileyangadadi dalamsuatufoldermemilikinamapackageberbedadengandifolderlainnya.Bahkanantara folderdansubfolderjugabisamemilikinamapackageyangberbeda. Fungsi,struct,danvariabelyangdibuatdipackagelain,jikadiaksesdaripackage main caranyatidaksepertibiasanya.Perluadanyapenentuanhakaksesyangtepat(apakah publicatauprivate)agarkodetidakkacaubalau.Packagepublic,berartibisadiaksesdari packageberbeda,sedangkanprivateberartihanyabisadiaksesdaripackageyangsama. Penentuanlevelaksesataumodifiersendiridigolangsangatmudah,ditandaidengan charactercasenamafungsi/struct/variabelyangingindiakses.Ketikanamanyadiawali denganhurufkapitalmenandakanbahwamodifier-nyapublic.Dansebaliknya,jikadiawali hurufkecil,berartiprivate. PenggunaanPackage,Import,DanModifier Public&Private Agarlebihmudahdipahami,makalangsungsajakitapraktekan. Pertamabuatfolderproyekbarubernama belajar-golang-level-aksesdalamfolder $GOPATH/src,lalubuatfilebarubernama main.godidalamnya.Fileinikitatentukan package-nyasebagaimain. Selanjutnyabuatfolderbarudidalamfolderyangsudahdibuatdengannama library, isinyasebuahfilebernama library.go.Fileiniditentukanpackage-nyaadalahlibrary. 110 PropertyPublic&Private Bukafile library.golaluisidengankodeberikut. packagelibrary import"fmt" funcSayHello(){ fmt.Println("hello") } funcintroduce(namestring){ fmt.Println("namasaya",name) } File library.goyangtelahdibuatditentukannamapackage-nyaadalah library(sesuai dengannamafolder).Dalampackagetersebutterdapatduafungsi: SayHello()dan introduce().Fungsi SayHello()adalahpublik,bisadiaksesdaripackagelain.Sedang fungsi introduce()adalahprivate,ditandaidenganhurufkecildihurufpertamanama fungsi. Selanjutnyaakandi-tesapakahmemangfungsiyangber-modifierprivatetidakbisadiakses daripackagelain.Bukafile main.go,lalutuliskodeberikut. packagemain import"belajar-golang-level-akses/library" funcmain(){ library.SayHello() library.introduce("ethan") } Packageyangtelahdibuatdi-importkedalampackage main.Padasaatimport,ditulis dengan "belajar-golang-level-akses/library"karenalokasifoldernyamerupakansubfolder dariproyek belajar-golang-level-akses.Denganinifungsi-fungsidalampackagetersebut bisadigunakan. 111 PropertyPublic&Private library.SayHello() library.introduce("ethan") Carapemanggilanfungsiyangberadadalampackagelainadalahdenganmenulisnama packagetargetdiikutdengannamafungsimenggunakandotnotationatautandatitik. OK,sekarangcobajalankankodeyangsudahdisiapkandiatas.Harusnyaakanadaerror sepertipadagambardibawahini. Errortersebutdisebabkankarenafungsi introduce()yangberadadipackage library adalahprivate,fungsijenisinitidakbisadiaksesdaripackagelain(padakasusini main). Agarfungsitersebutbisadiakses,solusinyabisadenganmenjadikannyapublic,ataudiubah carapemanggilannya.Disinikitamenggunakancarake-2. Tambahkanparameter namepadafungsi SayHello(),lalupanggilfungsi introduce() denganmenyisipkanparameter namedaridalamfungsi SayHello(). funcSayHello(namestring){ fmt.Println("hello") introduce(name) } Lalupadamain,cukuppanggilfungsi SayHello()saja,janganlupamenyisipkanpesan stringsebagaiparameter-nya. funcmain(){ library.SayHello("ethan") } Jikasudah,cobajalankanlagi,harusnyaerrorsudahlenyap. PenggunaanPublic&PrivatePadaStructDan Propertinya 112 PropertyPublic&Private Modifierprivate&publicbisaditerapkandifungsi,struct,method,maupunpropertyvariabel. Dancarapenggunaannyasamasepertipadacontohdiatas,yaitudenganmenentukan caseatauhurufpertamadarinama,apakahhuruftersebutbesarataukecil. BelajartentanglevelaksesdiGolangakanlebihcepatjikalangsungpraktek.Olehkarena itulangsungsajakitapraktekan.Hapusisifile library.go,lalusiapkanstructdengannama studentdidalamnya. packagelibrary typestudentstruct{ Namestring gradeint } Buatcontohsederhanapenerapanstructdiataspadafile main.go. packagemain import"belajar-golang-level-akses/library" import"fmt" funcmain(){ vars1=library.student{"ethan",21} fmt.Println("name",s1.Name) fmt.Println("grade",s1.grade) } Setelahitujalankanprogram. Errormunculketikaprogramdijalankan.Penyebabnyaadalahkarenastruct studentmasih disetsebagaiprivate.Gantimenjadipublic(dengancaramengubahhurufawalnyamenjadi hurufbesar)lalujalankan. //padalibrary/library.go typeStudentstruct{ //padamain.go vars1=library.Student{"ethan",21} 113 PropertyPublic&Private Errormasihtetapmuncul,tapikaliiniberbeda.Erroryangbaruinidisebabkankarenasalah satupropertidaristruct Studentbermodifierprivate.Propertiygdimaksudadalah grade. Ubahmenjadipublic,lalujalankanlagi. //padalibrary/library.go Gradeint //padamain.go fmt.Println("grade",s1.Grade) Daricontohprogramdiatas,bisadisimpulkanbahwauntukmenggunakan structyang beradadipackagelain,selainnamastuct-nyaharusbermodifierpublic,propertiyang diaksesjugaharuspublic. ImportDenganTandaTitik Sepertiyangkitatahu,untukmengaksesfungsi/struct/variabelygberadadipackagelain, namapackagenyaperluditulis,contohnyasepertipadapenggunaanpenggunaan library.Studentdan fmt.Println(). DiGolang,packagebisadi-importsetaradenganfilepeng-import,caranyadengan menambahkantitikpadasaatpenulisankeyword import.Maksuddarisetaradisiniadalah, semuapropertidipackagelainygdi-importbisadiaksestanpaperlumenuliskannama package,sepertiketikamengaksessesuatudarifileyangsama. import( ."belajar-golang-level-akses/library" "fmt" ) funcmain(){ vars1=Student{"ethan",21} fmt.Println("name",s1.Name) fmt.Println("grade",s1.Grade) } 114 PropertyPublic&Private Padakodediataspackage librarydi-importmenggunakantandatitik.Denganitu, pemanggilanstruct Studenttidakperludenganmenuliskannamapackagenya. PemanfaatanAliasKetikaImportPackage Fungsiyangberadadipackagelainbisadiaksesdengancaramenuliskannama-package diikutinamafungsi-nya,contohnyaseperti fmt.Println().Packageyangsudahdi-import tersebutbisadiubahnamanyadengancaramenggunakanaliaspadasaatimport. Contohnyabisadilihatpadakodeberikut. import( f"fmt" ) funcmain(){ f.Println("HelloWorld!") } Disiapkanaliasuntukpackage fmtdengannama f.Denganiniuntukmengaksesfungsi Println()cukupdengan f.Println(). MengaksesPropertiDalamFileYangPackagenyaSama Jikapropertiyangingindiaksesmasihdalamsatupackagetapifilenyasajaygberbeda, caramengaksesnyabisalangsungdenganmemanggilnamanya.Hanyasajaketika eksekusi,file-filelainyangyangnamapackage-nyasamajugaikutdipanggil. Langsungsajakitapraktekan,buatfilebarudalam belajar-golang-level-aksesdengan nama partial.go. File partial.goditentukanpackagenyaadalahmain(samadenganpackage main.go). Selanjutnyatuliskodeberikutpadafiletersebut. 115 PropertyPublic&Private packagemain import"fmt" funcsayHello(namestring){ fmt.Println("halo",name) } Hapussemuaisifile main.go,lalusilakantuliskodeberikut. packagemain funcmain(){ sayHello("ethan") } Sekarangterdapat2fileberbedayangpackage-nyasama-sama main,yaitu main.godan partial.go.Padasaatgobuildataugorun,semuafileyangnamapackage-nya main tersebutharusdituliskansebagaiargumen. $gorunmain.gopartial.go Fungsi sayHellopadafile partial.gobisadikenalimeskilevelaksesnyaadalahprivate. Halinikarenakeduafiletersebut( main.godan partial.go)memilikipackageyangsama. Fungsi init() Selainfungsi main(),terdapatjugafungsispesial,yaitu init().Fungsiiniakandipanggil pertamakaliketikapackage-dimana-fungsi-beradadi-import. Langsungsajakitapraktekkan.Bukafile library.go,laluisidengankodeberikut. 116 PropertyPublic&Private packagelibrary import"fmt" varStudent=struct{ Namestring Gradeint }{} funcinit(){ Student.Name="JohnWick" Student.Grade=2 fmt.Println("-->library/library.goimported") } Padapackagetersebut,variabel Studentdibuatdenganisianonymousstruct.Dalam fungsiinit,nilai Namedan Gradevariabeldi-set. Selanjutnyabukafile main.go,isidengankodeberikut. packagemain import"belajar-golang-level-akses/library" import"fmt" funcmain(){ fmt.Printf("Name:%s\n",library.Student.Name) fmt.Printf("Grade:%d\n",library.Student.Grade) } Package librarydi-import,danvariabel Studentdikonsumsi.Padasaatimportpackage, fungsi init()yangberadadidalamnyalangsungdieksekusi. Propertyvariabelobjek Studentakandiisidansebuahpesanditampilkankeconsole. Perludiketahuibahwadalamsebuahpackage,diperbolehkanadabanyakfungsi init() (urutaneksekusinyaadalahsesuaifilemanaygterlebihdahuludigunakan).Fungsiini dipanggilsebelumfungsi main(),padasaateksekusiprogram. 117 PropertyPublic&Private 118 Interface Interface Interfaceadalahkumpulandefinisimethodyangtidakmemilikiisi(hanyadefinisisaja),dan dibungkusdengannamatertentu. Interfacemerupakantipedata.Nilaiobjekbertipeinterfacedefault-nyaadalah nil. Interfacemulaibisadigunakanjikasudahadaisinya,yaituobjekkonkretyangmemiliki definisimethodminimalsamadenganyangadadiinterface-nya. PenerapanInterface Yangpertamaperludilakukanuntukmenerapkaninterfaceadalahmenyiapkaninterface barubesertadefinisimethodnya.Keyword typedan interfacedigunakandalam pembuatannya.Contoh: packagemain import"fmt" import"math" typehitunginterface{ luas()float64 keliling()float64 } Padakodediatas,interface hitungmemiliki2definisimethod, luas()dan keliling(). Interfaceininantinyadigunakansebagaitipedatavariabel,dimanavariabeltersebut digunakanuntukmenampungobjekbangundatarhasildaristructyangakankitabuat. Denganmemanfaatkanvariabelobjekhasilinterface hitung,perhitunganluasdankeliling suatubangundatarbisadilakukan,tanpaperlutahujenisbangundatarnyasendiriituapa. Selanjutnyadisiapkanstructbangundatar lingkaranyangmemilikimethodyangbeberapa diantaranyaterdefinisidiinterface hitung. 119 Interface typelingkaranstruct{ diameterfloat64 } func(llingkaran)jariJari()float64{ returnl.diameter/2 } func(llingkaran)luas()float64{ returnmath.Pi*math.Pow(l.jariJari(),2) } func(llingkaran)keliling()float64{ returnmath.Pi*l.diameter } Struct lingkarandiatasmemilikitigamethod, jariJari(), luas(),dan keliling(). Setelahitu,siapkanjugastructbangundatar persegi. typepersegistruct{ sisifloat64 } func(ppersegi)luas()float64{ returnmath.Pow(p.sisi,2) } func(ppersegi)keliling()float64{ returnp.sisi*4 } Perbedaanstruct persegidengan lingkaranterletakpadamethod jariJari().Struct persegitidakmemilikimethodtersebut.Tetapimeskidemikian,variabelobjekhasil cetakan2structiniakantetapbisaditampungolehvariabelcetakaninterface hitung, karenaduamethodyangter-definisidiinterfacetersebutjugaadapadastruct persegidan lingkaran,yaitu luas()dan keliling(). Terakhir,buatimplementasinyadi main. 120 Interface funcmain(){ varbangunDatarhitung bangunDatar=persegi{10.0} fmt.Println("=====persegi") fmt.Println("luas:",bangunDatar.luas()) fmt.Println("keliling:",bangunDatar.keliling()) bangunDatar=lingkaran{14.0} fmt.Println("=====lingkaran") fmt.Println("luas:",bangunDatar.luas()) fmt.Println("keliling:",bangunDatar.keliling()) fmt.Println("jari-jari:",bangunDatar.(lingkaran).jariJari()) } Perhatikankodediatas.Disiapkanvariabelobjek bangunDataryangtipe-nyainterface hitung.Variabeltersebutakandigunakanuntukmenampungobjekkonkritbuatanstruct lingkarandan persegi. Darivariabeltersebut,method luas()dan keliling()diakses.SecaraotomatisGolang akanmengarahkanpemanggilanmethodpadainterfacekemethodaslimilikstructyang bersangkutan. Method jariJari()padastruct lingkarantidakakanbisadiakseskarenatidakterdefinisi dalaminterface hitung.Pengaksesannyadenganpaksaakanmenyebabkanerror. Untukmengaksesmethodyangtidakter-definisidiinterface,variabel-nyaharusdi-casting terlebihdahuluketipeaslivariabelkonkritnya(padakasusinitipenya lingkaran), setelahnyamethodakanbisadiakses. Caracastingobjekinterfacesedikitunik,yaitudenganmenuliskannamatipetujuandalam kurung,ditempatkansetelahnamainterfacedenganmenggunakannotasititik(seperticara mengaksesproperty,hanyasajaadatandakurungnya).Contohnyabisadilihatdikode berikut.Statement bangunDatar.(lingkaran)adalahcontohcastingpadaobjekinterface. varbangunDatarhitung=lingkaran{14.0} varbangunLingkaranlingkaran=bangunDatar.(lingkaran) bangunLingkaran.jariJari() 121 Interface Perludiketahuijuga,jikaadainterfaceyangmenampungobjekkonkritdimanastruct-nya tidakmemilikisalahsatumethodyangterdefinisidiinterface,errorjugaakanmuncul.Intinya kembalikeaturanawal,variabelinterfacehanyabisamenampungobjekyangminimal memilikisemuamethodyangterdefinisidiinterface-nya. EmbeddedInterface Interfacebisadi-embedkeinterfacelain,samasepertistruct.Carapenerapannyajuga sama,cukupdenganmenuliskannamainterfaceyangingindi-embedkedalaminterface tujuan. Padacontohberikut,disiapkaninterfacebernama hitung2ddan hitung3d.Kedua interfacetersebutkemudiandi-embedkeinterfacebarubernama hitung. packagemain import"fmt" import"math" typehitung2dinterface{ luas()float64 keliling()float64 } typehitung3dinterface{ volume()float64 } typehitunginterface{ hitung2d hitung3d } Interface hitung2dberisikanmethoduntukkalkulasiluasdankeliling,sedang hitung3d berisikanmethoduntukmencarivolumebidang.Keduainterfacetersebutditurunkandi interface hitung,menjadikannyamemilikikemampuanuntukmenghitungluas,keliling,dan volume. Selanjutnyasiapkanstructbarubernama kubusyangmemilikimethod luas(), keliling(),dan volume(). 122 Interface typekubusstruct{ sisifloat64 } func(k*kubus)volume()float64{ returnmath.Pow(k.sisi,3) } func(k*kubus)luas()float64{ returnmath.Pow(k.sisi,2)*6 } func(k*kubus)keliling()float64{ returnk.sisi*12 } Objekhasilcetakanstruct kubusdiatas,nantinyaakanditampungolehobjekcetakan interface hitungyangisinyamerupakangabunganinterface hitung2ddan hitung3d. Selanjutnya,buatimplementasi-nyadimain. funcmain(){ varbangunRuanghitung=&kubus{4} fmt.Println("=====kubus") fmt.Println("luas:",bangunRuang.luas()) fmt.Println("keliling:",bangunRuang.keliling()) fmt.Println("volume:",bangunRuang.volume()) } Bisadilihatdikodediatas,lewatinterface hitung,method luas, keliling,dan volume bisadiakses. Padabab24dijelaskanbahwamethodpointerbisadiakseslewatvariabelobjekbiasadan variabelobjekpointer.Variabelobjekyangdicetakmenggunakanstructyangmemiliki methodpointer,jikaditampungkedalamvariabelinterface,harusdiambilreferensi-nya terlebihdahulu.Contohnyabisadilihatpadakodediatas varbangunRuanghitung= &kubus{4}. 123 Interface 124 InterfaceKosong InterfaceKosong Interfacekosongatau interface{}adalahtipedatayangsangatspesial.Variabelbertipe inibisamenampungsegalajenisdata,bahkanarray,bisapointerbisatidak(konsepini disebutdengandynamictyping). Penggunaan interface{} interface{}merupakantipedata,sehinggacarapenggunaannyasamasepertipadatipe datalainnya,hanyasajanilaiyangdiisikanbisaapasaja.Contoh: packagemain import"fmt" funcmain(){ varsecretinterface{} secret="ethanhunt" fmt.Println(secret) secret=[]string{"apple","manggo","banana"} fmt.Println(secret) secret=12.4 fmt.Println(secret) } Keyword interfacesepertiyangkitatau,digunakanuntukpembuataninterface.Tetapi ketikaditambahkankurungkurawal( {})dibelakang-nya(menjadi interface{}),maka kegunaannyaakanberubah,yaitusebagaitipedata. Agartidakbingung,cobaperhatikankodeberikut. 125 InterfaceKosong vardatamap[string]interface{} data=map[string]interface{}{ "name":"ethanhunt", "grade":2, "breakfast":[]string{"apple","manggo","banana"}, } Padakodediatas,disiapkanvariabel datadengantipe map[string]interface{},yaitu sebuahkoleksidengankeybertipe stringdannilaibertipeinterfacekosong interface{}. Kemudianvariabeltersebutdi-instansiasi,ditambahkanlagikurungkurawalsetelahkeyword deklarasiuntukkebutuhanpengisiandata, map[string]interface{}{/*data*/}. Darisituterlihatbahwa interface{}bukanlahsebuahobjek,melainkantipedata. CastingVariabelInterfaceKosong Variabelbertipe interface{}bisaditampilkankelayarsebagai stringdengan memanfaatkanfungsiprint,seperti fmt.Println().Tapiperludiketahuibahwanilaiyang dimunculkantersebutbukanlahnilaiasli,melainkanbentukstringdarinilaiaslinya. Halinipentingdiketahui,karenauntukmelakukanoperasiyangmembutuhkannilaiasli padavariabelyangbertipe interface{},diperlukancastingketipeaslinya.Contohseperti padakodeberikut. packagemain import"fmt" import"strings" funcmain(){ varsecretinterface{} secret=2 varnumber=secret.(int)*10 fmt.Println(secret,"multipliedby10is:",number) secret=[]string{"apple","manggo","banana"} vargruits=strings.Join(secret.([]string),",") fmt.Println(gruits,"ismyfavoritefruits") } 126 InterfaceKosong Pertama,variabel secretmenampungnilaibertipenumerik.Adakebutuhanuntuk mengalikannilaiyangditampungvariabeltersebutdenganangka 10.Makaperludilakukan castingketipeaslinya,yaitu int,setelahnyabarulahnilaibisadioperasikan,yaitu secret. (int)*10. Padacontohkedua, secretberisikanarraystring.Kitamemerlukanstringtersebutuntuk digabungkandenganpemisahtandakoma.Makaperludi-castingke []stringterlebih dahulusebelumbisadigunakandi strings.Join(),contohnyapada strings.Join(secret. ([]string),","). Teknikcastingpadainterfacedisebutdengantypeassertions. CastingVariabelInterfaceKosongKeObjek Pointer Variabel interface{}bisamenyimpandataapasaja,termasukdataobjek,pointer,ataupun gabungankeduanya.Dibawahinimerupakancontohpenerapaninterfaceuntuk menampungdataobjekpointer. typepersonstruct{ namestring ageint } varsecretinterface{}=&person{name:"wick",age:27} varname=secret.(*person).name fmt.Println(name) Variabel secretdideklarasikanbertipe interface{}menampungreferensiobjekcetakan struct person.Caracastingdari interface{}kestructpointeradalahdenganmenuliskan namastruct-nyadanditambahkantandaasterisk( *)diawal,contohnyaseperti secret. (*person).Setelahitubarulahnilaiaslibisadiakses. KombinasiSlice, map,dan interface{} 127 InterfaceKosong Kombinasidarislicedan map[string]interface{}mempunyaikemiripandengankombinasi slicedan struct.Silakanperhatikancontohberikut. Disiapkanvariabel person,menampungdata mapdengan2key,yaitu namedan age. varperson=[]map[string]interface{}{ {"name":"Wick","age":23}, {"name":"Ethan","age":23}, {"name":"Bourne","age":22}, } for_,each:=rangeperson{ fmt.Println(each["name"],"ageis",each["age"]) } Selainitu,denganmemanfaatkanslicedan interface{},kitabisamembuatdataarray yangisinyaadalahbisaapasaja.Silakanperhatikancontohpenggunaan []interface{} padakodeberikut. varfruits=[]interface{}{ map[string]interface{}{"name":"strawberry","total":10}, []string{"manggo","pineapple","papaya"}, "orange", } for_,each:=rangefruits{ fmt.Println(each) } 128 Reflect Reflect Reflectionadalahteknikuntukinspeksisebuahvariabel,mengambilinformasidarivariabel tersebutataubahkanmemanipulasinya.Cakupaninformasiyangbisadidapatkanlewat reflectionsangatluas,sepertimelihatstrukturvariabel,tipe,nilaipointer,danbanyaklagi. Golangmenyediakanpackagebernama reflect,berisikanbanyaksekalifungsiuntuk keperluanreflection.Dibabini,kitaakanbelajartentangdasarpenggunaanpackage tersebut. Daribanyakfungsiyangtersediadidalampackagetersebut,ada2fungsiyangpaling pentinguntukdiketahui,yaitu reflect.ValueOf()dan reflect.TypeOf(). Fungsi reflect.ValueOf()akanmengembalikanobjekdalamtipe reflect.Value,yang berisikaninformasiyangberhubungandengannilaipadavariabelyangdicari Sedangkan reflect.TypeOf()mengembalikanobjekdalamtipe reflect.Type.Objek tersebutberisikaninformasiyangberhubungandengantipedatavariabelyangdicari MencariTipeData&ValueMenggunakan Reflect Denganreflection,tipedatadannilaidarisuatuvariabeldapatdiketahuidenganmudah. Contohpenerapannyabisadilihatpadakodeberikut. packagemain import"fmt" import"reflect" funcmain(){ varnumber=23 varreflectValue=reflect.ValueOf(number) fmt.Println("tipevariabel:",reflectValue.Type()) ifreflectValue.Kind()==reflect.Int{ fmt.Println("nilaivariabel:",reflectValue.Int()) } } 129 Reflect Fungsi reflect.valueOf()memilikiparameteryangbisamenampungsegalajenistipedata. Fungsitersebutmengembalikanobjekdalamtipe reflect.Value,yangberisikaninformasi mengenaivariabelyangbersangkutan. Objek reflect.Valuememilikibeberapamethodyangbisadimanfaatkan.Salahsatunya adalah Type().Methodinimengembalikantipedatavariabelyangbersangkutandalam bentuk string. Statement reflectValue.Int()akanmenghasilkannilai intdarivariabeltersebut.Untuk menampilkannilaivariabelreflect,harusdipastikandulutipedatanya.Ketikatipedata adalah int,makabisamenggunakanmethod Int().Adabanyaklagimethodmilikstruct reflect.Valueyangbisadigunakanuntukpengambilannilaidalambentuktertentu, contohnya: reflectValue.String()digunakanuntukmengambilnilai string, reflectValue.Float64()untuknilai float64,danlainnya. Perludiketahui,fungsiyangdigunakanharussesuaidengantipedatanilaiyangditampung variabel.Jikafungsiyangdigunakanberbedadengantipedatavariabelnya,makaakan menghasilkanerror.Contohnyapadavariabelmenampungnilaibertipe float64,maka tidakbisamenggunakanmethod String(),karenajikadipaksa,akanmunculerror. Diperlukanadanyapengecekantipedatanilaiyangdisimpan,agarpengambilannilaibisa tepat.Salahsatunyabisadengancarasepertikodediatas,yaitudenganmengecekdahulu apajenistipedatanyamenggunakanmethod Kind(),setelahitudiambilnilainyadengan methodyangsesuai. Berikutadalahkonstantatipedatadanmethodyangbisadigunakandalamrefleksidi Golang. Bool Int Int8 Int16 Int32 Int64 Uint Uint8 Uint16 Uint32 Uint64 Uintptr 130 Reflect Float32 Float64 Complex64 Complex128 Array Chan Func Interface Map Ptr Slice String Struct UnsafePointer PengaksesanNilaiDalamBentuk interface{} Jikanilaihanyadiperlukanuntukditampilkankeoutput,menggunakan .Interface()akan mempersingkatwaktu.Leweatmethodtersebutsegalajenisnilaiakanbisadiaksesdengan mudah. varnumber=23 varreflectValue=reflect.ValueOf(number) fmt.Println("tipevariabel:",reflectValue.Type()) fmt.Println("nilaivariabel:",reflectValue.Interface()) Fungsi Interface()mengembalikannilaiinterfacekosongatau interface{}.Nilaiaslinya sendiribisadiaksesdenganmeng-castinginterfacekosongtersebut. varnilai=reflectValue.Interface().(int) PengaksesanInformasiPropertyVariabel Objek Reflectbisadigunakanuntukmengambilinformasisemuapropertyvariabelobjekcetakan struct,dengancatatanproperty-propertytersebutbermodifierpublic.Agarlebihmudah dipahami,langsungsajakitapraktekan. 131 Reflect Siapkansebuahstructbernama student. typestudentstruct{ Namestring Gradeint } Setelahitu,buatmethodbaruuntukstructtersebut,dengannamamethod getPropertyInfo().Methodiniberisikankodeuntukmengambildanmenampilkaninformasi tiappropertymilikstruct student. func(s*student)getPropertyInfo(){ varreflectValue=reflect.ValueOf(s) ifreflectValue.Kind()==reflect.Ptr{ reflectValue=reflectValue.Elem() } varreflectType=reflectValue.Type() fori:=0;i<reflectValue.NumField();i++{ fmt.Println("nama:",reflectType.Field(i).Name) fmt.Println("tipedata:",reflectType.Field(i).Type) fmt.Println("nilai:",reflectValue.Field(i).Interface()) fmt.Println("") } } Terakhir,lakukanujicobamethoddifungsimain. funcmain(){ vars1=&student{Name:"wick",Grade:2} s1.getPropertyInfo() } Didalammethod getPropertyInfoterjadibeberapahal.Pertamaobjek reflect.Valuedari variabel sdiambil.Setelahitudilakukanpengecekkanapakahvariabelobjektersebut merupakanpointeratautidak(bisadilihatdari ifreflectValue.Kind()==reflect.Ptr).jika iya,makaperludicariobjekreflectaslinyadengancaramemanggilmethod Elem(). 132 Reflect Setelahitu,dilakukanperulangansebanyakjumlahpropertyyangadapadastruct student. Method NumField()akanmengembalikanjumlahpropertypublikyangadadalamstruct. Ditiapperulangan,informasitiappropertystructdiambilberurutandenganlewatmethod Field().Methodiniadapadatipe reflect.Valuedan reflect.Type. reflectType.Field(i).Nameakanmengembalikannamaproperty reflectType.Field(i).Typemengembalikantipedataproperty reflectValue.Field(i).Interface()mengembalikannilaipropertydalambentuk interface{} Pengambilaninformasiproperty,selainmenggunakanindeks,bisadiambilberdasarkan namafielddenganmenggunakanmethod FieldByName(). PengaksesanInformasiMethodVariabelObjek Methodjugabiasdiakseslewatreflect,syaratnyamasihsamasepertipadapengaksesan proprerty,yaituharusbermodifierpublic. Langsungsajakitapraktekkan.Padacontohdibawahiniinformasimethod SetNameakan diambillewatreflection. Siapkanmethodbarudistruct student,dengannama SetName. func(s*student)SetName(namestring){ s.Name=name } Buatcontohpenerapannyadifungsi main. funcmain(){ vars1=&student{Name:"johnwick",Grade:2} fmt.Println("nama:",s1.Name) varreflectValue=reflect.ValueOf(s1) varmethod=reflectValue.MethodByName("SetName") method.Call([]reflect.Value{ reflect.ValueOf("wick"), }) fmt.Println("nama:",s1.Name) } 133 Reflect Padakodediatas,disiapkanvariabel s1yangmerupakaninstancestruct student. Awalnyaproperty Namevariabeltersebutberisikanstring "johnwick". Setelahitu,refleksinilaiobjektersebutdiambil,refleksimethod-nya( SetName)jugadiambil. Pengambilanrefleksimethodbisalewatnamamethod-nya(menggunakan MethodByName) ataulewatindeksmethod-nya(menggunakan Method(i)). Setelahrefleksimethodyangdicarisudahdidapatkan, Call()dipanggiluntuk pengeksekusianmethod. Jikaeksekusimethoddiikutipengisianparameter,makaparameternyaharusditulisdalam bentukarray []reflect.Valueberurutansesuaiurutandeklarasiparameter-nya.Dannilai yangdimasukkankearraytersebutharusdalambentuk reflect.Value(gunakan reflect.ValueOf()untukpengambilannya). []reflect.Value{ reflect.ValueOf("wick"), } 134 Goroutine Goroutine Goroutinebukanlahthread.Sebuahnativethreadbisaberisikansangatbanyakgoroutine. Mungkinlebihpaskalaugoroutinedisebutsebagaiminithread.Goroutinesangatringan, hanyadibutuhkansekitar2kBmemorisajauntuksatubuahgoroutine.Ekseksuigoroutine bersifatasynchronous,menjadikannyatidaksalingtunggudengangoroutinelain. PenerapanGoroutine Untukmenerapkangoroutine,prosesyangakandieksekusisebagaigoroutineharus dibungkuskedalamfungsi.Padasaatpemanggilanfungsitersebut,ditambahkankeyword godidepannya.Dengandemikianprosesyangadadalamfungsitersebutdideteksi sebagaigoroutinebaru. Berikutmerupakancontohimplementasisederhanatentanggoroutine.Programdibawahini menampilkan10baristeks,5dieksekusidengancarabiasa,dan5lainnyadieksekusi sebagaigoroutinebaru. packagemain import"fmt" import"runtime" funcprint(tillint,messagestring){ fori:=0;i<till;i++{ fmt.Println((i+1),message) } } funcmain(){ runtime.GOMAXPROCS(2) goprint(5,"halo") print(5,"apakabar") varinputstring fmt.Scanln(&input) } Padakodediatas, runtime.GOMAXPROCS(n)digunakanuntukmenentukanjumlahprosesor yangaktif. 135 Goroutine Pembuatangoroutinebaruditandaidengankeyword go.Contohnyapadastatement go print(5,"halo"),disitufungsi print()dieksekusisebagaigoroutinebaru. Fungsi fmt.Scanln()mengakibatkanprosesjalannyaaplikasiberhentidibarisitu (blocking)hinggausermenekantombolenter.Haliniperludilakukankarenaada kemungkinanwaktuselesainyaeksekusigoroutine print()lebihlamadibandingwaktu selesainyagoroutineutama main(),mengingatbahwakeduanyasama-sama asnychronous.Jikaituterjadi,goroutineyangbelumselesaisecarapaksadihentikan prosesnyakarenagoroutineutamasudahselesaidijalankan. Bisadilihatdioutput,tulisan "halo"dan "apakabar"bermunculanselang-seling.Ini disebabkankarenastatement print(5,"halo")dijalankansebagaigoroutinebaru, menjadikannyatidaksalingtunggudengan print(5,"apakabar"). Padagambardiatas,programdieksekusi2kali.Hasileksekusipertamaberbedadengan kedua,penyebabnyaadalahkarenakitamenggunakan2prosesor.Goroutinemanayang dieksekusiterlebihdahulutergantungkeduaprosesortersebut. Berikutadalahpenjelasantambahantentangbeberapafungsiyangbarukitapelajaridiatas. PenggunaanFungsi runtime.GOMAXPROCS() Fungsiinidigunakanuntukmenentukanjumlahprosesoryangdigunakandalameksekusi program. 136 Goroutine Jumlahprosesoryangdiinputkansecaraotomatisakandisesuaikandenganjumlahasli logicalprocessoryangada.Jikaangkaygdiinputkanadalahlebih,makadianggap menggunakansemuaprosesoryangada. PenggunaanFungsi fmt.Scanln() Fungsiiniakanmeng-capturesemuakaraktersebelumusermenekantombolenter,lalu menyimpannyapadavariabel. funcScanln(a...interface{})(nint,errerror) Kodediatasmerupakanskemafungsi fmt.Scanln().Fungsitersebutbisamenampung parameterbertipe interface{}berjumlahtakterbatas.Tiapparameterakanmenampung karakter-karakterinputanuseryangsudahdipisahdengantandaspasi.Agarlebihjelas, silakanperhatikancontohberikut. vars1,s2,s3string fmt.Scanln(&s1,&s2,&s3) //userinputs:"trafalgardlaw" fmt.Println(s1)//trafalgar fmt.Println(s2)//d fmt.Println(s3)//law Bisadilihatpadakodediatas,untukmenampunginputantext trafalgardlaw,dibutuhkan 3buahvariabel.Jugaperludiperhatikanbahwayangdisisipkansebagaiparameterpada pemanggilanfungsi fmt.Scanln()adalahreferensivariabel,bukannilaiaslinya. 137 Channel Channel Channeldigunakanuntukmenghubungkangorutinesatudengangoroutinelainnya. Mekanismenyaadalahdengancaraserah-terimadatalewatchanneltersebut.Goroutine pengirimdanpenerimaharusberadapadachannelyangberbeda(konsepinidisebut bufferedchannel).Pengirimandanpenerimaandatapadachannelbersifatblockingatau synchronous. Padababinikitaakanbelajarmengenaipemanfaatanchannel. PenerapanChannel Channelmerupakansebuahvariabel,dibuatdenganmenggunakankeyword makedan chan.Variabelchannelmemilikitugasmenjadipengirimdanpenerimadata. Programberikutadalahcontohimplementasichannel.3buahgoroutinebarudieksekusi, yangdimasing-masinggoroutineterdapatprosespengirimandatalewatchannel.Data tersebutakanditerima3kalidigoroutineutama( main). 138 Channel packagemain import"fmt" import"runtime" funcmain(){ runtime.GOMAXPROCS(2) varmessages=make(chanstring) varsayHelloTo=func(whostring){ vardata=fmt.Sprintf("hello%s",who) messages<-data } gosayHelloTo("johnwick") gosayHelloTo("ethanhunt") gosayHelloTo("jasonbourne") varmessage1=<-messages fmt.Println(message1) varmessage2=<-messages fmt.Println(message2) varmessage3=<-messages fmt.Println(message3) } Padakodediatas,variabel messagesdideklarasikanbertipe channelstring.Cara pembuatanchannelyaitudenganmenuliskankeyword makedenganisikeyword chan diikutidengantipedatachannelyangdiinginkan. varmessages=make(chanstring) Selainitudisiapkanjugaclosure sayHelloToyangmenghasilkandatastring.Datatersebut kemudiandikirimlewatchannel messages.Tanda <-jikadituliskandisebelahkirinama variabel,berartisedangberlangsungprosespengirimandatadarivariabelyangberadadi kananlewatchannelyangberadadikiri(padakonteksini,variabel datadikirimlewat channel messages). varsayHelloTo=func(whostring){ vardata=fmt.Sprintf("hello%s",who) messages<-data } 139 Channel Fungsi sayHelloTodieksekusitigakalisebagaigoroutineberbeda.Menjadikantigaproses iniberjalansecaraasynchronousatautidaksalingtunggu. gosayHelloTo("johnwick") gosayHelloTo("ethanhunt") gosayHelloTo("jasonbourne") Dariketigafungsitersebut,goroutineyangpalingawalmengirimdata,akanditerima datanyaolehvariabel message1.Tanda <-jikadituliskandisebelahkananchannel, menandakanprosespenerimaandatadarichannelyangdikanan,untukdisimpanke variabelyangdikiri. varmessage1=<-messages fmt.Println(message1) Penerimaanchannelbersifatblocking.Artinyastatement varmessage1=<-messageshingga setelahnyatidakakandieksekusisebelumadadatayangdikirimlewatchannel. Ketigagoroutinetersebutdatanyaakanditerimasecaraberurutanoleh message1, message2, message3;untukkemudianditampilkan. Dariscreenshotoutputdiatasbisadilihatbahwatextyangdikembalikanoleh sayHelloTo tidakselaluberurutan,meskipunpenerimaandatanyaadalahberurutan.Halinidikarenakan, pengirimandataadalahdari3goroutineyangberbeda,yangkitatidaktaumanayang dieksekusiterlebihdahulu.Goroutineyangdieksekusilebihawal,datanyaakanditerima lebihawal. Karenapengirimandanpenerimaandatalewatchannelbersifatblocking,tidakperlu memanfaatkansifatblockingdarifungsi fmt.Scanln()untukmengantisipasigoroutine utamaselesailebihdulu. ChannelSebagaiTipeDataParameter 140 Channel Variabelchannelbisadi-passingkefungsilainsebagaiparameter.Caranyadengan menambahkankeyword chanketikadeklarasinya. Langsungsajakitapraktekan.Siapkanfungsi printMessagedenganparameteradalah channel.Laluambildatayangdikirimkanlewatchanneltersebutuntukditampilkan. funcprintMessage(whatchanstring){ fmt.Println(<-what) } Setelahituubahimplementasidifungsi main. funcmain(){ runtime.GOMAXPROCS(2) varmessages=make(chanstring) for_,each:=range[]string{"wick","hunt","bourne"}{ gofunc(whostring){ vardata=fmt.Sprintf("hello%s",who) messages<-data }(each) } fori:=0;i<3;i++{ printMessage(messages) } } Parameter whatfungsi printMessagebertipechannelstring,bisadilihatdarikode chan stringpadacaradeklarasinya.Operasiserah-terimadataakanbisadilakukanpada variabeltersebut,danakanberdampakjugapadavariabel messagesdifungsi main. Passingdatabertipechannellewatparametersecaraimplisitadalahpassbyreference, yangdi-passingadalahpointer-nya.Outputprogramdiatasadalahsamadenganprogram sebelumnya. Berikutmerupakanpenjelasantambahankodediatas. 141 Channel IterasiDataArrayLangsungPadaSaat Inisialisasi Dataarrayyangbarudi-inisialisasibisalangsungdi-iterasi,caranyamudahdengan menuliskanyalangsungsetelahkeyword range. for_,each:=range[]string{"wick","hunt","bourne"}{ //... } EksekusiGoroutinePadaIIFE Eksekusigoroutinetidakharuspadafungsiatauclosureyangsudahterdefinisi.SebuahIIFE jugabisadijalankansebagaigoroutinebaru.Caranyadenganlangsungmenambahkan keyword gopadawaktudeklarasi-eksekusiIIFE-nya. varmessages=make(chanstring) gofunc(whostring){ vardata=fmt.Sprintf("hello%s",who) messages<-data }("wick") varmessage=<-messages fmt.Println(message) 142 BufferedChannel BufferedChannel Channelsecaradefaultadalahun-buffered,tidakdi-bufferdimemori.Ketikaadagoroutine yangmengirimkandatalewatchannel,harusadagoroutinelainyangbertugasmenerima datadarichannelyangsama,denganprosesserah-terimayangbersifatblocking. Maksudnya,bariskodedibagianpengirimandanpenerimaandata,tidakakanakan diprosessebelumprosesserah-terima-nyaselesai. Bufferedchannelsedikitberbeda.Padachanneljenisini,ditentukanjumlahbuffer-nya. Angkatersebutakanmenjadipenentukapankitabisamengirimkandata.Selamajumlah datayangdikirimtidakmelebihijumlahbuffer,makapengirimanakanberjalan asynchronous(tidakblocking). Ketikajumlahdatayangdikirimsudahmelewatibatasbuffer,makapengirimandatahanya bisadilakukanketikasalahsatudatasudahdiambildarichannel,sehinggaadaslotchannel yangkosong.Denganprosespenerimaan-nyasendiribersifatblocking. PenerapanBufferedChannel Penerapanbufferedchannelpadadasarnyamiripsepertichannelbiasa.Perbedannyapada channeljenisiniperludisiapkanjumlahbuffer-nya. Berikutadalahcontohpenerapanbufferedchannel.Programdibawahinimerupakan pembuktianbahwapengirimandatalewatbufferedchanneladalahasynchronousselama jumlahdatayangsedangdi-bufferolehchanneltidakmelebihikapasitasbuffernya. 143 BufferedChannel packagemain import"fmt" import"runtime" funcmain(){ runtime.GOMAXPROCS(2) messages:=make(chanint,2) gofunc(){ for{ i:=<-messages fmt.Println("receivedata",i) } }() fori:=0;i<5;i++{ fmt.Println("senddata",i) messages<-i } } Padakodediatas,parameterkeduafungsi makeadalahrepresentasijumlahbuffer-nya. Perludiperhatikanbahwanilaibufferedchanneldimulaidari 0.Ketikanilainyaadalah2, brartijumlahbuffermaksimalada3(0,1,dan2). Padacontohdiatas,terdapatjugasebuahgoroutineyangberisikanprosespenerimaan datadarichannelmessage,yangselanjutnyaakanditampilkan. Setelahgoroutineuntukpenerimaandatadieksekusi,datadikirimkanlewatperulangan for.Sejumlah5dataakandikirimlewatchannel messagesecarasekuensial. 144 BufferedChannel Bisadilihathasilnyapadaoutputdiatas.Pengirimandatake-4,diikutidenganpenerimaan data,dankeduaprosestersebutberjalansecarablocking. Pengirimandatake0,1,2dan3akanberjalansecaraasynchronous,halinikarenachannel ditentukannilaibuffer-nyasebanyak3(ingat,dimulaidari0).Pengirimanselanjutnya(ke-4 danke-5)hanyaakanterjadijikaadasalahsatudatadari4datayangsebelumnyatelah dikirimkan,sudahditerima(denganserahterimadatayangbersifatblocking).Setelahnya, sesudahslotchanneladayangkosong,serah-terimaakankembaliasynchronous. 145 Channel-Select Channel-Select Adanyachannelmemangsangatmembantupengontrolangoroutine,jumlahgoroutineyang banyakbukanlagimasalah. Adakalanyadimanakitabutuhtakhanyasatuchannelsajauntukmanagegoroutineyang jugabanyak,dibutuhkanbeberapaataumungkinbanyakchannel. Disinilahkegunaandari select.Selectmemudahkanpengontrolankomunikasidatalewat channel.Carapenggunaannyasamasepertiseleksikondisi switch. PenerapanKeyword select Programpencarianrata-ratadannilaitertinggiberikutmerupakancontohsederhana penerapanselectdalamchannel.Akanada2buahgoroutineyangmasing-masingdi-handle olehsebuahchannel.Setiapkaligoroutineselesaidieksekusi,akandikirimkandatanyake channelyangbersangkutan.Laludenganmenggunakanselect,akandikontrolpenerimaan datanya. Pertama,kitasiapkanterlebihdahulu2fungsiyangakandieksekusisebagaigoroutinebaru. Fungsipertamadigunakanuntukmencarirata-rata,danfungsikeduauntukpenentuannilai tertinggidarisebuahslice. 146 Channel-Select packagemain import"fmt" import"runtime" funcgetAverage(numbers[]int,chchanfloat64){ varsum=0 for_,e:=rangenumbers{ sum+=e } ch<-float64(sum)/float64(len(numbers)) } funcgetMax(numbers[]int,chchanint){ varmax=numbers[0] for_,e:=rangenumbers{ ifmax<e{ max=e } } ch<-max } Keduafungsidiatasakandieksekusididalam mainsebagaigoroutinebaru.Diakhir masing-masingfungsiakandikirimkandatahasilkomputasikechannelyangsudah ditentukan( ch1menampungdatarata-rata, ch2untukdatanilaitertinggi). Setelahitu,buatimplementasinyapadafungsi main. 147 Channel-Select funcmain(){ runtime.GOMAXPROCS(2) varnumbers=[]int{3,4,3,5,6,3,2,2,6,3,4,6,3} fmt.Println("numbers:",numbers) varch1=make(chanfloat64) gogetAverage(numbers,ch1) varch2=make(chanint) gogetMax(numbers,ch2) fori:=0;i<2;i++{ select{ caseavg:=<-ch1: fmt.Printf("Avg\t:%.2f\n",avg) casemax:=<-ch2: fmt.Printf("Max\t:%d\n",max) } } } Padakodediatas,transaksipengirimandatapadachannel ch1dan ch2dikontrol menggunakan select.Terdapat2buah casekondisipenerimaandatadarikeduachannel tersebut. Kondisi caseavg:=<-ch1akanterpenuhiketikaadapenerimaandatadarichannel ch1,yangkemudianakanditampungolehvariabel avg. Kondisi casemax:=<-ch2akanterpenuhiketikaadapenerimaandatadarichannel ch2,yangkemudianakanditampungolehvariabel max. Karenaada2buahchannel,makaperludisiapkanperulangan2kalisebelumpenggunaan keyword select. Cukupmudahbukan? 148 Channel-Range&Close Channel-RangedanClose Penerimaandatalewatchannelyangdipakaiolehbanyakgoroutine,akanlebihmudah denganmemanfaatkankeyword for- range. for- rangejikaditerapkanpadachannel,akanmelakukanperulangantanpahenti. Perulangantersebuttetapberjalanmeskitidakadatransaksipadachannel,danhanyaakan berhentijikastatuschannelberubahmenjadiclosedatausudahditutup.Fungsi close digunakanutukmenutupchannel. Channelyangsudahditutuptidakbisadigunakanlagiuntukmenerimamaupunmengirim data.Menjadikanpenerimaandatamenggunakan for- rangejugaikutberhenti. Penerapan for- range- closePada Channel Berikutadalahcontohprogramyangmenggunakan for- rangeuntukpengambilandata darichannel. Pertamasiapkanfungsi sendMessage()untukhandlepengirimandata.Didalamfungsiini akandijalankanperulangansebanyak20kali,ditiapperulangannyadatadikirimlewat channel.Setelahsemuadataterkirim,channeldi-close. funcsendMessage(chchan<-string){ fori:=0;i<20;i++{ ch<-fmt.Sprintf("data%d",i) } close(ch) } Siapkanjugafungsi printMessage()untukhandlepenerimaandata.Didalamnya,channel akandi-loopingmenggunakan for- range,yangkemudianditampilkandata-nya. funcprintMessage(ch<-chanstring){ formessage:=rangech{ fmt.Println(message) } } 149 Channel-Range&Close Batchannelbarudifungsi main,jalankan sendMessage()sebagaigoroutine.Jalankanjuga printMessage().Denganini20datadikirimkanlewatgoroutinebaru,dannantinyaditerima digoroutineutama. funcmain(){ runtime.GOMAXPROCS(2) varmessages=make(chanstring) gosendMessage(messages) printMessage(messages) } Setelah20datasuksesdikirimdanditerima,channel chakandimatikan( close(ch)). Membuatperulangandatachanneldalam printMessage()jugaakanberhenti. ChannelDirection AdayangunikdenganfiturparameterchannelyangdisediakanGolang.Levelakses channelbisaditentukan,apakahhanyasebagaipenerima,pengirim,ataupenerima sekaliguspengirim.Konsepinidisebutdenganchanneldirection. Carapemberianlevelaksesadalahdenganmenambahkantanda <-sebelumatausetelah keyword chan.Untuklebihjelasnyabisadilihatdilistberikut. 150 Channel-Range&Close Sintaks Penjelasan chchanstring Parameter chbisadigunakanuntukmengirimdanmenerima data chchan<string Parameter chhanyabisadigunakanuntukmengirimdata ch<-chan string Parameter chhanyabisadigunakanuntukmenerimadata Padakodediatasbisadilihatbahwasecaradefaultchannelakanmemilikikemampuan untukmengirimdanmenerimadata.Untukmengubahchanneltersebutagarhanyabisa mengirimataumenerimasaja,denganmemanfaatkansimbol <-. Sebagaicontohfungsi sendMessage(chchan<-string)yangparameter chdideklarasikan denganlevelaksesuntukpengirimandatasaja.Channeltersebuthanyabisadigunakan untukmengirim,contohnya: ch<-fmt.Sprintf("data%d",i). Dansebaliknyapadafungsi printMessage(ch<-chanstring),channel chhanyabisa digunakanuntukmenerimadatasaja. 151 Channel-Timeout Channel-Timeout Timeoutdigunakanuntukmengontrolpenerimaandatadarichannelberdasarkanwaktu diterimanya,dengandurasitimeoutbisaditentukansendiri. Ketikatidakadaaktivitaspenerimaandataselamadurasitersebut,akanmemicucallback yangisinyajugaditentukansendiri. PenerapanChannelTimeout Berikutadalahprogramsederhanatentangpengaplikasiantimeoutpadachannel.Sebuah goroutinebarudijalankandengantugasmengirimkandatasetiapintervaltertentu,dengan durasiinterval-nyaadalahacak/random. packagemain import"fmt" import"math/rand" import"runtime" import"time" funcsendData(chchan<-int){ fori:=0;true;i++{ ch<-i time.Sleep(time.Duration(rand.Int()%10+1)*time.Second) } } Selanjutnya,disiapkanperulangantanpahenti,yangditiapperulangannyaadaseleksi kondisichannelmenggunakan select. funcretreiveData(ch<-chanint){ loop: for{ select{ casedata:=<-ch: fmt.Print(`receivedata"`,data,`"`,"\n") case<-time.After(time.Second*5): fmt.Println("timeout.noactivitiesunder5seconds") breakloop } } } 152 Channel-Timeout Ada2blokkondisipada selecttersebut. casedata:=<-messages:,akanterpenuhiketikaadaserahterimadatapadachannel messages case<-time.After(time.Second*5):,akanterpenuhiketikatidakadaaktivitas penerimaandatadarichanneldalamdurasi5detik. Terakhir,keduafungsitersebutdipanggildi main. funcmain(){ rand.Seed(time.Now().Unix()) runtime.GOMAXPROCS(2) varmessages=make(chanint) gosendData(messages) retreiveData(messages) } Akanmunculoutputsetiapkaliadapenerimaandatadengandelaywaktuacak.Ketikatidak adaaktifitaspadachanneldalamdurasi5detik,perulanganpengecekkanchannelakan dihentikan. 153 Defer&Exit Defer&Exit Deferdigunakanuntukmengakhirkaneksekusisebuahstatement.SedangkanExit digunakanuntukmenghentikanprogram.2topikinisengajadigabungagarhubunganantara keduanyalebihmudahdipahami. Penerapankeyword defer Sepertiyangsudahdijelaskansecarasingkatdiatas,bahwadeferdigunakanuntuk mengakhirkaneksekusibariskode.Ketikaeksekusisudahsampaipadaakhirblokfungsi, statementyangdideferbaruakandijalankan. Deferbisaditempatkandimanasaja,awalmaupunakhirblok. packagemain import"fmt" funcmain(){ deferfmt.Println("halo") fmt.Println("selamatdatang") } Keyword deferdigunakanuntukmengakhirkanstatement.Padakodediatas, fmt.Println("halo")di-defer,hasilnyastring "halo"akanmunculsetelah "selamat datang". Ketikaadabanyakstatementyangdi-defer,makastatementtersebutakandieksekusidi akhirsecaraberurutan. PenerapanFungsi os.Exit() Exitdigunakanuntukmenghentikanprogramsecarapaksapadasaatitujuga.Semua statementsetelahexittidakakandieksekusi,termasukjugadefer. 154 Defer&Exit Fungsi os.Exit()beradadalampackage os.Fungsiinimemilikisebuahparameter bertipenumerikyangwajibdiisi.Angkayangdimasukkanakanmunculsebagaiexitstatus ketikaprogramberhenti. packagemain import"fmt" import"os" funcmain(){ deferfmt.Println("halo") os.Exit(1) fmt.Println("selamatdatang") } Meskipun deferfmt.Println("halo")ditempatkansebelum os.Exit(),statementtersebut tidakakandieksekusi,karenadi-tengahfungsiprogramdihentikansecarapaksa. 155 Error&Panic Error&Panic Errormerupakantopikyangpentingdalampemrogramangolang.Dibagianinikitaakan belajarmengenaipemanfaatanerrordancaramembuatcustomerrorsendiri. Kitajugaakanbelajartentangpenggunaanpanicuntukmenampilkanpesanerror. PemanfaatanError errormerupakansebuahtipe.Errormemilikibeberapapropertyyangmenampung informasiyangberhubungandenganerroryangbersangkutan. Digolang,banyaksekalifungsiyangmengembalikannilaibaliklebihdarisatu.Biasanya, salahsatukembalianadalahbertipe error.Contohnyasepertipadafungsi strconv.Atoi(). strconv.Atoi()bergunauntukmengkonversidatastringmenjadinumerik.Fungsiini mengembalikan2nilaibalik.Nilaibalikpertamaadalahhasilkonversi,dannilaibalikkedua adalah error. Ketikakonversiberjalanmulus,nilaibalikkeduaakanbernilai nil.Sedangkanketika konversigagal,kitabisalangsungtaupenyebaberrormunculdenganmemanfaatkannilai balikkedua. Berikutmerupakancontohprogramsederhanauntukdeteksiinputandariuser,apakah numerikataubukan. 156 Error&Panic packagemain import( "fmt" "strconv" ) funcmain(){ varinputstring fmt.Print("Typesomenumber:") fmt.Scanln(&input) varnumberint varerrerror number,err=strconv.Atoi(input) iferr==nil{ fmt.Println(number,"isnumber") }else{ fmt.Println(input,"isnotnumber") fmt.Println(err.Error()) } } Ketikaprogramdijalankan,akanmuncultulisan "Typesomenumber:".Ketiksebuahangka laluenter. fmt.Scanln(&input)akanmengambilinputanyangdiketikusersebelumdiamenekanenter, lalumenyimpannyasebagaistringkevariabel input. Selanjutnyavariabeltersebutdikonversiketipenumerikmenggunakan strconv.Atoi(). Fungsitersebutmengembalikan2data,yangkemudianakanditampungoleh numberdan err. Datapertama( number)akanberisihasilkonversi.Dandatakedua err,akanberisi informasierrornya(jikamemangterjadierrorketikaproseskonversi). Setelahitudilakukanpengecekkan,ketikatidakadaerror, numberditampilkan.Danjikaada error, inputditampilkanbesertapesanerrornya. Pesanerrorbisadidapatdarimethod Error()miliktipe error. 157 Error&Panic MembuatCustomError Selainmemanfaatkanerrorhasilkembalianfungsi,kitajugabisamembuaterrorsendiri denganmenggunakanfungsi errors.New(untukmenggunakannyaharusimportpackage errorsterlebihdahulu). Berikutmerupakancontohpembuatancustomerror.Pertamasiapkanfungsidengannama validate(),yangnantinyadigunakanuntukpengecekaninput,apakahinputankosong atautidak.Ketikakosong,makaerrorbaruakandibuat. packagemain import( "errors" "fmt" "strings" ) funcvalidate(inputstring)(bool,error){ ifstrings.TrimSpace(input)==""{ returnfalse,errors.New("cannotbeempty") } returntrue,nil } Selanjutnyadifungsimain,buatprogramsederhanauntukcaptureinputanuser. Manfaatkanfungsi validate()untukmengecekinputannya. funcmain(){ varnamestring fmt.Print("Typeyourname:") fmt.Scanln(&name) ifvalid,err:=validate(name);valid{ fmt.Println("halo",name) }else{ fmt.Println(err.Error()) } } Fungsi validate()mengembalikan2data.Datapertamaadalahnilai boolyang menandakaninputanapakahvalidatautidak.Datake-2adalahpesanerror-nya(jika inputantidakvalid). Fungsi strings.TrimSpace()digunakanuntukmenghilangkankarakterspasisebelumdan sesudahstring.Inidibutuhkankarenauserbisasajamenginputkanspasilaluenter. 158 Error&Panic Ketikainputantidakvalid,makaerrorbarudibuatdenganmemanfaatkanfungsi errors.New(). PenggunaanKeyword panic Panicdigunakanuntukmenampilkantraceerror.Hasilkeluarannyasamaseperti fmt.Println()hanyasajainformasiyangditampilkanlebihdetail. Padaprogramyangtelahkitabuattadi,ubah fmt.Println()yangberadadidalamblok kondisi elsepadafungsimainmenjadi panic(). ifvalid,err:=validate(name);valid{ fmt.Println("halo",name) }else{ panic(err.Error()) } Ketikausermenginputkanstringkosong,makaerrorakandimunculkanmenggunakan fungsi panic. 159 LayoutFormatString LayoutFormatString Dibab-babsebelumnyakitatelahbanyakmenggunakanlayoutformatstringseperti %s, %d, %.2f,danlainnya;untukkeperluanmenampilkanoutputkelayarataupununtuk memformatstring. Layoutformatstringdigunakanpadakonversidatakebentukstring.Contohnyaseperti %.3fyanguntukkonversinilai doubleke stringdengan3digitdesimal. Padababinikitaakanmempelajarisatupersatulayoutformatstringyangtersediadi Golang.Sampeldatayangdigunakansebagaicontohadalahkodeberikut. typestudentstruct{ namestring heightfloat64 ageint32 isGraduatedbool hobbies[]string } vardata=student{ name:"wick", height:182.5, age:26, isGraduated:false, hobbies:[]string{"eating","sleeping"}, } LayoutFormat %b Digunakanuntukmemformatdatanumerik,menjadibentukstringnumerikberbasis2 (biner). fmt.Printf("%b\n",data.age) //11010 LayoutFormat %c Digunakanuntukmemformatdatanumerikyangmerupakankodeunicode,menjadibentuk stringkarakterunicode-nya. 160 LayoutFormatString fmt.Printf("%c\n",1400) //Õ¸ fmt.Printf("%c\n",1235) //Ó“ LayoutFormat %d Digunakanuntukmemformatdatanumerik,menjadibentukstringnumerikberbasis10 (basisbilanganyangkitagunakan). fmt.Printf("%d\n",data.age) //26 LayoutFormat %eatau %E Digunakanuntukmemformatdatanumerikdesimalkedalambentuknotasistandar Scientificnotation. fmt.Printf("%e\n",data.height) //1.825000e+02 fmt.Printf("%E\n",data.height) //1.825000E+02 1.825000E+02maksudnyaadalah1.825x10^2,danhasiloperasitersebutadalahsesuai dengandataasli=182.5. Perbedaanantara %edan %Ehanyahurufbesarkecilkarakter epadahasil. LayoutFormat %fatau %F %Fadalahaliasdari %f.Keduanyamemilikifungsiyangsama. Berfungsiuntukmemformatdatanumerikdesimal,denganlebardesimalbisaditentukan. Secaradefaultlebardigitdesimaladalah6digit. 161 LayoutFormatString fmt.Printf("%f\n",data.height) //182.500000 fmt.Printf("%.9f\n",data.height) //182.500000000 fmt.Printf("%.2f\n",data.height) //182.50 fmt.Printf("%.f\n",data.height) //182 LayoutFormat %gatau %G %Gadalahaliasdari %g.Keduanyamemilikifungsiyangsama. Berfungsiuntukmemformatdatanumerikdesimal,denganlebardesimalbisaditentukan. Lebarkapasitasnyasangatbesar,pasdigunakanuntukdatayangjumlahdigitdesimalnya cukupbanyak. Bisadilihatpadakodeberikutperbandinganantara %e, %f,dan %g. fmt.Printf("%e\n",0.123123123123) //1.231231e-01 fmt.Printf("%f\n",0.123123123123) //0.123123 fmt.Printf("%g\n",0.123123123123) //0.123123123123 Perbedaanlainnyaadalahpada %g,lebardigitdesimaladalahsesuaidengandatanya, tidakbisadicustomsepertipada %f. fmt.Printf("%g\n",0.12) //0.12 fmt.Printf("%.5g\n",0.12) //0.12 LayoutFormat %o 162 LayoutFormatString Digunakanuntukmemformatdatanumerik,menjadibentukstringnumerikberbasis8 (oktal). fmt.Printf("%o\n",data.age) //32 LayoutFormat %p Digunakanuntukmemformatdatapointer,mengembalikanalamatpointerreferensivariabelnya. Alamatpointerdituliskandalambentuknumerikberbasis16denganprefix 0x. fmt.Printf("%p\n",&data.name) //0x2081be0c0 LayoutFormat %q Digunakanuntukescapestring.Meskipunstringyangdipakaimenggunakanliteral \akan tetapdi-escape. fmt.Printf("%q\n",`"name\height"`) //"\"name\\\\height\"" LayoutFormat %s Digunakanuntukmemformatdatastring. fmt.Printf("%s\n",data.name) //wick LayoutFormat %t Digunakanuntukmemformatdataboolean,menampilkannilai bool-nya. fmt.Printf("%t\n",data.isGraduated) //false 163 LayoutFormatString LayoutFormat %T Berfungsiuntukmengambiltipevariabelyangakandiformat. fmt.Printf("%T\n",data.name) //string fmt.Printf("%T\n",data.height) //float64 fmt.Printf("%T\n",data.age) //int32 fmt.Printf("%T\n",data.isGraduated) //bool fmt.Printf("%T\n",data.hobbies) //[]string LayoutFormat %v Digunakanuntukmemformatdataapasaja(termasukdatabertipe interface{}).Hasil kembaliannyaadalahstringnilaidataaslinya. Jikadataadalahobjekcetakan struct,makaakanditampilkansemuasecaraproperty berurutan. fmt.Printf("%v\n",data) //{wick182.526false[eatingsleeping]} LayoutFormat %+v Digunakanuntukmemformatstruct,mengembalikannamatiappropertydannilainya berurutansesuaidenganstrukturstruct. fmt.Printf("%+v\n",data) //{name:wickheight:182.5age:26isGraduated:falsehobbies:[eatingsleeping]} LayoutFormat %#v 164 LayoutFormatString Digunakanuntukmemformatstruct,mengembalikannamadannilaitiappropertysesuai denganstrukturstructdanjugabagaimanaobjektersebutdideklarasikan. fmt.Printf("%#v\n",data) //main.student{name:"wick",height:182.5,age:26,isGraduated:false,hobbies:[]string {"eating","sleeping"}} Ketikamenampilkanobjekyangdeklarasinyaadalahmenggunakanteknikanonymous struct,makaakanmunculjugastrukturanonymousstructnya. vardata=struct{ namestring heightfloat64 }{ name:"wick", height:182.5, } fmt.Printf("%#v\n",data) //struct{namestring;heightfloat64}{name:"wick",height:182.5} Formatinijugabisadigunakanuntukmenampilkantipedatalain,danakandimunculkan strukturnyajuga. LayoutFormat %xatau %X Digunakanuntukmemformatdatanumerik,menjadibentukstringnumerikberbasis16 (heksadesimal). fmt.Printf("%x\n",data.age) //1a Jikadigunakanpadatipedatastring,makaakanmengembalikankodeheksadesimaltiap karakter. vard=data.name fmt.Printf("%x%x%x%x\n",d[0],d[1],d[2],d[3]) //7769636b fmt.Printf("%x\n",d) //7769636b 165 LayoutFormatString %xdan %Xmemilikifungsiyangsama.Perbedaannyaadalah %Xakanmengembalikan stringdalambentukuppercaseatauhurufkapital. LayoutFormat %% Carauntukmenuliskarakter %padastringformat. fmt.Printf("%%\n") //% 166 Time,ParsingTime,&FormatTime Time,ParsingTime,&FormatTime Padababinikitaakanbelajartentangpemanfaatantime,method-methodyangdisediakan, danjugaformat&parsingdata stringke time.Timedansebaliknya. Golangmenyediakanpackage timeyangberisikanbanyaksekalikomponenyangbisa digunakanuntukkeperluanpemanfaatanwaktu. Timedisinimaksudnyaadalahgabungandatedantime,bukanhanyawaktusaja. Penggunaan time.Time time.Timeadalahtipedatauntukobjekwaktu.Ada2carayangbisadigunakanuntuk membuatdatabertipeini. Denganmenjadikanwaktusekarangsebagaitime Membuattimedengandataditentukansendiri Berikutmerupakancontohpenggunannya. packagemain import"fmt" import"time" funcmain(){ vartime1=time.Now() fmt.Printf("time1%v\n",time1) //time12015-09-0117:59:31.73600891+0700WIB vartime2=time.Date(2011,12,24,10,20,0,0,time.UTC) fmt.Printf("time2%v\n",time2) //time22011-12-2410:20:00+0000UTC } Fungsi time.Now()mengembalikanobjek time.Timedengandataadalahwaktusekarang. Bisadilihatketikaditampilkan,informasiyangmunculadalahsesuaidengantanggal programtersebutdieksekusi. 167 Time,ParsingTime,&FormatTime Sedangkan time.Date()digunakanuntukmembuatobjek time.Timebarudengan informasiwaktuyangbisakitatentukansendiri.Fungsiinimemiliki8buahparameter mandatorydenganskemabisadilihatdikodeberikut: time.Date(tahun,bulan,tanggal,jam,menit,detik,nanodetik,timezone) Objekcetakanfungsi time.Now(),informasitimezone-nyaadalahrelatifterhadaplokasi kita.Karenakebetulanpenulisberlokasidijawatimur,makaakanterdeteksimasukdalam GMT+7atauWIB.Berbedadenganvariabel time2yanglokasinyasudahkitatentukan secaraeksplisityaituUTC. Selainmenggunakan time.UTCuntukpenentuanlokasi,tersediajuga time.Localyang nilainyaadalahrelatifterhadapwaktukita. MethodMilik time.Time varnow=time.Now() fmt.Println("year:",now.Year(),"month:",now.Month()) //year:2015month:8 Kodediatasadalahcontohpenggunaanbeberapamethodmilikobjekbertipe time.Time. Method Year()mengembalikaninformasitahun,dan Month()mengembalikaninformasi angkabulan. Selainkeduamethoddiatas,adabanyaklagiyangbisadimanfaatkan.Tabelberikut merupakanlistmethodyangberhubungandengandate,time,danlocationyangtersedia padatipe time.Time. 168 Time,ParsingTime,&FormatTime Method ReturnType Penjelasan now.Year() int Tahun now.YearDay() int Harike-?dimulaiawaltahun now.Month() int Bulan now.Weekday() string Namahari.Bisamenggunakan now.Weekday().String()untukmengambil bentukstring-nya now.ISOWeek() ( int, int) Tahundanmingguke-?mulaiawaltahun now.Day() int Tanggal now.Hour() int Jam now.Minute() int Menit now.Second() int Detik now.Nanosecond() int Nanodetik now.Local() time.Time Waktudalamtimezonelokal now.Location() *time.Location Mengambilinformasilokasi,apakahlocalatau utc.Bisamenggunakan now.Location().String()untukmengambil bentukstring-nya now.Zone() ( string, int) Mengembalikaninformasitimezoneoffset dalamstringdannumerik.Sebagaicontoh WIB,25200 now.IsZero() bool Deteksiapakahnilaiobject nowadalah 01 Januaritahun1,00:00:00UTC.Jikaiyamaka bernilai true now.UTC() time.Time Waktudalamtimezone UTC now.Unix() int64 Waktudalamformatunixtime now.UnixNano() int64 Waktudalamformatunixtime.Infomasinano detikjugadimasukkan now.String() string Waktudalamstring Parsing time.Time Data stringbisadikonversimenjadi time.Timedenganmemanfaatkan time.Parse. Fungsiinimembutuhkan2parameter: Parameterke-1adalahlayoutformatdaridatawaktuyangakandiparsing Parameterke-2adalahdatastringyangingindiparsing 169 Time,ParsingTime,&FormatTime Contohpenerapannyabisadilihatdikodeberikut: varlayoutFormat,valuestring vardatetime.Time layoutFormat="2006-01-0215:04:05" value="2015-09-0208:04:00" date,_=time.Parse(layoutFormat,value) fmt.Println(value,"\t->",date.String()) //2015-09-0208:04:00+0000UTC layoutFormat="02/01/2006MST" value="02/09/2015WIB" date,_=time.Parse(layoutFormat,value) fmt.Println(value,"\t\t->",date.String()) //2015-09-0200:00:00+0700WIB Layoutformattimedigolangberbedadibandingbahasalain.Umumnyalayoutformatyang digunakanadalahseperti "DD/MM/YYYY"dll,diGolangtidak. Golangmemilikistandarlayoutformatyangcukupunik,contohnyasepertipadakodediatas "2006-01-0215:04:05".Golangmenggunakan 2006untukparsingtahun,bukan YYYY; 01untukparsingbulan; 02untukparsinghari;danseterusnya.Detailnyabisadilihatdi tabelberikut. 170 Time,ParsingTime,&FormatTime LayoutFormat Penjelasan ContohData 2006 Tahun4digit 2015 006 Tahun3digit 015 06 Tahun2digit 15 01 Bulan2digit 05 1 Bulan1digitjikadibawahbulan10, selainnya2digit 5, 12 January Namabulandalambahasainggris September, August Jan Namabulandalambahasainggris,3huruf Sep, Aug 02 Tanggal2digit 02 2 Tanggal1digitjikadibawahbulan10, selainnya2digit 8, 31 Monday Namaharidalambahasainggris Saturday, Friday Mon Namaharidalambahasainggris,3huruf Sat, Fri 15 Jamdenganformat24jam 18 03 Jamdenganformat12jam2digit 05, 11 3 Jamdenganformat12jam1digitjika dibawahjam11,selainnya2digit 5, 11 PM AM/PM,biasadigunakandenganformat jam12jam PM, AM 04 Menit2digit 08 4 Menit1digitjikadibawahmenit10, selainnya2digit 8, 24 05 Detik2digit 06 5 Detik1digitjikadibawahdetik10,selainnya 2digit 6, 36 999999 Nanodetik 124006 MST Lokasitimezone UTC, WIB, EST Z0700 Offsettimezone Z, +0700, -0200 PredefinedLayoutFormatUntukKeperluan ParsingTime 171 Time,ParsingTime,&FormatTime Golangjugamenyediakanbeberapapredefinedlayoutformatumumyangbisa dimanfaatkan.Jaditidakperlumenuliskankombinasikomponen-komponenlayoutformat. Salahsatupredefinedlayoutyangbisadigunakanadalah time.RFC822.Formatinisama dengan 02Jan0615:04MST.Berikutadalahcontohpenerapannya. vardate,_=time.Parse(time.RFC822,"02Sep1508:00WIB") fmt.Println(date.String()) //2015-09-0208:00:00+0700WIB Adabeberapalayoutformatlainyangbisadimanfaatkan.Berikutadalahlistnya. PredefinedLayoutFormat LayoutFormat time.ANSIC MonJan_215:04:052006 time.UnixDate MonJan_215:04:05MST2006 time.RubyDate MonJan0215:04:05-07002006 time.RFC822 02Jan0615:04MST time.RFC822Z 02Jan0615:04-0700 time.RFC850 Monday,02-Jan-0615:04:05MST time.RFC1123 Mon,02Jan200615:04:05MST time.RFC1123Z Mon,02Jan200615:04:05-0700 time.RFC3339 2006-01-02T15:04:05Z07:00 time.RFC3339Nano 2006-01-02T15:04:05.999999999Z07:00 time.Kitchen 3:04PM time.Stamp Jan_215:04:05 time.StampMilli Jan_215:04:05.000 time.StampMicro Jan_215:04:05.000000 time.StampNano Jan_215:04:05.000000000 Format time.Time Setelahsebelumnyakitabelajartentangkonversi stringke time.Time.Kaliinikitaakan belajarsebaliknya,yaitukonversi time.Timeke string. Method Format()digunakanuntukmembentuk stringmenggunakanlayoutformat tertentu.Layoutformatyangbisadigunakanadalahsamasepertipadaparsingtime.Contoh bisadilihatpadakodeberikut. 172 Time,ParsingTime,&FormatTime vardate,_=time.Parse(time.RFC822,"02Sep1508:00WIB") vardateS1=date.Format("Monday02,January200615:04MST") fmt.Println("dateS1",dateS1) //Wednesday02,September201508:00WIB vardateS2=date.Format(time.RFC3339) fmt.Println("dateS2",dateS2) //2015-09-02T08:00:00+07:00 Variabel dateberisikanhasilparsingmenggunakanpredefinedlayoutformat time.RFC822. Variabeltersebutkemudianditampilkan2kalidenganlayoutformatberbeda. HandleErrorParsing time.Time Ketikaparsing stringke time.Time,sangatmemungkinkanbisaterjadierrorkarena strukturdatayangakandiparsingtidaksesuailayoutformatyangdigunakan. Untukmendeteksihalinibisamemanfaatkannilaikembalianke-2fungsi time.Parse. Berikutadalahcontohpenerapannya. vardate,err=time.Parse("06Jan15","02Sep1508:00WIB") iferr!=nil{ fmt.Println("error",err.Error()) return } fmt.Println(date) Kodediatasmenghasilkanerrorkarenaformattidaksesuaidenganskemadatayangakan diparsing.Layoutformatyangharusnyadigunakanadalah 06Jan1503:04MST. 173 Timer Timer Adabeberapafungsidalampackage timeyangmemilikikegunaansebagaitimer.Dengan memanfaatkanfungsi-fungsitersebut,kitabisamenundaeksekusisebuahprosesdengan durasiwaktutertentu. Fungsi time.Sleep() Fungsiinidigunakanuntukmenghentikanprogramsejenak. time.Sleep()bersifat blocking,sehinggastatementdibawahnyatidakakandieksekusisampaiwaktu pemberhentianusai.Contohsederhanapenerapannyabisadilihatpadakodeberikut. packagemain import"fmt" import"time" funcmain(){ fmt.Println("start") time.Sleep(time.Second*4) fmt.Println("after4seconds") } Tulisan "start"muncul,lalu4detikkemudiantulisan "after4seconds"muncul. Fungsi time.NewTimer() Fungsiinisedikitberbedadengan time.Sleep().Fungsi time.NewTimer()mengembalikan sebuahobjek *time.Timeryangmemilikimethod C.Methodinimengembalikansebuah channeldanakandieksekusidalamwaktuyangsudahditentukan.Contohpenerapannya bisadilihatpadakodeberikut. vartimer=time.NewTimer(4*time.Second) fmt.Println("start") <-timer.C fmt.Println("finish") Tulisan "finish"akanmunculsetelahdelay4detik. 174 Timer Fungsi time.AfterFunc() Fungsi time.AfterFunc()memiliki2parameter.Parameterpertamaadalahdurasitimer, danparameterkeduaadalahcallbacknya.Callbacktersebutakandieksekusijikawaktu sudahmemenuhidurasitimer. varch=make(chanbool) time.AfterFunc(4*time.Second,func(){ fmt.Println("expired") ch<-true }) fmt.Println("start") <-ch fmt.Println("finish") Tulisan "start"akanmunculdiawal.Diikuti4detikkemudiantulisan "expired". Didalamcallbackterdapatprosestransferdatalewatchannel,mengakibatkantulisan "finish"akanmuncultepatsetelahtulisan "expired"muncul. Beberapahalyangperludiketahuidalammenggunakanfungsiini: Jikatidakadaserahterimadatalewatchannel,makaeksekusi time.AfterFunc() adalahasynchronousdantidakblocking. Jikaadaserahterimadatalewatchannel,makafungsiakantetapberjalan asynchronousdantidakblockinghinggabariskodedimanapenerimaandatachannel dilakukan. Fungsi time.After() Kegunaanfungsiinimiripseperti time.Sleep().Perbedaannyaadalah,fungsi timer.After()akanmengembalikandatachannel,sehinggaperlumenggunakantanda <-dalampenerapannya. <-time.After(4*time.Second) fmt.Println("expired") Tulisan "expired"akanmunculsetelah4detik. KombinasiTimer&Goroutine 175 Timer Berikutmerupakancontohpenerapantimerdangoroutine.Programdibawahiniadalah programtanya-jawabsederhana.Userharusmenginputkanjawabandalamwaktutidak lebihdari5detik.Jikalebihdariwaktutersebutbelumadajawabamn,makaakanmuncul pesantimeout. Pertama,importpackageyangdiperlukan. packagemain import"fmt" import"os" import"time" Buatfungsi timer(),yangnantinyaakandieksekusisebagaigoroutine.Didalamfungsiini akanadaprosespengirimandatalewatchannel chketikawaktusudahmencapai timeout. functimer(timeoutint,chchan<-bool){ time.AfterFunc(time.Duration(timeout)*time.Second,func(){ ch<-true }) } Siapkanjugafungsi watcher().Fungsiinijugaakandieksekusisebagaigoroutine. Tugasnyacukupsederhana,yaituketikasebuahdataditerimadarichannel chmakaakan ditampilkantulisanpenandawaktuhabis. funcwatcher(timeoutint,ch<-chanbool){ <-ch fmt.Println("\ntimeout!noanswermorethan",timeout,"seconds") os.Exit(0) } Terakhir,buatimplementasidifungsi main. 176 Timer funcmain(){ vartimeout=5 varch=make(chanbool) gotimer(timeout,ch) gowatcher(timeout,ch) varinputstring fmt.Print("whatis725/25?") fmt.Scan(&input) ifinput=="29"{ fmt.Println("theanswerisright!") }else{ fmt.Println("theansweriswrong!") } } Ketikausertidakmenginputkanapa-apadalamkurunwaktu5detik,makaakanmuncul pesantimeout,laluprogramdihentikan. 177 KonversiData KonversiData Dibab-babsebelumnyakitasudahmengaplikasikanbeberapacarakonversidata, contohnyasepertikonversi string↔ intmenggunakan strconv,dan time.Time↔ string.Dibabinikitaakanbelajarlebihbanyak. KonversiMenggunakan strconv strconvberisikanbanyakfungsiyangsangatmembantuuntukkeperluankonversidata. Berikutmerupakanbeberapafungsidalampackagetersebutyangbisadimanfaatkan. Fungsi strconv.Atoi() Fungsiinidigunakanuntukkonversidatadaritipe stringke int.Mengembalikan2buah nilaibalik,yaituhasilkonversidan error(jikakonversisukses,maka errorakanberisi nil). packagemain import"fmt" import"strconv" funcmain(){ varstr="124" varnum,err=strconv.Atoi(str) iferr==nil{ fmt.Println(num)//124 } } Fungsi strconv.Itoa() Merupakankebalikandari strconv.Atoi,bergunauntukkonversi intke string. varnum=124 varstr=strconv.Itoa(num) fmt.Println(str)//"124" 178 KonversiData Fungsi strconv.ParseInt() Digunakanuntukkonversi stringberbentuknumerikdenganbasistertentuketipenumerik non-desimaldenganlebardatabisaditentukan. Padacontohberikut,string "124"ditentukanbasisnumeriknya10,akandikonversikejenis tipedata int64. varstr="124" varnum,err=strconv.ParseInt(str,10,64) iferr==nil{ fmt.Println(num)//124 } Contohlainnya,string "1010"ditentukanbasisnumeriknya2(biner),akandikonversike jenistipedata int8. varstr="1010" varnum,err=strconv.ParseInt(str,2,8) iferr==nil{ fmt.Println(num)//10 } Fungsi strconv.FormatInt() Bergunauntukkonversidatanumerik int64ke stringdenganbasisnumerikbisa ditentukansendiri. varnum=int64(24) varstr=strconv.FormatInt(num,8) fmt.Println(str)//30 Fungsi strconv.ParseFloat() Digunakanuntukkonversi stringkenumerikdesimaldenganlebardatabisaditentukan. 179 KonversiData varstr="24.12" varnum,err=strconv.ParseFloat(str,32) iferr==nil{ fmt.Println(num)//24.1200008392334 } Padacontohdiatas,string "24.12"dikonversikefloatdenganlebar float32.Hasil konversi strconv.ParseFloatdisesuaikandenganstandarIEEEStandardforFloating-Point Arithmetic. Fungsi strconv.FormatFloat() Bergunauntukkonversidatabertipe float64ke stringdenganformateksponen,lebar digitdesimal,danlebartipedatabisaditentukan. varnum=float64(24.12) varstr=strconv.FormatFloat(num,'f',6,64) fmt.Println(str)//24.120000 Padakodediatas,Data 24.12yangbertipe float64dikonversikestringdenganformat eksponen fatautanpaeksponen,lebardigitdesimal6digit,danlebartipedata float64. Adabeberapaformateksponenyangbisadigunakan.Detailnyabisadilihatditabelberikut. FormatEksponen Penjelasan b -ddddp±ddd,a,eksponenbiner(basis2) e -d.dddde±dd,a,eksponendesimal(basis10) E -d.ddddE±dd,a,eksponendesimal(basis10) f -ddd.dddd,tanpaeksponen g Akanmenggunakanformateksponen euntukeksponenbesar dan funtukselainnya G Akanmenggunakanformateksponen Euntukeksponenbesar dan funtukselainnya Fungsi strconv.ParseBool() Digunakanuntukkonversi stringke bool. 180 KonversiData varstr="true" varbul,err=strconv.ParseBool(str) iferr==nil{ fmt.Println(bul)//true } Fungsi strconv.FormatBool() Digunakanuntukkonversi boolke string. varbul=true varstr=strconv.FormatBool(bul) fmt.Println(str)//124 KonversiDataMenggunakanCasting Keywordtipedatabisadigunakanuntukcasting.Carapenggunaannyaadalahdengan memanggilnyasebagaifungsidanmenyisipkandatayangakandikonversisebagai parameter. varafloat64=float64(24) fmt.Println(a)//24 varbint32=int32(24.00) fmt.Println(b)//24 Casting string↔ byte Stringsebenarnyaadalahslice/array byte.DiGolangsebuahkarakterbiasa(bukan unicode)direpresentasikanolehsebuahelemenslicebyte.Nilaislicetersebutadalahdata intyang(default-nya)ber-basisdesimal,yangmerupakankodeASCIIdarikarakterbiasa tersebut. Caramendapatkanslicebytedarisebuahdatastringadalahdenganmeng-casting-nyake tipe []byte.Tiapelemen byteisinyaadalahdatanumerikdenganbasisdesimal. 181 KonversiData vartext1="halo" varb=[]byte(text1) fmt.Printf("%d%d%d%d\n",b[0],b[1],b[2],b[3]) //10497108111 Padacontohdiatas,stringdalamvariabel text1dikonversike []byte.Tiapelemenslice bytetersebutkemudianditampilkansatu-per-satu. Contohselanjutnyadibawahinimerupakankebalikandaricontohdiatas,sebuah []byte akandicaribentuk string-nya. varbyte1=[]byte{104,97,108,111} vars=string(byte1) fmt.Printf("%s\n",s) //halo Beberapakodebytestringsayatuliskansebagaidalamsebuahslice,yangditampungoleh variabel byte1.Lalu,nilaivariabeltersebutdi-castke string,untukkemudian ditampilkan. Selainitu,tiapkarakterstringjugabisadi-castingkebentuk int,hasilnyaadalahsama yaitudatabytedalambentuknumerikbasisdesimal,denganketentuanliteralstringyang digunakanadalahtandapetiksatu( '). Jugaberlakusebaliknya,datanumerikjikadi-castingkebentukstringdideteksisebagai kodebytedarikarakteryangakandihasilkan. varcint64=int64('h') fmt.Println(c)//104 vardstring=string(104) fmt.Println(d)//h KonversiData interface{}Menggunakan TeknikTypeAssertions Typeassertionsmerupakanteknikcastingdata interface{}kesegalajenistipe(dengan syaratdatatersebutmemangbisadi-casting). Berikutmerupakancontohpenerapannya.Disiapkanvariabel databertipe map[string]interface{}denganvalueberbedabedatipedatanya. 182 KonversiData vardata=map[string]interface{}{ "nama":"johnwick", "grade":2, "height":156.5, "isMale":true, "hobbies":[]string{"eating","sleeping"}, } fmt.Println(data["nama"].(string)) fmt.Println(data["grade"].(int)) fmt.Println(data["height"].(float64)) fmt.Println(data["isMale"].(bool)) fmt.Println(data["hobbies"].([]string)) Statement data["nama"].(string)maksudnyaadalah,nilai data["nama"]dicastingsebagai string. Tipeaslidatapadavariabel interface{}bisadiketahuidengancarameng-casting interface{}ketipe type.Namuncastinginihanyabisadilakukanpada switch. for_,val:=rangedata{ switchval.(type){ casestring: fmt.Println(val.(string)) caseint: fmt.Println(val.(int)) casefloat64: fmt.Println(val.(float64)) casebool: fmt.Println(val.(bool)) case[]string: fmt.Println(val.([]string)) default: fmt.Println(val.(int)) } } Kombinasi switch- casebisadimanfaatkanuntukdeteksitipeaslisebuahdatabertipe interface{},contohpenerapannyasepertipadakodediatas. 183 FungsiString FungsiString Golangmenyediakanpackage stringsyangdidalamnyaberisikancukupbanyakfungsi untukkeperluanpengolahandatabertipestring.Babinimerupakanpembahasanmengenai beberapafungsiyangadadidalampackagetersebut. Fungsi strings.Contains() Dipakaiuntukdeteksiapakahstring(parameterkedua)merupakanbagiandaristringlain (parameterpertama).Nilaikembaliannyaberupa bool. packagemain import"fmt" import"strings" funcmain(){ varisExists=strings.Contains("johnwick","wick") fmt.Println(isExists) } Variabel isExistsakanbernilai true,karenastring "wick"merupakanbagiandari "johnwick". Fungsi strings.HasPrefix() Digunakanuntukdeteksiapakahsebuahstring(parameterpertama)diawalistringtertentu (parameterkedua). varisPrefix1=strings.HasPrefix("johnwick","jo") fmt.Println(isPrefix1)//true varisPrefix2=strings.HasPrefix("johnwick","wi") fmt.Println(isPrefix2)//false Fungsi strings.HasSuffix() 184 FungsiString Digunakanuntukdeteksiapakahsebuahstring(parameterpertama)diakhiristringtertentu (parameterkedua). varisSuffix1=strings.HasSuffix("johnwick","ic") fmt.Println(isSuffix1)//false varisSuffix2=strings.HasSuffix("johnwick","ck") fmt.Println(isSuffix2)//true Fungsi strings.Count() Memilikikegunaanuntukmenghitungjumlahkaraktertertentu(parameterkedua)dari sebuahstring(parameterpertama).Nilaikembalianfungsiiniadalahjumlahkarakternya. varhowMany=strings.Count("ethanhunt","t") fmt.Println(howMany)//2 Nilaiyangdikembalikan 2,karenapadastring "ethanhunt"terdapatduabuahkarakter "t". Fungsi strings.Index() Digunakanuntukmencariposisiindekssebuahstring(parameterkedua)dalamstring (parameterpertama). varindex1=strings.Index("ethanhunt","ha") fmt.Println(index1)//2 String "ha"beradapadaposisike 2dalamstring "ethanhunt"(indeksdimulaidari0). Jikadiketemukanduasubstring,makayangdiambiladalahyangpertama,contoh: varindex2=strings.Index("ethanhunt","n") fmt.Println(index2)//4 String "n"beradapadaindeks 4dan 8.Yangdikembalikanadalahyangpalingkiri (palingkecil),yaitu 4. Fungsi strings.Replace() 185 FungsiString Fungsiinidigunakanuntukreplace/menggantibagiandaristringdenganstringtertentu. Jumlahsubstringyangdi-replacebisaditentukan,apakahhanya1stringpertama,2string, ataukesemuanya. vartext="banana" varfind="a" varreplaceWith="o" varnewText1=strings.Replace(text,find,replaceWith,1) fmt.Println(newText1)//"bonana" varnewText2=strings.Replace(text,find,replaceWith,2) fmt.Println(newText2)//"bonona" varnewText3=strings.Replace(text,find,replaceWith,-1) fmt.Println(newText3)//"bonono" Padacontohdiatas,substring "a"padastring "banana"akandi-replacedenganstring "o". Pada newText1,hanya1huruf osajayangtereplacekarenamaksimalsubstringyang ingindi-replaceditentukan1. Angka -1akanmenjadikanprosesreplaceberlakupadasemuasubstring.Contohbisa dilihatpada newText3. Fungsi strings.Repeat() Digunakanuntukmengulangstring(parameterpertama)sebanyakdatayangditentukan (parameterkedua). varstr=strings.Repeat("na",4) fmt.Println(str)//"nananana" Padacontohdiatas,string "na"diulangsebanyak4kali.Hasilnyaadalah: "nananana" Fungsi strings.Split() Digunakanuntukmemisahstring(parameterpertama)dengantandapemisahbisa ditentukansendiri(parameterkedua).Hasilnyaberupaarraystring. 186 FungsiString varstring1=strings.Split("thedarkknight","") fmt.Println(string1)//["the","dark","knight"] varstring2=strings.Split("batman","") fmt.Println(string2)//["b","a","t","m","a","n"] String "thedarkknight"dipisahmenggunakanpemisahstringspasi "",hasilnya kemudianditampungoleh string1. Untukmemisahstringmenjadiarraytiap1string,gunakanpemisahstringkosong "".Bisa dilihatcontohnyapadavariabel string2. Fungsi strings.Join() Memilikikegunaanberkebalikandengan strings.Split().Digunakanuntuk menggabungkanarraystring(parameterpertama)menjadisebuahstringdenganpemisah tertentu(parameterkedua. vardata=[]string{"banana","papaya","tomato"} varstr=strings.Join(data,"-") fmt.Println(str)//"banana-papaya-tomato" Array datadigabungkanmenjadisatudenganpemisahtandadash( -). Fungsi strings.ToLower() Mengubahhuruf-hurufstringmenjadihurufkecil. varstr=strings.ToLower("aLAy") fmt.Println(str)//"alay" Fungsi strings.ToUpper() Mengubahhuruf-hurufstringmenjadihurufbesar. varstr=strings.ToUpper("eat!") fmt.Println(str)//"EAT!" 187 FungsiString 188 Regexp Regexp Regexpatauregularexpressionadalahsuatuteknikyangdigunakanuntukpencocokan stringdenganpolatertentu.Regexpbiasadimanfaatkanuntukpencariandanpengubahan datastring. GolangmengadopsistandarregexRE2,untukmelihatsintaksyangdi-supportengineini bisalangsungmerujukkedokumentasinyadihttps://github.com/google/re2/wiki/Syntax. Padababinikitaakanbelajarmengenaipengaplikasianregexdenganmemanfaatkan fungsi-fungsidalampackage regexp. PenerapanRegexp Fungsi regexp.Compile()digunakanuntukmengkompilasiekspresiregexyang dimasukkan.Fungsitersebutmengembalikanobjekbertipe regexp.*Regexp. Berikutmerupakancontohpenerapanregexuntukpencariankarakter. packagemain import"fmt" import"regexp" funcmain(){ vartext="bananaburgersoup" varregex,err=regexp.Compile(`[a-z]+`) iferr!=nil{ fmt.Println(err.Error()) } varres1=regex.FindAllString(text,2) fmt.Printf("%#v\n",res1) //["banana","burger"] varres2=regex.FindAllString(text,-1) fmt.Printf("%#v\n",res2) //["banana","burger","soup"] } 189 Regexp Ekspresi [a-z]+maknanyaadalah,semuastringyangmerupakanalphabetyanghurufnya kecil.Ekspresitersebutdi-compileoleh regexp.Compile()laludisimpankevariabelobjek regexyangtipenyaadalah regexp.*Regexp. Struct regexp.Regexpmemilikibanyakmethod,salahsatunyaadalah FindAllString(), yangberfungsiuntukpencariansemuastringyangsesuaidenganekspresiregex,dengan kembalianberupaarraystring. Jumlahhasilpencariandari regex.FindAllString()bisaditentukan.Contohnyapada res1, ditentukanmaksimal 2datasajapadanilaikembalian.Jikabatasdiset -1,makaakan mengembalikansemuadata. Adacukupbanyakmethodstruct regexp.*Regexpyangbisakitamanfaatkanuntuk keperluanpengelolaanstring.Berikutmerupakanpembahasantiapmethod-nya. Method MatchString() Methodinidigunakanuntukmendeteksiapakahstringmemenuhisebuahpolaregexp. vartext="bananaburgersoup" varregex,_=regexp.Compile(`[a-z]+`) varisMatch=regex.MatchString(text) fmt.Println(isMatch) //true Padacontohdiatas isMatchbernilai truekarenastring "bananaburgersoup"memenuhi polaregex [a-z]+. Method FindString() Digunakanuntukmencaristringyangmemenuhikriteriaregexpyangtelahditentukan. vartext="bananaburgersoup" varregex,_=regexp.Compile(`[a-z]+`) varstr=regex.FindString(text) fmt.Println(str) //"banana" Fungsiinihanyamengembalikan1buahhasilsaja.Jikaadabanyaksubstringyangsesuai denganekspresiregexp,akandikembalikanyangpertamasaja. 190 Regexp Method FindStringIndex() Digunakanuntukmencariindexstringkembalianhasildarioperasiregexp. vartext="bananaburgersoup" varregex,_=regexp.Compile(`[a-z]+`) varidx=regex.FindStringIndex(text) fmt.Println(idx) //[0,6] varstr=text[0:6] fmt.Println(str) //"banana" Methodinisamadengan FindString()hanyasajayangdikembalikanindeks-nya. Method FindAllString() Digunakanuntukmencaribanyakstringyangmemenuhikriteriaregexpyangtelah ditentukan. vartext="bananaburgersoup" varregex,_=regexp.Compile(`[a-z]+`) varstr1=regex.FindAllString(text,-1) fmt.Println(str1) //["banana","burger","soup"] varstr2=regex.FindAllString(text,1) fmt.Println(str2) //["banana"] Jumlahdatayangdikembalikanbisaditentukan.Jikadiisidengan -1,makaakan mengembalikansemuadata. Method ReplaceAllString() Bergunauntukme-replacesemuastringyangmemenuhikriteriregexp,denganstringlain. 191 Regexp vartext="bananaburgersoup" varregex,_=regexp.Compile(`[a-z]+`) varstr=regex.ReplaceAllString(text,"potato") fmt.Println(str) //"potatopotatopotato" Method ReplaceAllStringFunc() Digunakanuntukme-replacesemuastringyangmemenuhikriteriregexp,dengankondisi yangbisaditentukanuntuksetiapsubstringyangakandireplace. vartext="bananaburgersoup" varregex,_=regexp.Compile(`[a-z]+`) varstr=regex.ReplaceAllStringFunc(text,func(eachstring)string{ ifeach=="burger"{ return"potato" } returneach }) fmt.Println(str) //"bananapotatosoup" Padacontohdiatas,jikasalahsatusubstringyangmatchadalah "burger"makaakan digantidengan "potato",stringselainnyatidakdireplace. Method Split() Digunakanuntukmemisahstringdenganpemisahadalahsubstringyangmemenuhikriteria regexpyangtelahditentukan. Jumlahkarakteryangakandisplitbisaditentukandenganmengisiparameterkeduafungsi regex.Split().Jikadiisi -1makaakanme-replacesemuakarakter. vartext="banana,burger,soup" varregex,_=regexp.Compile(`[a-z]+`) varstr=regex.Split(text,-1) fmt.Printf("%#v\n",str) //["",",",",",""] 192 Regexp 193 Encode-DecodeBase64 Encode-DecodeBase64 Golangmemilikipackage encoding/base64,yangberisikanfungsi-fungsiuntukkebutuhan encodedandecodedatakebase64dansebaliknya.Datayangakandi-encodeharus bertipe []byte,perludilakukancastinguntukdata-datayangbelumsesuaitipenya. Adabeberapacarayangbisadigunakanuntukencodedandecodedata,dandibabinikita akanmempelajarinya. PenerapanFungsi EncodeToString()& DecodeString() Fungsi EncodeToString()dan DecodeString()digunakanuntukencodedandecodedata daribentuk stringke []byteatausebaliknya.Berikutadalahcontohpenerapannya. packagemain import"encoding/base64" import"fmt" funcmain(){ vardata="johnwick" varencodedString=base64.StdEncoding.EncodeToString([]byte(data)) fmt.Println("encoded:",encodedString) vardecodedByte,_=base64.StdEncoding.DecodeString(encodedString) vardecodedString=string(decodedByte) fmt.Println("decoded:",decodedString) } Variabel datayangbertipe string,harusdi-castingterlebihdahulukedalambentuk []bytesebelumdi-encodemenggunakanfungsi base64.StdEncoding.EncodeToString(). Hasilencodeadalahberupa string. Sedangkanpadafungsidecode base64.StdEncoding.DecodeString(),data stringyangdidecodeakandikembalikandalambentuk []byte.Ekspresi string(decodedByte) menjadikandata []bytetadiberubahmenjadistring. 194 Encode-DecodeBase64 PenerapanFungsi Encode()& Decode() Keduafungsiinidigunakanuntukdecodedanencodedatadari []byteke []byte. Penggunaancarainicukuppanjangkarenavariabelpenyimpanhasilencodemaupun decodeharusdisiapkanterlebihdahuludenganketentuanmemilikilebarelemensesuai denganhasilyangakanditampung(yangnilainyabisadicarimenggunakanfungsi EncodedLen()dan DecodedLen()). Lebihjelasnyasilakanperhatikancontohberikut. vardata="johnwick" varencoded=make([]byte,base64.StdEncoding.EncodedLen(len(data))) base64.StdEncoding.Encode(encoded,[]byte(data)) varencodedString=string(encoded) fmt.Println(encodedString) vardecoded=make([]byte,base64.StdEncoding.DecodedLen(len(encoded))) var_,err=base64.StdEncoding.Decode(decoded,encoded) iferr!=nil{ fmt.Println(err.Error()) } vardecodedString=string(decoded) fmt.Println(decodedString) Fungsi base64.StdEncoding.EncodedLen(len(data))menghasilkaninformasilebardata-ketikasudah-di-encode.Nilaitersebutkemudianditentukansebagailebaralokasitipe []byte padavariabel encodedyangnantinyadigunakanuntukmenampunghasilencoding. Fungsi base64.StdEncoding.DecodedLen()memilikikegunaansamadengan EncodedLen(), hanyasajadigunakanuntukkeperluandecoding. Dibanding2fungsisebelumnya,fungsi Encode()dan Decode()memilikibeberapa perbedaan.Selainlebardatapenampungencode/decodeharusdicariterlebihdahulu, terdapatperbedaanlainnya,yaitupadafungsiinihasilencode/decodetidakdidapatdarinilai kembalian,melainkandariparameter.Variabelyangdigunakanuntukmenampunghasil, disisipkanpadaparameterfungsitersebut. Padapemanggilanfungsiencode/decode,variabel encodeddan decodedtidakdisisipkan nilaipointer-nya,cukupdi-passdengancarabiasa,karenatipedatanyasudahdalambentuk []byte. Encode&DecodeDataURL 195 Encode-DecodeBase64 KhususuntukdatastringyangbentuknyaURL,akanlebihefektifmenggunakan URLEncodingdibanding StdEncoding. Carapenerapannyakuranglebihsama,bisamenggunakanmetodepertamamaupun metodekeduayangsudahdibahasdiatas.Cukupganti StdEncodingmenjadi URLEncoding. vardata="http://depeloper.com/" varencodedString=base64.URLEncoding.EncodeToString([]byte(data)) fmt.Println(encodedString) vardecodedByte,_=base64.URLEncoding.DecodeString(encodedString) vardecodedString=string(decodedByte) fmt.Println(decodedString) 196 HashSha1 HashSha1 Hashmerupakansebuahalgoritmaenkripsiuntukmengubahtextmenjadideretankarakter acak.Jumlahkarakterhasilhashselalusama.Hashtermasukone-wayencription,membuat hasildarihashtidakbisadikembalikanketextasli. Sha1atauSecureHashAlgorithm1merupakansalahsatualgoritmahashingyangsering digunakanuntukenkripsidata.Hasildarisha1adalahdatadenganlebar20byteatau160 bit,biasaditampilkandalambentukbilanganheksadesimal40digit. Dibabinikitaakanbelajartentangpemanfaatansha1dantekniksaltingdalamhash. PenerapanHashSha1 Golangmenyediakanpackage crypto/sha1,berisikanlibraryuntukkeperluanhashing. Carapenerapannyacukupmudah,contohnyabisadilihatpadakodeberikut. packagemain import"crypto/sha1" import"fmt" funcmain(){ vartext="thisissecret" varsha=sha1.New() sha.Write([]byte(text)) varencrypted=sha.Sum(nil) varencryptedString=fmt.Sprintf("%x",encrypted) fmt.Println(encryptedString) //f4ebfd7a42d9a43a536e2bed9ee4974abf8f8dc8 } Variabelhasildari sha1.New()adalahobjekbertipe hash.Hashyangmemilikimethod Writedan Sum. Method Write()digunakanuntukmenge-setdatayangakandi-hash.Dataharus dalambentuk []byte. Method Sum()digunakanuntukeksekusiproseshash,menghasilkandatayangsudah di-hashdalambentuk []byte.Methodinimembutuhkansebuahparameter,isidengan nil. 197 HashSha1 Untukmengambilbentukheksadesimalstringdaridatayangsudahdi-hash,bisa memanfaatkanfungsi fmt.Sprintfdenganlayoutformat %x. MetodeSaltingPadaHash Saltdalamkontekskriptografiadalahdataacakyangdigabungkanpadadataaslisebelum proseshashdilakukan. Hashmerupakanenkripsisatuarahdenganlebardatayangsudahpasti,menjadikansangat mungkinsekalikalauhasilhashuntukbeberapadataadalahsama.Disinilahkegunaansalt, teknikinibergunauntukmencegahseranganmenggunakanmetodepencocokandata-data yanghasilhash-nyaadalahsama(dictionaryattack). Langsungsajakitapraktekan.Pertamaimportpackageyangdibutuhkan.Lalubuatfungsi untukhashmenggunakansaltdariwaktusekarang. packagemain import"crypto/sha1" import"fmt" import"time" funcdoHashUsingSalt(textstring)(string,string){ varsalt=fmt.Sprintf("%d",time.Now().UnixNano()) varsaltedText=fmt.Sprintf("text:'%s',salt:%s",text,salt) fmt.Println(saltedText) varsha=sha1.New() sha.Write([]byte(saltedText)) varencrypted=sha.Sum(nil) returnfmt.Sprintf("%x",encrypted),salt } Saltyangdigunakanadalahhasildariekspresi time.Now().UnixNano().Hasilnyaakanselalu uniksetiapdetiknya,karenascopeterendahwaktupadafungsitersebutadalahnano secondataunanodetik. Selanjutnyatestfungsiyangtelahdibuatbeberapakali. 198 HashSha1 funcmain(){ vartext="thisissecret" fmt.Printf("original:%s\n\n",text) varhashed1,salt1=doHashUsingSalt(text) fmt.Printf("hashed1:%s\n\n",hashed1) //929fd8b1e58afca1ebbe30beac3b84e63882ee1a varhashed2,salt2=doHashUsingSalt(text) fmt.Printf("hashed2:%s\n\n",hashed2) //cda603d95286f0aece4b3e1749abe7128a4eed78 varhashed3,salt3=doHashUsingSalt(text) fmt.Printf("hashed3:%s\n\n",hashed3) //9e2b514bca911cb76f7630da50a99d4f4bb200b4 _,_,_=salt1,salt2,salt3 } Hasilekripsifungsi doHashUsingSaltakanselalubeda,karenasaltyangdigunakanadalah waktu. Metodeiniseringdipakaiuntukenkripsipassworduser.Selainhasilhash,datasaltjuga harusdisimpanpadadatabase,karenadigunakandalampencocokanpasswordsetiapuser melakukanlogin. 199 Arguments&Flag Arguments&Flag Argumentsadalahdataopsionalyangdisisipkanketikaeksekusiprogram.Sedangkanflag merupakanekstensidariargument.Denganflag,penulisanargumentmenjadilebihrapidan terstruktur. Dibabinikitaakanbelajartentangpenggunaanargumentsdanflag. PenggunaanArguments Dataargumentsbisadidapatlewatvariabel os.Args(package osperludi-importterlebih dahulu).Datatersebuttersimpandalambentukarraydenganpemisahadalahtandaspasi. Berikutmerupakancontohpenggunaannya. packagemain import"fmt" import"os" funcmain(){ varargsRaw=os.Args fmt.Printf("->%#v\n",argsRaw) //[]string{".../bab45","banana","potato","icecream"} varargs=argsRaw[1:] fmt.Printf("->%#v\n",args) //[]string{"banana","potato"} } Padasaateksekusiprogramdisisipkanjugaargument-nya.Sebagaicontohdisisipkan3 buahdatasebagaiargumen,yaitu: banana, potato,dan icecream. Untukeksekusinyasendiribisamenggunakan gorunataupundengancarabuild-execute. Menggunakan gorun $gorunbab45.gobananapotato"icecream" Menggunakan gobuild 200 Arguments&Flag $gobuildbab45.go $./bab45bananapotato"icecream" Variabel os.Argsmengembalikantakhanyaargumentssaja,tapijugapathfileexecutable (jikaeksekusi-nyamenggunakan gorunmakapathakanmerujukkefoldertemporary). Gunakan os.Args[1:]untukmengambilslicearguments-nyasaja. Bisadilihatpadakodediatas,bahwauntukdataargumenyangadakarakterspasinya( ),makaharusdiapittandapetik( "),agartidakdideteksisebagai2argumen. PenggunaanFlag Flagmemilikikegunaanyangsamasepertiarguments,yaituuntukparameterizeeksekusi program,denganpenulisandalambentukkey-value.Berikutmerupakancontoh penerapannya. packagemain import"flag" import"fmt" funcmain(){ varname=flag.String("name","anonymous","typeyourname") varage=flag.Int64("age",25,"typeyourage") flag.Parse() fmt.Printf("name\t:%s\n",*name) fmt.Printf("age\t:%d\n",*age) } Carapenulisanargumentsmenggunakanflag: $gorunbab45.go-name="johnwick"-age=28 Tiapargumentharusditentukankey,tipedata,dannilaidefault-nya.Contohnyasepertipada flag.String()diatas.Agarlebihmudahdipahami,marikitabahaskodeberikut. 201 Arguments&Flag vardataName=flag.String("name","anonymous","typeyourname") fmt.Println(*dataName) Kodetersebutmaksudnyaadalah,disiapkanflagbertipe string,dengankeyadalah name,dengannilaidefault "anonymous",danketerangan "typeyourname".Nilaiflagnya sendiriakandisimpankedalamvariabel dataName. Nilaibalikfungsi flag.String()adalahstringpointer,jadiperludi-dereferenceterlebih dahuluagarbisamendapatkannilaiaslinya( *dataName). Flagyangnilainyatidakdiset,secaraotomatisakanmengembalikannilaidefault. Tabelberikutmerupakanmacam-macamfungsiflagyangtersediauntuktiapjenistipedata. NamaFungsi ReturnValue flag.Bool(name,defaultValue,usage) *bool flag.Duration(name,defaultValue,usage) *time.Duration flag.Float64(name,defaultValue,usage) *float64 flag.Int(name,defaultValue,usage) *int flag.Int64(name,defaultValue,usage) *int64 flag.String(name,defaultValue,usage) *string flag.Uint(name,defaultValue,usage) *uint flag.Uint64(name,defaultValue,usage) *uint64 DeklarasiFlagDenganCaraPassingReference VariabelPenampungData Sebenarnyaada2caradeklarasiflagyangbisadigunakan,dancaradiatasmerupakan carapertama. Carakeduamiripdengancarapertama,perbedannyaadalahkalaudicarapertamanilai pointerflagdikembalikanlaluditampungvariabel;sedangkanpadacarakedua,nilainya diambillewatparameterpointer. Agarlebihjelasperhatikancontohberikut. 202 Arguments&Flag //carake-1 vardata1=flag.String("name","anonymous","typeyourname") fmt.Println(*data1) //carake-2 vardata2string flag.StringVar(&data2,"gender","male","typeyourgender") fmt.Println(data2) Tinggaltambahkansuffix Varpadapemanggilannamafungsiflagyangdigunakan(contoh flag.IntVar(), flag.BoolVar(),dll),laludisisipkanreferensivariabelpenampungflag sebagaiparameterpertama. 203 Exec Exec Execdigunakanuntukeksekusiperintahcommandlinelewatkodeprogram.Command yangbisadieksekusiadalahsemuacommandyangbisadieksekusiditerminal(CMDuntuk penggunaWind*ws). PenggunaanExec Golangmenyediakanpackage execberisikanbanyakfungsiuntukkeperluaneksekusi perintahCLI. Carauntukeksekusicommandcukupmudah,yaitudenganmenuliskancommanddalam bentukstring,diikutiarguments-nya(jikaada)sebagaiparametervariadicpadafungsi exec.Command().Contoh: packagemain import"fmt" import"os/exec" funcmain(){ varoutput1,_=exec.Command("ls").Output() fmt.Printf("->ls\n%s\n",string(output1)) varoutput2,_=exec.Command("pwd").Output() fmt.Printf("->pwd\n%s\n",string(output2)) varoutput3,_=exec.Command("git","config","user.name").Output() fmt.Printf("->gitconfiguser.name\n%s\n",string(output3)) } Fungsi exec.Command()digunakanuntukmenjalankancommand.Fungsitersebutbisa langsungdi-chaindenganmethod Output(),jikainginmendapatkanoutputnya.Output yangdihasilkanberbentuk []byte,gunakancastkestringuntukmengambilbentukstringnya. 204 Exec 205 File File AdabeberapacarayangbisadigunakanuntukoperasifilediGolang.Padababinikitaakan mempelajariteknikyangpalingdasar,yaitudenganmemanfaatkan os.File. MembuatFileBaru PembuatanfilediGolangsangatlahmudah,cukupdenganmemanggilfungsi os.Create() lalumemasukkanpathfileingindibuatsebagaiparameterfungsitersebut. Jikafileyangakandibuatsudahada,makaakanditimpa.Bisamemanfaatkan os.IsNotExist()untukmendeteksiapakahfilesudahdibuatataubelum. Berikutmerupakancontohpembuatanfile. packagemain import"fmt" import"os" varpath="/Users/novalagung/Documents/temp/test.txt" funccheckError(errerror){ iferr!=nil{ fmt.Println(err.Error()) os.Exit(0) } } funccreateFile(){ //deteksiapakahfilesudahada var_,err=os.Stat(path) //buatfilebarujikabelumada ifos.IsNotExist(err){ varfile,err=os.Create(path) checkError(err) deferfile.Close() } } funcmain(){ createFile() } 206 File Fungsi os.Stat()mengembalikan2data,yaituinformasitetangpathyangdicari,danerror (jikaada).Masukkanerrorkembalianfungsitersebutsebagaiparameterfungsi os.IsNotExist(),untukmendeteksiapakahfileyangakandibuatsudahada.Jikabelum ada,makafungsitersebutakanmengembalikannilai true. Fungsi os.Create()digunakanuntukmembuatfilepadapathtertentu.Fungsiini mengembalikanobjek *os.Filedarifileyangbersangkutan.Perludiketahuibahwafile yangbaruterbuatstatusnyaadalahotomatisopen,jadiperluuntukdi-closemenggunakan method file.Close()setelahfiletidakdigunakanlagi.Membiarkanfileterbukaketika sudahtaklagidigunakanbukanhalyangbaik,menyebabkanalokasimemorymenjadisiasia. MengeditIsiFile Untukmengeditfile,yangperludilakukanpertamaadalahmembukafiledenganlevelakses write.Setelahmendapatkanobjekfile-nya,gunakanmethod WriteString()untuk pengisiandata.Terakhirpanggilmethod Sync()untukmenyimpanperubahan. funcwriteFile(){ //bukafiledenganlevelaksesREAD&WRITE varfile,err=os.OpenFile(path,os.O_RDWR,0644) checkError(err) deferfile.Close() //tulisdatakefile _,err=file.WriteString("halo\n") checkError(err) _,err=file.WriteString("maribelajargolang\n") checkError(err) //simpanperubahan err=file.Sync() checkError(err) } funcmain(){ writeFile() } 207 File Padaprogramdiatas,filedibukadenganlevelaksesreaddanwritedengankode permission0664.Setelahitu,beberapastringdiisikankedalamfiletersebutmenggunakan WriteString().Diakhir,semuaperubahanterhadapfileakandisimpandengan dipanggilnya Sync(). MembacaIsiFile Fileyangingindibacaharusdibukaterlebihdahulumenggunakanfungsi os.OpenFile() denganlevelaksesminimaladalahread.Setelahitu,gunakanmethod Read()dengan parameteradalahvariabelyangdimanahasilprosesbacaakandisimpankevariabel tersebut. //tambahkandibagianimportpackageio import"io" funcreadFile(){ //bukafile varfile,err=os.OpenFile(path,os.O_RDONLY,0644) checkError(err) deferfile.Close() //bacafile vartext=make([]byte,1024) for{ n,err:=file.Read(text) iferr!=io.EOF{ checkError(err) } ifn==0{ break } } fmt.Println(string(text)) checkError(err) } funcmain(){ readFile() } 208 File os.OpenFile()digunakanuntukmembukafile.Fungsitersebutmemilikibeberapa parameter. 1. Parameterpertamaadalahpathfileyangakandibuka 2. Parameterkeduaadalahlevelakses. os.O_RDONLYmaksudnyaadalahreadonly. 3. Parameterketigaadalahpermissionfile-nya Kemudiandisiapkanvariabel textyangbertipeslice []bytedenganalokasielemen 1024.Variabeltersebutakanberisikandatahasilfungsi file.Read().Prosespembacaan fileakandilakukanterusmenerus,berurutandaribarispertamahinggaakhir. Erroryangmunculketikaeksekusi file.Read()akandifilter,ketikaerrortersebutadalah selain io.EOFmakaprosesbacafileakanberlanjut. Error io.EOFsendirimenandakanbahwafileyangsedangdibacaadalahbaristerakhirisi fileatauendoffile. MenghapusFile Caramenghapusfilesangatlahmudah,cukuppanggilfungsi os.Remove(),masukkanpath fileyangingindihapussebagaiparameter. funcdeleteFile(){ varerr=os.Remove(path) checkError(err) } funcmain(){ deleteFile() } 209 Web Web Golangmenyediakanpackage net/httpyangberisikanberbagaimacamfituruntuk keperluanpembuatanaplikasiberbasiweb.Termasukdidalamnyarouting,server, templating,danlainnya,semuatinggalpakai. Golangmemilikiwebserversendiri,danwebservertersebutberadadidalamgolang,tdak sepertibahasalainyangservernyaterpisahdanperludi-instalsendiri(sepertiPHPyang memerlukanApache,.NETyangmemerlukanIIS).Tapitakmenutupkemungkinanjuga sebuahaplikasiGolangdijalankanpadawebserverlainsepertiserverNginx. Dibabinikitaakanbelajarcarapembuatanaplikasiwebsederhanda,danjuga pemanfaatantemplatedalammendesainview. MembuatAplikasiWebSederhanda Package net/httpmemilikibanyaksekalifungsiyangbisadimanfaatkan.Dibagianinikita akanmempelajaribeberapafungsipentingsepertiroutingdanstartserver. Programdibawahinimerupakancontohsederhanauntukmemunculkantextdiwebketika urltertentudiakses. packagemain import"fmt" import"net/http" funcindex(whttp.ResponseWriter,r*http.Request){ fmt.Fprintln(w,"apakabar!") } funcmain(){ http.HandleFunc("/",func(whttp.ResponseWriter,r*http.Request){ fmt.Fprintln(w,"halo!") }) http.HandleFunc("/index",index) fmt.Println("startingwebserverathttp://localhost:8080/") http.ListenAndServe(":8080",nil) } Jalankanprogramtersebut. 210 Web JikamunculdialogDoyouwanttheapplication“bab48”toacceptincomingnetwork connections?atausejenis,pilihallow.Setelahitu,bukaurlhttp://localhost/dan http://localhost/indexlewatbrowser. Fungsi http.HandleFunc()digunakanuntukroutingaplikasiweb.Maksuddarirouting adalahpenentuanaksiketikaurltertentudiaksesolehuser. Padakodediatas2rutedidaftarkan,yaitu /dan /index.Aksidarirute /adalah menampilkantext "halo"dihalamanwebsite.Sedangkan /indexmenampilkantext "apa kabar!". Fungsi http.HandleFunc()memiliki2buahparameteryangharusdiisi.Parameterpertama adalahruteyangdiinginkan.Parameterkeduaadalahcallbackatauaksiketikarutetersebut diakses.Callbacktersebutbertipefungsi func(whttp.ResponseWriter,r*http.Request). Padapendaftaranrute /index,callback-nyaadalahfungsi index(),halsepertiini diperbolehkanasalkantipedarifungsitersebutsesuai. Fungsi http.listenAndServe()digunakanuntukmenghidupkanserversekaligus menjalankanaplikasimenggunakanservertersebut.Digolang,1webaplikasiadalah1 buahserverberbeda. Padacontohdiatas,serverdijalankanpadaport 8080. Perludiingat,setiapadaperubahanpadafile, gorunharusdipanggillagi. Untukmenghentikanwebserver,tekanCTRL+CpadaterminalatauCMDdimana pengeksekusianaplikasiberlangsung. 211 Web PenggunaanTemplateWeb Templatememberikankemudahandalammendesaintampilanviewaplikasiwebsite.Dan kabarbaiknyagolangmenyediakanenginetemplatesendiri,denganbanyakfituryang tersediadidalamnya. Disinikitaakanbelajarcontohsederhanapenggunaantemplateuntukmenampilkandata. Pertamasiapkandahulutemplatenya.Buatfile template.htmllaluisidengankodeberikut. <html> <head> <title>Golanglearnnet/http</title> </head> <body> <p>Hello{{.Name}}!</p> <p>{{.Message}}</p> </body> </html> Kode {{.Name}}maksudnyaadalahrepresentasivariabel Nameyangdikirimdarirouter. Kodetersebutnantinyadi-replacedenganisivariabel Name. Selanjutnyaubahisifile .godengankodeberikut. packagemain import"fmt" import"html/template" import"net/http" funcmain(){ http.HandleFunc("/",func(whttp.ResponseWriter,r*http.Request){ vardata=map[string]string{ "Name":"johnwick", "Message":"haveaniceday", } vart,err=template.ParseFiles("template.html") iferr!=nil{ fmt.Println(err.Error()) } t.Execute(w,data) }) fmt.Println("startingwebserverathttp://localhost:8080/") http.ListenAndServe(":8080",nil) } 212 Web Jalankan,lalubukahttp://localhost:8080/,makadata Namadan Messageakanmunculdi view. Fungsi template.ParseFiles()digunakanuntukparsingtemplate,mengembalikan2data yaituinstancetemplate-nyadanerror(jikaada).Pemanggilanmethod Execute()akan membuathasilparsingtemplateditampilkankelayarwebbrowser. 213 URLParsing URLParsing Datastringurlbisadikonversikedalambentuk url.URL.Tipetersebutberisikanbanyak informasiyangbisadiakses,diantaranyaadalahjenisprotokolyangdigunakan,pathyang diakses,query,danlainnya. Berikutadalahcontohsederhanakonversistringke url.URL. packagemain import"fmt" import"net/url" funcmain(){ varurlString="http://depeloper.com:80/hello?name=johnwick&age=27" varu,e=url.Parse(urlString) ife!=nil{ fmt.Println(e.Error()) } fmt.Printf("url:%s\n",urlString) fmt.Printf("protocol:%s\n",u.Scheme)//http fmt.Printf("host:%s\n",u.Host)//depeloper.com:80 fmt.Printf("path:%s\n",u.Path)///hello varname=u.Query()["name"][0]//johnwick varage=u.Query()["age"][0]//27 fmt.Printf("name:%s,age:%s\n",name,age) } Fungsi url.Parse()digunakanuntukparsingstringkebentukurl.Mengembalikan2data, variabelobjekbertipe url.URLdanerror(jikaada).Lewatvariabelobjektersebut pengaksesaninformasiurlakanmenjadilebihmudah,contohnyasepertinamahostbisa didapatkanlewat u.Host,protokollewat u.Scheme,danlainnya. Selainitu,queryyangadapadaurlakanotomatisdiparsingjuga,menjadibentuk map[string][]string,dengankeyadalahnamaelemenquery,danvaluearraystringyang berisikanvalueelemenquery. 214 URLParsing 215 JSON JSON JSONatauJavascriptObjectNotationadalahnotasistandaryangumumdigunakanuntuk komunikasidataviaweb.JSONmerupakansubsetdarijavascript. Golangmenyediakanpackage encoding/jsonyangberisikanbanyakfungsiuntuk kebutuhanoeprasijson. Dibabini,kitaakanbelajarcarauntukkonverstristringyangberbentukjsonmenjadiobjek golang,dansebaliknya. DecodeJSONKeVariabelObjekCetakan Struct Datajsontipenyaadalah []byte,bisadidapatdarifileataupunstring(denganhasil casting).Denganmenggunakan json.Unmarshal,datatersebutbisadikonversimenjadi bentukobjek,entahitudalambentuk map[string]interface{}ataupunvariabelobjekhasil struct. Programberikutiniadalahcontohcaradecodingjsonkebentukobjek.Pertamaimport packageyangdibutuhkan,dansiapkanstruct User. packagemain import"encoding/json" import"fmt" typeUserstruct{ FullNamestring`json:"Name"` Ageint } Hasildecodenantinyaakandisimpankevariabelobjekcetakanstruct User. Selanjutnyasiapkandatajsonstringsederhana,gunakancastingke []byteagardideteksi sebagaidatajson. 216 JSON funcmain(){ varjsonString=`{"Name":"johnwick","Age":27}` varjsonData=[]byte(jsonString) vardataUser varerr=json.Unmarshal(jsonData,&data) iferr!=nil{ fmt.Println(err.Error()) } fmt.Println("user:",data.FullName) fmt.Println("age:",data.Age) } Dalampenggunaanfungsi json.Unmarshal,variabelyangakanmenampunghasildecode harusdi-passingsebagaipointer( &data). Padakodediatasbisadilihatbahwasalahsatuproprtystruct Useradayangmemilikitag, yaitu FullName.Tagtersebutdigunakanuntukmappingdatajsonkepropertyyang bersangkutan. Datajsonyangakandiparsingmemiliki2propertyyaitu Namedan Age.Kebetulan penulisan Agepadadatajsondanpadastrukturstructadalahsama,berbedadengan Nameyangtidakadapadastruct. Property FullNamestructtersebutkemudianditugaskanuntukmenampungdatajson property Name,ditandaidenganpenambahantag json:"Name"padasaatdeklarasistructnya. Perludiketahuibahwauntukdecodedatajsonkevariabelobjekhasilstruct,semualevel aksespropertystruct-nyaharuspublik. DecodeJSONKe map[string]interface{}& interface{} Selainkevariabelobjek,targetdecodingdatajsonjugabisaberupavariabelbertipe map[string]interface{}. 217 JSON vardata1map[string]interface{} json.Unmarshal(jsonData,&data1) fmt.Println("user:",data1["Name"]) fmt.Println("age:",data1["Age"]) Selainitu, interface{}jugabisadigunakanuntukmenampunghasildecode.Dengan catatanpadapengaksesannilaiproperty,harusdilakukancastingterlebihdahuluke map[string]interface{}. vardata2interface{} json.Unmarshal(jsonData,&data2) vardecodedData=data2.(map[string]interface{}) fmt.Println("user:",decodedData["Name"]) fmt.Println("age:",decodedData["Age"]) DecodeArrayJSONKeArrayObjek Jikadatajsonadalaharrayberisikanobjek,makavariabelpenampungharusbertipearray denganisipointerobjek.Padapemanggilan json.Unmarshal,variabeltersebutjugadipassing-kansebagaipointer.Contoh: varjsonString=`[ {"Name":"johnwick","Age":27}, {"Name":"ethanhunt","Age":32} ]` vardata[]*User varerr=json.Unmarshal([]byte(jsonString),&data) iferr!=nil{ fmt.Println(err.Error()) } fmt.Println("user1:",data[0].FullName) fmt.Println("user2:",data[1].FullName) EncodeObjekKeJSON Setelahsebelumnyadijelaskanbeberapacaradecodedatadarijsonkeobjek,sekarangkita akanbelajarcaraencodedatakebentukjson. 218 JSON Fungsi json.Marshaldigunakanuntukdecodingdatakejson.Datatersebutbisaberupa variabelobjekcetakanstruct, map[string]interface{},bisajugabertipearray. Padacontohberikut,dataarraystructakandikonversikedalambentukjson.Hasilkonversi jsonbisaditampilkandengandi-castingterlebihdahulukestring. varobject=[]User{{"johnwick",27},{"ethanhunt",32}} varjsonData,err=json.Marshal(object) iferr!=nil{ fmt.Println(err.Error()) } varjsonString=string(jsonData) fmt.Println(jsonString) Hasilencodeadalahdatabertipe []byte.Castingke stringbisadigunakanuntuk menampilkandata. 219 WebJSONAPI WebAPIJSON Padababinikitaakanmengkombinasikanpembahasan2babsebelumnya,yaituwebdan JSON,untukmembuatsebuahwebAPIdengantipedatareponseberbentukJSON. WebAPIadalahsebuahwebyangmenerimarequestdariclientdanmenghasilkan response,biasaberupaJSON/XML. PembuatanWebAPI Pertamasiapkanterlebihdahulustructdanbeberapadatasample. packagemain import"encoding/json" import"net/http" import"fmt" typestudentstruct{ IDstring Namestring Gradeint } vardata=[]student{ student{"E001","ethan",21}, student{"W001","wick",22}, student{"B001","bourne",23}, student{"B002","bond",23}, } Struct studentdiatasdigunakansebagaitipeelemenarraysampledatayangditampung olehvariabel data. Selanjutnyabuatfungsi users()untukhandlerute /users.Didalamfungsitersebutada prosesdeteksijenisrequestlewatproperty r.Method(),untukmencaritahuapakahjenis requestadalahPOSTatauGETataulainnya. 220 WebJSONAPI funcusers(whttp.ResponseWriter,r*http.Request){ w.Header().Set("Content-Type","application/json") ifr.Method=="POST"{ varresult,err=json.Marshal(data) iferr!=nil{ http.Error(w,err.Error(),http.StatusInternalServerError) return } w.Write(result) return } http.Error(w,"",http.StatusBadRequest) } JikarequestadalahPOST,makadatayangdi-encodekeJSONdijadikansebagairesponse. Statement w.Header().Set("Content-Type","application/json")digunakanuntuk menentukantiperesponse,yaitusebagaiJSON.Sedangkan r.Write()digunakanuntuk mendaftarkandatasebagairesponse. Selebihnya,jikarequesttidakvalid,responsedisetsebagaierrormenggunakanfungsi http.Error(). Siapkanjugahandleruntukrute /user.Perbedaanruteinidenganrute /usersdiatas adalah: /usersmenghasilkansemuasampledatayangada(array). /usermenghasilkansatubuahdatasaja,diambeldaridatasampleberdasarkan ID- nya.Padaruteini,clientharusmengirimkanjugainformasi IDdatayangdicari. 221 WebJSONAPI funcuser(whttp.ResponseWriter,r*http.Request){ w.Header().Set("Content-Type","application/json") ifr.Method=="POST"{ varid=r.FormValue("id") varresult[]byte varerrerror for_,each:=rangedata{ ifeach.ID==id{ result,err=json.Marshal(each) iferr!=nil{ http.Error(w,err.Error(),http.StatusInternalServerError) return } w.Write(result) return } } http.Error(w,"Usernotfound",http.StatusBadRequest) return } http.Error(w,"",http.StatusBadRequest) } Method r.FormValue()digunakanuntukmengambildatapayloadyangdikirimdariclient, padakonteksinidatayangdimaksudadalah ID. Denganmenggunakan IDtersebutdicarilahdatayangrelevan.Jikaada,maka dikembalikansebagairesponse.Jikatidakadamakaerror400,BadRequestdikembalikan denganpesanUserNotFound. Terakhir,implementasikankeduahandlerdiatas. funcmain(){ http.HandleFunc("/users",users) http.HandleFunc("/user",user) fmt.Println("startingwebserverathttp://localhost:8080/") http.ListenAndServe(":8080",nil) } Jalankanprogram,makawebserversudahlivedanbisadikonsumsidatanya. 222 WebJSONAPI TestAPI Setelahwebserversudahberjalan,webAPIyangtelahdibuatperluuntukdites.Disini sayamenggunakanGo*gleChromepluginbernamaPostmanuntukmengetesAPIyang sudahdibuat. Test /users,apakahdatayangdikembalikansudahbenar. Test /userdengandatapayload idadalah E001. 223 WebJSONAPI 224 HTTPRequest HTTPRequest SetelahdibabsebelumnyakitabelajartentangbagaimanamembuatWebAPIyang menyediakandatadalambentukJSON,padababinikitaakanbelajarmengenaicarauntuk mengkonsumsidatatersebut. Pastikanandasudahmempraktekkanapa-apayangadapadababsebelumnya(bab51), karenawebapiserveryangsudahdibahaspadababtersebutdigunakanjugapadababini. PenggunaanHTTPRequest Package net/http,selainberisikantoolsuntukkeperluanpembuatanweb,jugaberisikan fungsi-fungsiuntukmelakukanhttprequest.Salahsatunyaadalah http.NewRequest()yang akankitabahasdisini. Sebelumnya,importpackageyangdibutuhkan.Dansiapkanstruct studentyangnantinya akandipakaisebagaitipedatareponsedariwebAPI.Struktersebutskemanyasama denganyangadapadabab51. packagemain import"fmt" import"net/http" import"encoding/json" varbaseURL="http://localhost:8080" typestudentstruct{ IDstring Namestring Gradeint } Setelahitubuatfungsi fetchUsers().Fungsiinibertugasmelakukanrequestke http://localhost:8080/users,menerimaresponsedarirequesttersebut,lalumenampilkannya. 225 HTTPRequest funcfetchUsers()[]*student{ varerrerror varclient=&http.Client{} vardata[]*student request,err:=http.NewRequest("POST",baseURL+"/users",nil) iferr!=nil{ fmt.Println(err.Error()) returndata } response,err:=client.Do(request) iferr!=nil{ fmt.Println(err.Error()) returndata } deferresponse.Body.Close() err=json.NewDecoder(response.Body).Decode(&data) iferr!=nil{ fmt.Println(err.Error()) returndata } returndata } Statement &http.Client{}menghasilkaninstance http.Client.Objekininantinya diperlukanuntukeksekusirequest. Fungsi http.NewRequest()digunakanuntukmembuatrequestbaru.Fungsitersebut memiliki3parameteryangwajibdiisi. 1. Parameterpertama,berisikantiperequestPOSTatauGETataulainnya 2. Parameterkedua,adalahURLtujuanrequest 3. Parameterketiga,payloadrequest(jikaada) Fungsitersebutmenghasilkaninstancebertipe http.Request.Objektersebutnantinya disisipkanpadasaateksekusirequest. Caraeksekusirequestsendiriadalahdenganmemanggilmethod Do()padainstance http.Clientyangsudahdibuat,denganparameteradalahinstancerequest-nya. Contohnyasepertipada client.Do(request). Methodtersebutmengembalikaninstancebertipe http.Response,yangdidalamnya berisikaninformasiyangdikembalikandariwebAPI. 226 HTTPRequest Dataresponsebisadiambillewatproperty Bodydalambentukstring.GunakanJSON DecoderuntukmengkonversinyamenjadibentukJSON.Contohnyabisadilihatdikodedi atas, json.NewDecoder(response.Body).Decode(&data).Setelahitubarulahkitabisa menampilkannya. Perludiketahui,dataresponseperludi-closesetelahtidakdipakai.Caranyasepertipada kode deferresponse.Body.Close(). Implementasikanfungsi fetchUsers()diataspada main. funcmain(){ varusers=fetchUsers() for_,each:=rangeusers{ fmt.Printf("ID:%s\tName:%s\tGrade:%d\n",each.ID,each.Name,each.Grade) } } Jalankanprogramuntukmengeteshasilnya. HTTPRequestDenganPayload Untukmenyisipkandatapadasebuahrequest,adabeberapahalyangperluditambahkan. Yangpertama,importbeberapapackagelagi, bytesdan net/url. import"bytes" import"net/url" Buatfungsibarudenganisiadalahsebuahrequestkehttp://localhost:8080/userdengan datayangdisisipkanadalah ID. 227 HTTPRequest funcfetchUser(IDstring)student{ varerrerror varclient=&http.Client{} vardatastudent varparam=url.Values{} param.Set("id",ID) varpayload=bytes.NewBufferString(param.Encode()) request,err:=http.NewRequest("POST",baseURL+"/user",payload) iferr!=nil{ fmt.Println(err.Error()) returndata } request.Header.Set("Content-Type","application/x-www-form-urlencoded") response,err:=client.Do(request) iferr!=nil{ fmt.Println(err.Error()) returndata } deferresponse.Body.Close() err=json.NewDecoder(response.Body).Decode(&data) iferr!=nil{ fmt.Println(err.Error()) returndata } returndata } Isifungsidiatasbisadilihatmemilikibeberapakemiripandenganfungsi fetchUsers() sebelumnya. Statement url.Values{}akanmenghasilkanobjekyangnantinyadigunakansebagai payloadrequest.Padaobjektersebutperludisetdataapasajayangingindikirimkan menggunakanfungsi Set()sepertipada param.Set("id",ID). Statement bytes.NewBufferString(param.Encode())maksudnya,objekpayloaddi-encode laludiubahmenjadibentuk bytes.Buffer,yangnantinyadisisipkanpadaparameterketiga pemanggilanfungsi http.NewRequest(). Karenadatayangakandikirimdi-encode,makapadaheaderperludisettipekonten request-nya.Kode request.Header.Set("Content-Type","application/x-www-formurlencoded")artinyatipekontenrequestdisetsebagai application/x-www-form-urlencoded. 228 HTTPRequest PadakonteksHTML,HTTPRequestyangditriggerdaritag <form></form>secara defaulttipekonten-nyasudahdiset application/x-www-form-urlencoded.Lebih detailnyabisamerujukkespesifikasiHTMLform http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.1 Responsedarirute /userbukanberupaarrayobjek,melainkansebuahobjek.Makapada saatdecodepastikantipevariabelpenampunghasildecodedataresponseadalah student bukan []*student. Terakhirbuatimplementasinyapadafungsi main. funcmain(){ varuser1=fetchUser("E001") fmt.Printf("ID:%s\tName:%s\tGrade:%d\n",user1.ID,user1.Name,user1.Grade) } Padakodediatas IDditentukannilainyaadalah "E001".Jalankanprogramuntuk mengetesapakahdatayangdikembalikansesuai. 229 SQL SQL Golangmenyediakanpackage database/sqlberisikangenericinterfaceuntukkeperluan interaksidengandatabasesql.Packageinihanyabisadigunakanketikadriverdatabase engineyangdipilihjugaada. AdacukupbanyaksqldriveryangtersediauntukGolang,detailnyabisadiaksesdi https://github.com/golang/go/wiki/SQLDrivers.Beberapadiantaranya: MySql Oracle MSSqlServer danlainnya Driver-drivertersebutmerupakanproyekopensourceyangdiinisiasiolehkomunitasdi Github.Artinyakitaselakudeveloperjugabisaikutberkontribusididalamnya. PadababinikitaakanbelajarbagaimanberkomunikasidengandatabaseMySQL menggunakandriverGo-MySQL-Driver. InstalasiDriver Undahdrivergithub.com/go-sql-driver/mysqlmenggunakan goget. gogetgithub.com/go-sql-driver/mysql SetupDatabase Sebelumnyapastikansudahadamysqlserveryangterinstaldilokalanda. 230 SQL Buatdatabasebarubernama db_belajar_golang,dansebuahtabelbarubernama tb_student. CREATETABLEIFNOTEXISTS`tb_student`( `id`varchar(5)NOTNULL, `name`varchar(255)NOTNULL, `age`int(11)NOTNULL, `grade`int(11)NOTNULL )ENGINE=InnoDBDEFAULTCHARSET=latin1; INSERTINTO`tb_student`(`id`,`name`,`age`,`grade`)VALUES ('B001','JasonBourne',29,1), ('B002','JamesBond',27,1), ('E001','EthanHunt',27,2), ('W001','JohnWick',28,2); ALTERTABLE`tb_student`ADDPRIMARYKEY(`id`); MembacaDataDariMySQLServer Yangpertamaperludisiapkanadalahmeng-importpackageyangdibutuhkan.Juga,perlu disiapkansebuahstructdenganskemayangsamasepertipada tb_studentdidatabase. Nantinyastructinidigunakansebagaitipedatapenampunghasilquery. packagemain import"fmt" import"database/sql" import"os" import_"github.com/go-sql-driver/mysql" typestudentstruct{ idstring namestring ageint gradeint } Driverdatabaseyangdigunakanperludi-importmenggunakantanda _,karenameskipun dibutuhkanolehpackage database/sql,kitatidaklangsungberinteraksidengandriver tersebut. Selanjutnyabuatfungsiuntukkoneksikedatabase. 231 SQL funcconnect()*sql.DB{ vardb,err=sql.Open("mysql","root@tcp(127.0.0.1:3306)/db_belajar_golang") iferr!=nil{ fmt.Println(err.Error()) os.Exit(0) } returndb } Fungsi sql.Open()digunakanuntukmemulaikoneksidengandatabase.Fungsitersebut memiliki2parametermandatory,namadriverdanconnectionstring. Skemaconnectionstringuntukdrivermysqlyangkitagunakancukupunik, root@tcp(127.0.0.1:3306)/db_belajar_golang. Agartidakbingung,silakanperhatikanskemaconnectionstringdibawahini. user:password@tcp(host:port)/dbname user@tcp(host:port)/dbname Berikutadalahpenjelasanmengenaiconnectionstringyangdigunakanpadafungsi connect(). root@tcp(127.0.0.1:3306)/db_belajar_golang //user=>root //password=> //host=>127.0.0.1ataulocalhost //port=>3306 //dbname=>db_belajar_golang Setelahfungsiuntukkonektivitasdengandatabasesudahdibuat,saatnyauntuk mempraktekanprosespembacaandatadariserverdatabase. Siapkanfungsi sqlQuery()denganisiadalahkodeberikut. 232 SQL funcsqlQuery(){ vardb=connect() deferdb.Close() varage=27 varrows,err=db.Query("selectid,name,gradefromtb_studentwhereage=?",a ge) iferr!=nil{ fmt.Println(err.Error()) os.Exit(0) } deferrows.Close() varresult[]student forrows.Next(){ vareach=student{} varerr=rows.Scan(&each.id,&each.name,&each.grade) iferr!=nil{ fmt.Println(err.Error()) os.Exit(0) } result=append(result,each) } iferr=rows.Err();err!=nil{ fmt.Println(err.Error()) os.Exit(0) } for_,each:=rangeresult{ fmt.Println(each.name) } } Setiapkaliterbuatkoneksibaru,janganlupauntukselalucloseinstancekoneksinya.Bisa menggunakankeyword defersepertipadakodediatas, deferdb.Close(). Fungsi db.Query()digunakanuntukeksekusisqlquery.Fungsitersebutparameter keduanyaadalahvariadic,sehinggabolehtidakdiisi.Padakodediatasbisadilihatbahwa nilaisalahsatuclause whereadalahtandatanya( ?).Tandatersebutkemudianakanterreplaceolehnilaipadaparametersetelahnya(nilaivariabel age).Teknikpenulisanquery sejenisinisangatdianjurkan,untukmencegahterjadinyasqlinjection. Fungsitersebutmenghasilkaninstancebertipe sql.*Rows,yangjugaperludicloseketika sudahtidakdigunakan( deferrows.Close()). 233 SQL Selanjutnya,sebuaharraydengantipeelemenstruct studentdisiapkandengannama result.Nantinyahasilqueryakanditampungkevariabeltersebut. Kemudiandilakukanperulangandenganacuankondisiadalah rows.Next().Perulangan dengancarainidilakukansebanyakjumlahtotalrecordyangada,berurutandarirecord pertamahinggaakhir,satupersatu. Method Scan()milik sql.Rowsberfungsiuntukmengambilnilairecordyangsedang diiterasi,untukdisimpanpadavariabel.Variabelyangdigunakanuntukmenyimpanfield-field recorddituliskanberurutannilaipointernyasebagaiparametervariadicfungsitersebut, sesuaidenganfieldyangdiselectpadaquery. //query selectid,name,grade... //scan rows.Scan(&each.id,&each.name,&each.grade... Setelahitu,datadi-appendkedalamarray resultlewatstatement result=append(result, each). Setelahfungsi sqlQuery()siap,implementasikanpadapadafungsi main. funcmain(){ sqlQuery() } Membaca1RecordDataMenggunakanMethod QueryRow() Untukqueryyangmenghasilkan1barisrecordsaja,bisagunakanmethod QueryRow() untukeksekusiquery-nya,denganmetodeinikodemenjadilebihringkas.Chaindengan method Scan()untukmendapatkanvalue-nya. 234 SQL funcsqlQueryRow(){ vardb=connect() deferdb.Close() varresult=student{} varid="E001" varerr=db.QueryRow("selectname,gradefromtb_studentwhereid=?",id).Scan( &result.name,&result.grade) iferr!=nil{ fmt.Println(err.Error()) os.Exit(0) } fmt.Printf("name:%s\ngrade:%d\n",result.name,result.grade) } funcmain(){ sqlQueryRow() } EksekusiQueryMenggunakan Prepare() Teknikpreparedstatementadalahteknikpenulisanquerydiawaldengankelebihanbisadi re-useataudigunakanbanyakkaliuntukeksekusiyangberbeda-beda. Metodeinibisadigabungdengan Query()maupun QueryRow(). Berikutmerupakancontohpenerapannya. 235 SQL funcsqlPrepare(){ vardb=connect() deferdb.Close() varstatement,err=db.Prepare("selectname,gradefromtb_studentwhereid=?") iferr!=nil{ fmt.Println(err.Error()) os.Exit(0) } varresult1=student{} statement.QueryRow("E001").Scan(&result1.name,&result1.grade) fmt.Printf("name:%s\ngrade:%d\n",result1.name,result1.grade) varresult2=student{} statement.QueryRow("W001").Scan(&result2.name,&result2.grade) fmt.Printf("name:%s\ngrade:%d\n",result2.name,result2.grade) varresult3=student{} statement.QueryRow("B001").Scan(&result3.name,&result3.grade) fmt.Printf("name:%s\ngrade:%d\n",result3.name,result3.grade) } funcmain(){ sqlPrepare() } Method Prepare()digunakanuntukdeklarasiquery,yangmengembalikanobjekbertipe sql.*Stmt.Dariobjektersebut,dipanggilmethod QueryRow()beberapakalidenganisi valueuntuk idberbeda-bedauntuktiappemanggilannya. Insert,Update,&DeleteDataMenggunakan Exec() Untukoperasiinsert,update,dandelete;dianjurkanuntuktidakmenggunakanfungsi sql.Query()ataupun sql.QueryRow()untukeksekusinya.Direkomendasikaneksekusi perintah-perintahtersebutlewatfungsi Exec(),contohnyasepertipadakodeberikut. 236 SQL funcsqlExec(){ vardb=connect() deferdb.Close() varerrerror _,err=db.Exec("insertintotb_studentvalues(?,?,?,?)","G001","Galahad", 29,2) iferr!=nil{ fmt.Println(err.Error()) } _,err=db.Exec("updatetb_studentsetage=?whereid=?",28,"G001") iferr!=nil{ fmt.Println(err.Error()) } _,err=db.Exec("deletefromtb_studentwhereid=?","G001") iferr!=nil{ fmt.Println(err.Error()) } } funcmain(){ sqlExec() } Teknikpreparedstatementjugabisadigunakanpadametodeini.Berikutmerupakan perbandinganeksekusi Exec()menggunakan Prepare()dancarabiasa. //menggunakanmetodepreparedstatement varstmt,_=db.Prepare("insertintotb_studentvalues(?,?,?,?)") stmt.Exec("G001","Galahad",29,2) //menggunakanmetodebiasa _,_=db.Exec("insertintotb_studentvalues(?,?,?,?)","G001","Galahad",29,2) KoneksiDenganEngineDatabaseLain Karenapackage database/sqlmerupakaninterfacegeneric,makacarauntukkoneksike enginedatabaselain(semisalOracle,Postgres,SQLServer)adalahsamadengancara koneksikeMySQL.Cukupdenganmeng-importdriveryangdigunakan,lalumengganti namadriverpadasaatpembuatankoneksibaru. sql.Open(driverName,connectionString) 237 SQL SebagaicontohsayamenggunakandriverpquntukkoneksikeserverPostgres,maka connectionstring-nya: sql.Open("pq","user=postgrespassword=secretdbname=testsslmode=disable") Selengkapyamengenaidriveryangtersediabisadilihatdi https://github.com/golang/go/wiki/SQLDrivers 238 MongoDB NoSQLMongoDB GolangtidakmenyediakaninterfacegenericuntukNoSQL,halinimenjadikandrivertiap brandNoSQLuntukGolangbisaberbedasatudenganlainnya. DarisekianbanyakteknologiNoSQLyangada,yangterpilihuntukdibahasdibukuini adalahMongoDB.DanpadababinikitaakanbelajarcaraberkomunikasidenganMongoDB menggunakandrivermgo. Persiapan Adabeberapahalyangperludisiapkansebelummulaimasukkebagiancoding. 1. Instalmgomenggunakan goget. gogetgopkg.in/mgo.v2 2. PastikansudahterinstalMongoDBdikomputeranda,danjanganlupauntuk menjalankandaemon-nya.Jikabelum,downloaddaninstallterlebihdahulu. 3. InstaljugaMongoDBGUIuntukmempermudahbrowsingdata.Bisamenggunakan MongoChef,Robomongo,ataulainnya. InsertData Carainsertdatalewatmongotidakterlalusulit.Yangpertamaperludilakukanadalahimport packageyangdibutuhkan,danjugamenyiapkanstructmodel. packagemain import"fmt" import"gopkg.in/mgo.v2" import"os" typestudentstruct{ Namestring`bson:"name"` Gradeint`bson:"Grade"` } 239 MongoDB Tag bsonpadapropertystructdalamkonteksmgo,digunakansebagaipenentunamafield ketikadatadisimpankedalamcollection.Jikasebuahpropertytidakmemilikitagbson, secaradefaultnamafieldadalahsamadengannamapropertyhanyasajalowercase.Untuk customizenamafield,gunakantag bson. Padacontohdiatas,property Nameditentukannamafieldnyasebagai name,dan Grade sebagai Grade. Selanjutnyasiapkanfungsiuntukmembuatsessionbaru. funcconnect()*mgo.Session{ varsession,err=mgo.Dial("localhost") iferr!=nil{ os.Exit(0) } returnsession } Fungsi mgo.Dial()digunakanuntukmembuatsessionbaru(bertipe *mgo.Session).Fungsi tersebutmemilikisebuahparameteryangharusdiisi,yaituconnectionstringdariserver mongoyangakandiakses. Secaradefaultjeniskonsistensisessionyangdigunakanadalah mgo.Primary.Andabisa mengubahnyalewatmethod SetMode()milikstruct mgo.Session.Lebihjelasnyasilakan merujukhttps://godoc.org/gopkg.in/mgo.v2#Session.SetMode. Terkahirbuatfungsiinsertyangdidalamnyaberisikankodeuntukinsertdatakemongodb, laluimplementasikandi main. funcinsert(){ varsession=connect() defersession.Close() varcollection=session.DB("belajar_golang").C("student") varerr=collection.Insert(&student{"Wick",2},&student{"Ethan",2}) iferr!=nil{ fmt.Println(err.Error()) } } funcmain(){ insert() } 240 MongoDB Sessiondimgojugaharusdicloseketikasudahtidakdigunakan,sepertipadainstance connectiondibabSQL.Statement defersession.Close()akanmengakhirkanprosesclose sessiondalamfungsi insert(). Struct mgo.Sessionmemilikimethod DB()yangdigunakanuntukmemilihdatabaseyang digunakan,danbisalangsungdichaindenganfungsi C()untukmemilihcollection. Setelahmendapatkaninstancecollection-nya,digunakanmethod Insert()untukinsert datakedatabase.Methodinimemilikiparametervariadicpointerdatayangingindi-insert. Jalankanprogramtersebut,lalucekmenggunakanmongoGUIuntukmelihatapakahdata sudahmasuk. MembacaData method Find()miliktipecollection mgo.Collectiondigunakanuntukmelakukan pembacaandata.Queryselectornyadituliskanmenggunakan bson.Mlaludisisipkan sebagaiparameterfungsi Find(). Untukmenggunakan bson.M,package gopkg.in/mgo.v2/bsonharusdi-importterlebih dahulu. import"gopkg.in/mgo.v2/bson" Setelahitubuatfungsi findyangdidalamnyaterdapatprosesbacadatadaridatabase. 241 MongoDB funcfind(){ varsession=connect() defersession.Close() varcollection=session.DB("belajar_golang").C("student") varresult=student{} varselector=bson.M{"name":"Wick"} varerr=collection.Find(selector).One(&result) iferr!=nil{ fmt.Println(err.Error()) } fmt.Println("Name:",result.Name) fmt.Println("Grade:",result.Grade) } funcmain(){ find() } Variabel resultdi-inisialisasimenggunakanstruct student.Variabeltersebutnantinya digunakanuntukmenampunghasilpencariandata. Tipe bson.Msebenarnyaadalahaliasdari map[string]interface{},digunakandalam penulisanselector. Selectortersebutkemudiandimasukansebagaiparametermethod Find(),yangkemudian dichainlangsungdenganmethod One()untukmengambil1barisdatanya.Kemudian pointervariabel resultdisisipkansebagaiparametermethodtersebut. UpdateData Method Update()milikstruct mgo.Collectiondigunakanuntukupdatedata.Ada2 parameteryangharusdiisi: 1. Parameterpertamaadalahqueryselectordatayangingindiupdate 2. Parameterkeduaadalahdataperubahannya 242 MongoDB funcupdate(){ varsession=connect() defersession.Close() varcollection=session.DB("belajar_golang").C("student") varselector=bson.M{"name":"Wick"} varchanges=student{"JohnWick",2} varerr=collection.Update(selector,changes) iferr!=nil{ fmt.Println(err.Error()) } } funcmain(){ update() } BisadiceklewatMongoGUIapakahdatasudahberubah. MenghapusData Caramenghapusdocumentpadacollectioncukupmudah,tinggalgunakanmethod Remove()denganisiparameteradalahqueryselectordocumentyangingindihapus. funcremove(){ varsession=connect() defersession.Close() varcollection=session.DB("belajar_golang").C("student") varselector=bson.M{"name":"JohnWick"} varerr=collection.Remove(selector) iferr!=nil{ fmt.Println(err.Error()) } } funcmain(){ remove() } 243 MongoDB 2datayangsebelumnyasudahdi-insertkinitinggalsatusaja. 244 AutomatedTest AutomatedTesting Golangmenyediakanpackage testing,yangberisikanbanyaksekalitoolsuntukkeperluan automationtesting. Padababinikitaakanbelajarmengenaitesting,benchmark,danjugatestingmenggunakan testify. Persiapan Pertamasiapkanterlebihdahulusebuahstruct Kubus.Variabelobjecthasilstructini nantinyakitagunakansebagaibahantesting. packagemain import"math" typeKubusstruct{ Sisifloat64 } func(kKubus)Volume()float64{ returnmath.Pow(k.Sisi,3) } func(kKubus)Luas()float64{ returnmath.Pow(k.Sisi,2)*6 } func(kKubus)Keliling()float64{ returnk.Sisi*12 } Kodediatassayasimpankefilebernama bab55.go. Testing Fileuntukkeperluantestingterpisahdenganfileutama,namanyaharusberakhiran _test.go,danpackage-nyaharussama.Padababini,fileutamaadalah bab55.go,maka filetestingsayaberinama bab55_test.go. 245 AutomatedTest TestingdiGolangdituliskandalambentukfungsi,sebagaicontohjikaada2fungsimakaada 2test.FungsitersebutnamanyaharusdiawalidenganTestdanmemilikiparameteryang bertipe *testing.T(pastikansudahmeng-importpackage testingsebelumnya).Lewat parametertersebut,kitabisamengaksesmethod-methoduntukkeperluantesting. Padacontohdibawahinidisiapkan3buahfungsitest,yangmasing-masingdigunakan untukmengecekapakahhasilkalkulasivolume,luas,dankelilingkubusadalahbenar. packagemain import"testing" var( kubusKubus=Kubus{4} volumeSeharusnyafloat64=64 luasSeharusnyafloat64=96 kelilingSeharusnyafloat64=48 ) funcTestHitungVolume(t*testing.T){ t.Logf("Volume:%.2f",kubus.Volume()) ifkubus.Volume()!=volumeSeharusnya{ t.Errorf("SALAH!harusnya%.2f",volumeSeharusnya) } } funcTestHitungLuas(t*testing.T){ t.Logf("Luas:%.2f",kubus.Luas()) ifkubus.Luas()!=luasSeharusnya{ t.Errorf("SALAH!harusnya%.2f",luasSeharusnya) } } funcTestHitungKeliling(t*testing.T){ t.Logf("Keliling:%.2f",kubus.Keliling()) ifkubus.Keliling()!=kelilingSeharusnya{ t.Errorf("SALAH!harusnya%.2f",kelilingSeharusnya) } } Method t.Logf()digunakanuntukmemunculkanlog.Methodiniequivalendengan fmt.Printf(). Method Errorf()digunakanuntukmemunculkanlogdengandiikutiketeranganbahwa terjadifailpadasaattesting. 246 AutomatedTest Jalankanaplikasi,makaakanterlihatbahwatidakadafail. Caraeksekusitestingadalahmenggunakancommand gotest.Karenastructyangdiuji beradadalamfile bab55.go,makapadasaateksekusitestmenggunakan gotest,nama file bab55_test.godan bab55.goperludituliskansebagaiargument. Argument -vatauverbosedigunakanmenampilkansemuaoutputlogpadasaat pengujian. OK,selanjutnyacobaubahrumuskalkulasimethod Keliling().Tujuandaripengubahan iniadalahuntukmengetahuibagaimanapenandafailmunculketikaadatestyanggagal. func(kKubus)Keliling()float64{ returnk.Sisi*15 } Setelahitujalankanlagitest. MethodTest TableberikutberisikanmethodstandartestingyangbisadigunakandiGolang. 247 AutomatedTest Method Kegunaan Log() Menampilkanlog Logf() Menampilkanlogmenggunakanformat Fail() Menandakanterjadi Fail()danprosestestingfungsitetapditeruskan FailNow() Menandakanterjadi Fail()danprosestestingfungsidihentikan Failed() Menampilkanlaporanfail Error() Log()diikutidengan Fail() Errorf() Logf()diikutidengan Fail() Fatal() Log()diikutidengan failNow() Fatalf() Logf()diikutidengan failNow() Skip() Log()diikutidengan SkipNow() Skipf() Logf()diikutidengan SkipNow() SkipNow() Menghentikanprosestestingfungsi,dilanjutkanketestingfungsi setelahnya Skiped() Menampilkanlaporanskip Parallel() Menge-setbahwaeksekusitestingadalahparallel Benchmark Package testingselainberisikantoolsuntuktestingjugaberisikantoolsuntuk benchmarking.Carapembuatanbenchmarksendiricukupmudahyaitudenganmembuat fungsiyangnamanyadiawalidenganBenchmarkdanparameternyabertipe *testing.B. Sebagaicontoh,kitaakanmengetesperformaperhitunganluaskubus.Siapkanfungsi dengannama BenchmarkHitungLuas()denganisiadalahkodeberikut. funcBenchmarkHitungLuas(b*testing.B){ fori:=0;i<b.N;i++{ kubus.Luas() } } Jalankantestmenggunakanargument -bench=.,argumeninidigunakanuntukmenandai bahwaselaintestingterdapatjugabenchmarkyangperludiuji. 248 AutomatedTest 3000000051.1ns/opartinyaadalahperulangandiatasdilakukansebanyak30jutakali, dalamwaktu51nanodetikuntuktiapperulangannya. TestingMenggunakantestify Packagetestifyberisikanbanyaksekalitoolsyangbisadimanfaatkanuntukkeperluan testingdiGolang. Testifybisadi-downloadpadagithub.com/stretchr/testifymenggunakan goget. Didalamtestifyterdapat5packagedengankegunaanberbeda-bedasatudenganlainnya. Detailnyabisadilihatpadatabelberikut. Package Kegunaan assert Berisikantoolsstandaruntuktesting http Berisikantoolsuntukkeperluantestinghttp mock Berisikantoolsuntukmockingobject require Samasepertiassert,hanyasajajikaterjadifailpadasaattestakan menghentikaneksekusiprogram suite Berisikantoolstestingyangberhubungandenganstructdanmethod Padababiniakankitacontohkanbagaimanapenggunaanpackageassertuntukkeperluan testing.Caranyacukupmudah,contohnyabisadilihatpadakodeberikut. 249 AutomatedTest import"github.com/stretchr/testify/assert" ... funcTestHitungVolume(t*testing.T){ assert.Equal(t,kubus.Volume(),volumeSeharusnya,"perhitunganvolumesalah") } funcTestHitungLuas(t*testing.T){ assert.Equal(t,kubus.Luas(),luasSeharusnya,"perhitunganluassalah") } funcTestHitungKeliling(t*testing.T){ assert.Equal(t,kubus.Keliling(),kelilingSeharusnya,"perhitungankelilingsalah" ) } Fungsi assert.Equal()digunakanuntukujiperbandingan.Parameterke-2dibandingkan nilainyadenganparameterke-3.Jikatidaksama,makapesanparameterke-3akan dimunculkan. 250 WaitGroup WaitGroup Sebelumnyakitatelahbelajarbanyakmengenaichannel,bagaimanasebuah/banyak goroutinedapatdikontroldenganbaik.Padababinitopikyangakandipelajarimasih relevan,yaitutentangmanajemengoroutinetetapitidakmenggunakanchannel,melainkan sync.WaitGroup. Golangmenyediakanpackage sync,yangberisikancukupbanyakAPIuntukhandle masalahthreading(dalamkasusinigoroutine).Darisekianbanyakfituryangada,padabab inikitahanyaakanmempelajari sync.WaitGroup. Penerapan sync.WaitGroup sync.WaitGroupdigunakanmenungguselesainyagoroutineyangsedangberjalan.Cara penggunaannyasangatmudah,tinggalmasukanjumlahgoroutineyangdieksekusi,sebagai parametermethod Add()objectcetakan sync.WaitGroup.Danpadaakhirtiap-tiap goroutine,panggilmethod Done().Juga,padabariskodesetelaheksekusigoroutine, panggilmethod Wait(). Agarlebihjelas,silakancobakodeberikut. 251 WaitGroup packagemain import"sync" import"runtime" import"fmt" funcdoPrint(wg*sync.WaitGroup,messagestring){ deferwg.Done() fmt.Println(message) } funcmain(){ runtime.GOMAXPROCS(2) varwgsync.WaitGroup fori:=0;i<5;i++{ vardata=fmt.Sprintf("data%d",i) wg.Add(1) godoPrint(&wg,data) } wg.Wait() } Kodediatasmerupakancontohpenerapan sync.WaitGroupuntukpengelolahangoroutine. Fungsi doPrint()akandijalankansebagaigoroutine,dengantugasmenampilkanisi variabel message. Variabel wgdisiapkanbertipe sync.WaitGroup,nantinyadigunakanuntukmengontrol prosessinkronisasigoroutinesyangdijalankan. Ditiapperulanganstatement wg.Add(1)dipanggil.Kodetersebutakanmemberikan informasikepada wgbahwajumlahgoroutineyangsedangdiprosesditambah1(karena dipanggil5kali,maka wgakansadarbahwaterdapat5buahgoroutinesedangberjalan). Dibarisselanjutnya,fungsi doPrint()dieksekusisebagaigoroutine.Didalamfungsi tersebut,sebuahmethodbernama Done()dipanggil.Methodinidigunakanuntuk memberikaninformasikepada wgbahwagoroutinedimanamethoditudipanggilsudah selesai.Sejumlah5buahgoroutinedijalankan,makamethodtersebutharusdipanggil5kali. Statement wg.Wait()bersifatblocking,proseseksekusiprogramtidakakanditeruskanke barisselanjutnya,sebelumsejumlah5goroutineselesai.Jika Add(1)dipanggil5kali,maka Done()jugaharusdipanggil5kali. 252 WaitGroup PerbedaanWaitGroupDenganChannel Beberapaperbedaanantarachanneldan sync.WaitGroup: Channeltergantungkepadagoroutinetertentudalampenggunaannya,tidakseperti sync.WaitGroupyangdiatidakperlutahugoroutinemanasajayangdijalankan,cukup tahujumlahgoroutineyangharusselesai Penerapan sync.WaitGrouplebihmudahdibandingchannel Kegunaanutamachannelselainuntukmanajemengoroutine,adalahuntukkomunikasi dataantargoroutine;sedangkanWaitGrouphanyadigunakanuntukpengontrolan goroutinesaja Performa sync.WaitGrouplebihbaikdibandingchannel,sumber: https://groups.google.com/forum/#!topic/golang-nuts/whpCEk9yLhc Jikamunculpertanyaanmanakahyanglebihbaik,apakahWaitGroupatauchannel,maka kembalikekebutuhan,karenakeduaAPItersebutmemilikikelebihanmasing-masing. 253 Mutex Mutex Sebelumkitamembahasmengenaiapaitumutex?adabaiknyauntukmempelajariterlebih dahuluapaituracecondition,karenakeduakonsepinisangaterathubungannyasatu samalain. Raceconditionadalahkondisidimanalebihdari1thread(dalamkonteksini,goroutine), mengaksesdatayangsamapadawaktuyangbersamaan(benar-benarbersamaan).Ketika haliniterjadi,nilaidatatersebutakanmenjadikacau.Dalamconcurrencyprogramming situasisepertiiniiniseringterjadi. Mutexadalahpengubahanlevelaksessebuahdatamenjadieksklusif,menjadikandata tersebuthanyadapatdikonsumsi(read/write)olehsatubuahgoroutinesaja.Ketikaterjadi racecondition,makahanyagoroutineyangberuntungsajayangbisamengaksesdata tersebut.Goroutinelain(yangwakturunningnyakebetulanbersamaan)akandipaksauntuk menunggu,hinggagoroutineyangsedangmemanfaatkandatatersebutselesai. Golangmenyediakan sync.Mutexyangbisadimanfaatkanuntukkeperluanlockdan unlockdata. Padababinikitaakanmembahasmengenairacecondition,dancarauntuk menanggulanginyamenggunakanteknikmutex. Persiapan Pertamasiapkanstructbarubernama counter,denganisisebuahproperty valbertipe int.Propertyininantinyaakandikonsumsidandiolaholehbanyakgoroutine. Selainitustructinijugamemilikibeberapamethod: 1. Method Add()untukincrementnilai 2. Method Value()untukmengembalikannilai Janganlupajugauntukmeng-importpackageyangdibutuhkan. 254 Mutex packagemain import( "fmt" "runtime" "sync" ) typecounterstruct{ valint } func(c*counter)Add(xint){ c.val++ } func(c*counter)Value()(xint){ returnc.val } Kodediatasakankitagunakansebagaitemplatecontohsourcecodeyangadapadabab ini. ContohRaceCondition Programberikutmerupakancontohprogramyangdidalamnyamemungkinkanterjadirace conditionataukondisigoroutinebalapan. Pastikanjumlahcoreprosesorkomputerandaadalahlebihdarisatu.Karenacontoh padababinihanyaakanberjalansesuaiharapanjika GOMAXPROCS>1. 255 Mutex funcmain(){ runtime.GOMAXPROCS(2) varwgsync.WaitGroup varmetercounter fori:=0;i<1000;i++{ wg.Add(1) gofunc(){ forj:=0;j<1000;j++{ meter.Add(1) } wg.Done() }() } wg.Wait() fmt.Println(meter.Value()) } Padakodediatas,disiapkansebuahinstance sync.WaitGroupbernama wg,danvariabel object meterbertipe counter(nilaiproperty valdefault-nyaadalah0). Setelahnyadijalankanperulangansebanyak1000kali,yangditiapperulanganyadijalankan sebuahgoroutinebaru.Didalamgoroutinetersebut,terdapatperulanganlagi,sebanyak 1000kali.Dalamperulangantersebutnilaiproperty valdinaikkansebanyak1lewat method Add(). Dengandemikian,ekspektasinilaiakhir meter.valharusnyaadalah1000000. Diakhir, wg.Wait()dipanggil,dannilaivariabelcounter meterdiambillewat meter.Value()untukkemudianditampilkan.Hasilnyabisadilihatpadagambarberikut. Nilai meter.valtidakgenap1000000?kenapabisabegitu?Padahalseharusnyatidakada masalahdalamkodeyangkitatulisdiatas. Inilahyangdisebutdenganracecondition,kasussepertiinimemanghanyaterjadidalam concurrencyprogramming. 256 Mutex DeteksiRaceConditionMenggunakanGolangRace Detector Golangmenyediakanfituruntukdeteksisebuahracecondition.Carapenggunaannya adalahdenganmenambahkanflag -racepadasaateksekusiaplikasi. Terlihatpadagambardiatasadapesanbahwaterdapatsebuahdatayangdijadikanbahan balapanolehgoroutine( Found1datarace(s)). Penerapan sync.Mutex Sekarangkitatahubahwaprogramdiatasmenghasilkanbugracecondition.Untuk mengatasimasalahtersebutadabeberapacarayangbisadigunakan,dandisinikitaakan menggunakan sync.Mutex. Ubahkodediatas,tambahkanpropertybarupadastruct counter,yaitu mudengantipe sync.Mutex.Variabeliniakankitagunakanuntuklockdanunlockdata c.valpadasaat pengaksesanlewatmethod Add()dan Value(). 257 Mutex typecounterstruct{ musync.Mutex valint } func(c*counter)Add(xint){ c.mu.Lock() c.val++ c.mu.Unlock() } func(c*counter)Value()(xint){ c.mu.Lock() varval=c.val c.mu.Unlock() returnval } Method Lock()digunakanuntukmenandaibahwasemuaoperasipadabarissetelahkode tersebutadalahbersifateksklusif.Hanyaadasatubuahgoroutineyangbisamelakukannya dalamsatuwaktu.Jikaadabanyakgoroutineyangeksekusinyabersamaan,harusantri. Padakodediatasterdapatkodeuntukincrementnilai meter.val.Makapropertytersebut hanyabisadiaksesolehsatugoroutinesaja. Method Unlock()akanmembukakembaliaksesoperasikeproperty/variabelyangdilock. Bisadibilang,prosesmutualexclusionterjadidiantarakeduamethodtersebut, Lock()dan Unlock(). Takhanyaketikapengubahannilai,padasaatpengaksesanjugaperluditambahkankedua fungsiini,agardatayangdiambilbenar-benardatapadawaktuitu. 258