Dasar Pemrograman Golang

advertisement
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
Download