View
3
Download
0
Category
Preview:
Citation preview
1.1
1.2
1.2.1
1.2.2
1.2.3
1.2.4
1.2.5
1.3
1.3.1
1.3.2
1.3.3
1.3.4
1.3.5
1.3.6
1.3.7
1.3.8
1.4
1.4.1
1.4.2
1.4.3
1.4.4
1.4.5
1.5
1.5.1
1.5.2
1.5.3
1.5.4
1.5.5
1.5.6
1.6
1.6.1
1.6.2
1.6.3
1.6.4
1.6.5
1.6.6
1.6.7
1.7
1.7.1
TableofContentsIntroduction
GoEnvironmentConfiguration
Installation
$GOPATHandworkspace
Gocommands
Godevelopmenttools
Summary
Gobasicknowledge
Hello,Go
Gofoundation
Controlstatementsandfunctions
struct
Object-oriented
interface
Concurrency
Summary
Webfoundation
Webworkingprinciples
Buildasimplewebserver
HowGoworkswithweb
Getintohttppackage
Summary
HTTPForm
Processforminputs
Validationofinputs
Crosssitescripting
Duplicatesubmissions
Fileupload
Summary
Database
database/sqlinterface
HowtouseMySQL
HowtouseSQLite
HowtousePostgreSQL
HowtousebeedbORM
NOSQL
Summary
Datastorageandsession
Sessionandcookies
2
1.7.2
1.7.3
1.7.4
1.7.5
1.8
1.8.1
1.8.2
1.8.3
1.8.4
1.8.5
1.8.6
1.8.7
1.9
1.9.1
1.9.2
1.9.3
1.9.4
1.9.5
1.10
1.10.1
1.10.2
1.10.3
1.10.4
1.10.5
1.10.6
1.10.7
1.11
1.11.1
1.11.2
1.11.3
1.11.4
1.12
1.12.1
1.12.2
1.12.3
1.12.4
1.13
1.13.1
1.13.2
1.13.3
1.13.4
1.13.5
HowtousesessioninGo
Sessionstorage
Preventhijackofsession
Summary
Textfiles
XML
JSON
Regexp
Templates
Files
Strings
Summary
Webservices
Sockets
WebSocket
REST
RPC
Summary
Securityandencryption
CSRFattacks
Filterinputs
XSSattacks
SQLinjection
Passwordstorage
Encryptanddecryptdata
Summary
Internationalizationandlocalization
Timezone
Localizedresources
Internationalsites
Summary
Errorhandling,debuggingandtesting
Errorhandling
DebuggingbyusingGDB
Writetestcases
Summary
Deploymentandmaintenance
Logs
Errorsandcrashes
Deployment
Backupandrecovery
Summary
3
1.14
1.14.1
1.14.2
1.14.3
1.14.4
1.14.5
1.14.6
1.15
1.15.1
1.15.2
1.15.3
1.15.4
1.15.5
1.15.6
1.15.7
1.16
1.17
Buildawebframework
Projectprogram
Customizedrouters
Designcontrollers
Logsandconfigurations
Add,deleteandupdateblogs
Summary
Developwebframework
Staticfiles
Session
Form
Uservalidation
Multi-languagesupport
pprof
Summary
References
preface
4
BuildWebApplicationwithGolangPurpose
BecauseI'minterestedinwebapplicationdevelopment,Iusedmyfreetimetowritethisbookasanopensourceversion.Itdoesn'tmeanthatIhaveaverygoodabilitytobuildwebapplications;IwouldliketosharewhatI'vedonewithGoinbuildingwebapplications.
ForthoseofyouwhoareworkingwithPHP/Python/Ruby,youwilllearnhowtobuildawebapplicationwithGo.ForthoseofyouwhoareworkingwithC/C++,youwillknowhowthewebworks.
Ibelievethepurposeofstudyingissharingwithothers.ThehappiestthinginmylifeissharingeverythingI'veknownwithmorepeople.
Donate
AliPay:
alipay
EnglishDonate:donate
CommunityQQ群:386056972
BBS:http://gocn.io/
Acknowledgments四月份平民AprilCitizen(reviewcode)洪瑞琦HongRuiqi(reviewcode)边疆BianJiang(writetheconfigurationsaboutVimandEmacsforGodevelopment)欧林猫OlingCat(reviewcode)吴文磊WenleiWu(providesomepictures)北极星Polaris(reviewwholebook)雨痕RainTrail(reviewchapter2and3)
LicenseThisbookislicensedundertheCCBY-SA3.0License,thecodeislicensedunderaBSD3-ClauseLicense,unlessotherwisespecified.
GetStarted
Index
Introduction
5
http://beego.me/donatehttp://gocn.io/https://plus.google.com/110445767383269817959https://github.com/hongruiqihttps://github.com/borderhttps://github.com/OlingCatmailto:spadesacn@gmail.comhttps://github.com/polaris1119https://github.com/qyuhenhttp://creativecommons.org/licenses/by-sa/3.0/https://github.com/astaxie/build-web-application-with-golang/blob/master/LICENSE.md
Introduction
6
1GoEnvironmentConfigurationWelcometotheworldofGo,let'sstartexploring!
Goisafast-compiled,garbage-collected,concurrentsystemsprogramminglanguage.Ithasthefollowingadvantages:
Compilesalargeprojectwithinafewseconds.Providesasoftwaredevelopmentmodelthatiseasytoreasonabout,avoidingmostoftheproblemsassociatedwithC-styleheaderfiles.Isastaticlanguagethatdoesnothavelevelsinitstypesystem,sousersdonotneedtospendmuchtimedealingwithrelationsbetweentypes.Itismorelikealightweightobject-orientedlanguage.Performsgarbagecollection.Itprovidesbasicsupportforconcurrencyandcommunication.Designedformulti-corecomputers.
Goisacompiledlanguage.Itcombinesthedevelopmentefficiencyofinterpretedordynamiclanguageswiththesecurityofstaticlanguages.Itisgoingtobethelanguageofchoiceformodern,multi-corecomputerswithnetworking.Forthesepurposes,therearesomeproblemsthatneedtoinherentlyberesolvedatthelevelofthelanguageofchoice,suchasarichlyexpressivelightweighttypesystem,anativeconcurrencymodel,andstrictlyregulatedgarbagecollection.Forquitesometime,nopackagesortoolshaveemergedthathaveaimedtosolvealloftheseproblemsinapragmaticfashion;thuswasbornthemotivationfortheGolanguage.
Inthischapter,IwillshowyouhowtoinstallandconfigureyourownGodevelopmentenvironment.
LinksDirectoryNextsection:Installation
GoEnvironmentConfiguration
7
1.1Installation
ThreewaystoinstallGoTherearemanywaystoconfiguretheGodevelopmentenvironmentonyourcomputer,andyoucanchoosewhicheveroneyoulike.Thethreemostcommonwaysareasfollows.
Officialinstallationpackages.TheGoteamprovidesconvenientinstallationpackagesinWindows,Linux,Macandotheroperatingsystems.Thisisprobablytheeasiestwaytogetstarted.YoucangettheinstallersfromtheGolangDownloadPage.
Installityourselffromsourcecode.PopularwithdeveloperswhoarefamiliarwithUnix-likesystems.
Usingthird-partytools.Therearemanythird-partytoolsandpackagemanagersforinstallingGo,likeapt-getinUbuntuandhomebrewforMac.
IncaseyouwanttoinstallmorethanoneversionofGoonacomputer,youshouldtakealookatatoolcalledGVM.ItisthebesttoolI'veseensofarforaccomplishingthistask,otherwiseyou'dhavetodealwithityourself.
InstallfromsourcecodeTocompileGo1.5andupwards,youonlyneedthepreviousversionofGo,asGohasachievedbootstrapping.YouonlyneedGotocompileGo.
TocompileGo1.4downwards,youwillneedaCcompilerassomepartsofGoarestillwritteninPlan9CandAT&Tassembler.
OnaMac,ifyouhaveinstalledXcode,youalreadyhavethecompiler.
OnUnix-likesystems,youneedtoinstallgccorasimilarcompiler.Forexample,usingthepackagemanagerapt-get(includedwithUbuntu),onecaninstalltherequiredcompilersasfollows:
sudoapt-getinstallgcclibc6-dev
OnWindows,youneedtoinstallMinGWinordertoinstallgcc.Don'tforgettoconfigureyourenvironmentvariablesaftertheinstallationhascompleted.(Everythingthatlookslikethismeansit'scommentedbyatranslator:Ifyouareusing64-bitWindows,youshouldinstallthe64-bitversionofMinGW)
Atthispoint,executethefollowingcommandstoclonetheGosourcecodeandcompileit.(Itwillclonethesourcecodetoyourcurrentdirectory.Switchyourworkpathbeforeyoucontinue.Thismaytakesometime.)
gitclonehttps://go.googlesource.com/gocdgo/src./all.bash
Asuccessfulinstallationwillendwiththemessage"ALLTESTSPASSED."
OnWindows,youcanachievethesamebyrunningall.bat.
IfyouareusingWindows,theinstallationpackagewillsetyourenvironmentvariablesautomatically.InUnix-likesystems,youneedtosetthesevariablesmanuallyasfollows.(IfyourGoversionisgreaterthan1.0,youdon'thavetoset$GOBIN,anditwillautomaticallyberelatedtoyour$GOROOT/bin,whichwewilltalkaboutinthenextsection)
Installation
8
https://golang.org/dl/https://github.com/moovweb/gvm
exportGOROOT=$HOME/goexportGOBIN=$GOROOT/binexportPATH=$PATH:$GOROOT/bin
Ifyouseethefollowinginformationonyourscreen,you'reallset.
Figure1.1Informationafterinstallingfromsourcecode
OnceyouseetheusageinformationofGo,itmeansyouhavesuccessfullyinstalledGoonyourcomputer.Ifitsays"nosuchcommand",checkthatyour$PATHenvironmentvariablecontainstheinstallationpathofGo.
UsingthestandardinstallationpackagesGohasone-clickinstallationpackagesforeverysupportedoperatingsystem.ThesepackageswillinstallGoin/usr/local/go(c:\GoinWindows)bydefault.Ofcoursethiscanbemodified,butyoualsoneedtochangealltheenvironmentvariablesmanuallyasI'veshownabove.
Howtocheckifyouroperatingsystemis32-bitor64-bit?
Ournextstepdependsonyouroperatingsystemtype,sowehavetocheckitbeforewedownloadthestandardinstallationpackages.
IfyouareusingWindows,pressWin+Randthenrunthecommandtool.Typethesysteminfocommandanditwillshowyousomeusefulsysteminformation.Findthelinethatsays"systemtype"-ifyousee"x64-basedPC"thatmeansyouroperatingsystemis64-bit,32-bitotherwise.
Istronglyrecommenddownloadingthe64-bitpackageifyouareaMacuser,asGonolongersupportspure32-bitprocessorsonMacOSX.
Linuxuserscantypeuname-aintheterminaltoseesysteminformation.A64-bitoperatingsystemwillshowthefollowing:
x86_64x86_64x86_64GNU/Linux//somemachinessuchasUbuntu10.04willshowasfollowingx86_64GNU/Linux
32-bitoperatingsystemsinsteadshow:
i686i686i386GNU/Linux
Mac
Gotothedownloadpage,choosego1.4.2.darwin-386.pkg(Thelaterversionhasno32-bitdownload.)for32-bitsystemsandgo1.8.3.darwin-amd64.pkgfor64-bitsystems.Goingallthewaytotheendbyclicking"next",~/go/binwillbeaddedtoyoursystem's$PATHafteryoufinishtheinstallation.Nowopentheterminalandtypego.Youshouldseethesameoutputshowninfigure1.1.
Linux
Gotothedownloadpage,choosego1.8.3.linux-386.tar.gzfor32-bitsystemsandgo1.8.3.linux-amd64.tar.gzfor64-bitsystems.SupposeyouwanttoinstallGointhe$GO_INSTALL_DIRpath.Uncompressthetar.gztoyourchosenpathusingthecommandtarzxvfgo1.8.3.linux-amd64.tar.gz-C$GO_INSTALL_DIR.Thensetyour$PATHwiththefollowing:exportPATH=$PATH:$GO_INSTALL_DIR/go/bin.Nowjustopentheterminalandtypego.Youshouldnowseethesameoutputdisplayedinfigure1.1.
Installation
9
https://golang.org/dl/https://golang.org/dl/
Windows
Gotothedownloadpage,choosego1.8.3.windows-386.msifor32-bitsystemsandgo1.8.3.windows-amd64.msifor64-bitsystems.Goingallthewaytotheendbyclicking"next",c:/go/binwillbeaddedtopath.Nowjustopenacommandlinewindowandtypego.Youshouldnowseethesameoutputdisplayedinfigure1.1.
Usethird-partytools
GVM
GVMisaGomulti-versioncontroltooldevelopedbyathird-party,likervmforruby.It'squiteeasytouse.Installgvmbytypingthefollowingcommandsinyourterminal:
bash<
1. InstallGo
brewupdate&&brewupgradebrewinstallgo
LinksDirectoryPrevioussection:GoenvironmentconfigurationNextsection:$GOPATHandworkspace
Installation
11
1.2$GOPATHandworkspace
$GOPATHGotakesauniqueapproachtomanagethecodefileswiththeintroductionofa$GOPATHdirectorywhichcontainsallthegocodeinthemachine.Notethatthisisdifferentfromthe$GOROOTenvironmentvariablewhichstateswheregoisinstalledonthemachine.Wehavetodefinethe$GOPATHvariablebeforeusingthelanguage,in*nixsystemsthereisafilecalled.profileweneedtoappendthebelowexportstatementtothefile.Theconceptbehindgopathisanovelone,wherewecanlinktoanygocodeatanyinstantoftimewithoutambiguity.
Startingfromgo1.8,theGOPATHenvironmentvariablenowhasadefaultvalueifitisunset.Itdefaultsto$HOME/goonUnixand%USERPROFILE%/goonWindows.
InUnix-likesystems,thevariableshouldbeusedlikethis:
exportGOPATH=${HOME}/mygo
InWindows,youneedtocreateanewenvironmentvariablecalledGOPATH,thensetitsvaluetoc:\mygo(Thisvaluedependsonwhereyourworkspaceislocated)
It'sOKtohavemorethanonepath(workspace)in$GOPATH,butrememberthatyouhavetouse:(;inWindows)tobreakthemup.Atthispoint,gogetwillsavethecontenttoyourfirstpathin$GOPATH.Itishighlyrecommendedtonothavemultiplesversions,theworstcaseistocreateafolderbythenameofyourprojectrightinside$GOPATH,itbreakseverythingthatthecreatorswerewishingtochangeinprogrammingwiththecreationofgolanguagebecausewhenyoucreateafolderinside$GOPATHyouwillreferenceyourpackagesasdirectlyas,andthisbreaksalltheapplicationswhichwillimportyourpackagebecausethegogetwon'tfindyourpackage.Pleasefollowconventions,thereisareasonconventionsarecreated.
In$GOPATH,youmusthavethreefoldersasfollows:
srcforsourcefileswhosesuffixis.go,.c,.g,.s.pkgforcompiledfileswhosesuffixis.a.binforexecutablefiles
Inthisbook,Iusemygoasmyonlypathin$GOPATH.
PackagedirectoryCreatepackagesourcefilesandfolderslike$GOPATH/src/mymath/sqrt.go(mymathisthepackagename)(Authorusesmymathashispackagename,andthesamenameforthefolderthatcontainsthepackagesourcefiles)
Everytimeyoucreateapackage,youshouldcreateanewfolderinthesrcdirectory,withthenotableexceptionofmain,forwhichmainfoldercreationisoptional.Foldernamesareusuallythesameasthepackagethatyouaregoingtouse.Youcanhavemulti-leveldirectoriesifyouwantto.Forexample,ifyoucreatethedirectory$GOPATH/src/github.com/astaxie/beedb,thenthepackagepathwouldbegithub.com/astaxie/beedb.Thepackagenamewillbethelastdirectoryinyourpath,whichisbeedbinthiscase.
Executefollowingcommands.(Nowauthorgoesbacktotalkexamples)
cd$GOPATH/srcmkdirmymath
Createanewfilecalledsqrt.go,typethefollowingcontenttoyourfile.
$GOPATHandworkspace
12
//Sourcecodeof$GOPATH/src/mymath/sqrt.gopackagemymath
funcSqrt(xfloat64)float64{z:=0.0fori:=0;i<1000;i++{z-=(z*z-x)/(2*x)}returnz}
Nowmypackagedirectoryhasbeencreatedandit'scodehasbeenwritten.Irecommendthatyouusethesamenameforyourpackagesastheircorrespondingdirectories,andthatthedirectoriescontainallofthepackagesourcefiles.
CompilepackagesWe'vealreadycreatedourpackageabove,buthowdowecompileitforpracticalpurposes?Therearetwowaystodothis.
1. Switchyourworkpathtothedirectoryofyourpackage,thenexecutethegoinstallcommand.2. Executetheabovecommandexceptwithafilename,likegoinstallmymath.
Aftercompiling,wecanopenthefollowingfolder.
cd$GOPATH/pkg/${GOOS}_${GOARCH}//youcanseethefilewasgeneratedmymath.a
Thefilewhosesuffixis.aisthebinaryfileofourpackage.Howdoweuseit?
Obviously,weneedtocreateanewapplicationtouseit.
Createanewapplicationpackagecalledmathapp.
cd$GOPATH/srcmkdirmathappcdmathappvimmain.go
Writethefollowingcontenttomain.go.
//$GOPATH/src/mathapp/main.gosourcecode.packagemain
import("mymath""fmt")
funcmain(){fmt.Printf("Hello,world.Sqrt(2)=%v\n",mymath.Sqrt(2))}
Tocompilethisapplication,youneedtoswitchtotheapplicationdirectory,whichinthiscaseis$GOPATH/src/mathapp,thenexecutethegoinstallcommand.Nowyoushouldseeanexecutablefilecalledmathappwasgeneratedinthedirectory$GOPATH/bin/.Torunthisprogram,usethe./mathappcommand.Youshouldseethefollowingcontentinyourterminal.
Helloworld.Sqrt(2)=1.414213562373095
$GOPATHandworkspace
13
InstallremotepackagesGohasatoolforinstallingremotepackages,whichisacommandcalledgoget.Itsupportsmostopensourcecommunities,includingGithub,GoogleCode,BitBucket,andLaunchpad.
gogetgithub.com/astaxie/beedb
Youcanusegoget-u…toupdateyourremotepackagesanditwillautomaticallyinstallallthedependentpackagesaswell.
Thistoolwillusedifferentversioncontroltoolsfordifferentopensourceplatforms.Forexample,gitforGithubandhgforGoogleCode.Therefore,youhavetoinstalltheseversioncontroltoolsbeforeyouusegoget.
Afterexecutingtheabovecommands,thedirectorystructureshouldlooklikefollowing.
$GOPATHsrc|-github.com|-astaxie|-beedbpkg|--${GOOS}_${GOARCH}|-github.com|-astaxie|-beedb.a
Actually,gogetclonessourcecodetothe$GOPATH/srcofthelocalfilesystem,thenexecutesgoinstall.
Youcanuseremotepackagesinthesamewaythatweuselocalpackages.
import"github.com/astaxie/beedb"
DirectorycompletestructureIfyou'vefollowedalloftheabovesteps,yourdirectorystructureshouldnowlooklikethefollowing.
bin/mathapppkg/${GOOS}_${GOARCH},suchasdarwin_amd64,linux_amd64mymath.agithub.com/astaxie/beedb.asrc/mathappmain.gomymath/sqrt.gogithub.com/astaxie/beedb/beedb.goutil.go
Nowyouareabletoseethedirectorystructureclearly;bincontainsexecutablefiles,pkgcontainscompiledfilesandsrccontainspackagesourcefiles.
(TheformatofenvironmentvariablesinWindowsis%GOPATH%,howeverthisbookmainlyfollowstheUnix-style,soWindowsusersneedtoreplacetheseyourself.)
$GOPATHandworkspace
14
LinksDirectoryPrevioussection:InstallationNextsection:Gocommands
$GOPATHandworkspace
15
1.3Gocommands
GocommandsTheGolanguagecomeswithacompletesetofcommandoperationtools.Youcanexecutethegocommandontheterminaltoseethem:
Figure1.3Gocommanddisplaysdetailedinformation
Theseareallusefulforus.Let'sseehowtousesomeofthem.
gobuildThiscommandisforcompilingtests.Itwillcompilepackagesanddependenciesifit'snecessary.
Ifthepackageisnotthemainpackagesuchasmymathinsection1.2,nothingwillbegeneratedafteryouexecutegobuild.Ifyouneedthepackagefile.ain$GOPATH/pkg,usegoinstallinstead.Ifthepackageisthemainpackage,itwillgenerateanexecutablefileinthesamefolder.Ifyouwantthefiletobegeneratedin$GOPATH/bin,usegoinstallorgobuild-o${PATH_HERE}/a.exe.Iftherearemanyfilesinthefolder,butyoujustwanttocompileoneofthem,youshouldappendthefilenameaftergobuild.Forexample,gobuilda.go.gobuildwillcompileallthefilesinthefolder.Youcanalsoassignthenameofthefilethatwillbegenerated.Forinstance,inthemathappproject(insection1.2),usinggobuild-oastaxie.exewillgenerateastaxie.exeinsteadofmathapp.exe.Thedefaultnameisyourfoldername(non-mainpackage)orthefirstsourcefilename(mainpackage).
(AccordingtoTheGoProgrammingLanguageSpecification,packagenamesshouldbethenameafterthewordpackageinthefirstlineofyoursourcefiles.Itdoesn'thavetobethesameasthefoldername,andtheexecutablefilenamewillbeyourfoldernamebydefault.)
gobuildignoresfileswhosenamesstartwith_or..Ifyouwanttohavedifferentsourcefilesforeveryoperatingsystem,youcannamefileswiththesystemnameasasuffix.Supposetherearesomesourcefilesforloadingarrays.Theycouldbenamedasfollows:
array_linux.go|array_darwin.go|array_windows.go|array_freebsd.go
gobuildchoosestheonethat'sassociatedwithyouroperatingsystem.Forexample,itonlycompilesarray_linux.goinLinuxsystems,andignoresalltheothers.
gocleanThiscommandisforcleaningfilesthataregeneratedbycompilers,includingthefollowingfiles:
_obj///olddirectoryofobject,leftbyMakefiles_test///olddirectoryoftest,leftbyMakefiles_testmain.go//olddirectoryofgotest,leftbyMakefilestest.out//olddirectoryoftest,leftbyMakefilesbuild.out//olddirectoryoftest,leftbyMakefiles*.[568ao]//objectfiles,leftbyMakefiles
DIR(.exe)//generatedbygobuildDIR.test(.exe)//generatedbygotest-cMAINFILE(.exe)//generatedbygobuildMAINFILE.go
Gocommands
16
https://golang.org/ref/spec
IusuallyusethiscommandtocleanupmyfilesbeforeIuploadmyprojecttoGithub.Theseareusefulforlocaltests,butuselessforversioncontrol.
gofmtandgofmtThepeoplewhoareworkingwithC/C++shouldknowthatpeoplearealwaysarguingaboutwhichcodestyleisbetter:K&R-styleorANSI-style.HoweverinGo,thereisonlyonecodestylewhichisenforced.Forexample,leftbracesmustonlybeinsertedattheendoflines,andtheycannotbeontheirownlines,otherwiseyouwillgetcompileerrors!Fortunately,youdon'thavetoremembertheserules.gofmtdoesthisjobforyou.Justexecutethecommandgofmt.gointerminal.Idon'tusethiscommandverymuchbecauseIDEsusuallyexecutethiscommandautomaticallywhenyousavesourcefiles.IwilltalkmoreaboutIDEsinthenextsection.
gofmtisjustanalias,whichrunsthecommand'gofmt-l-w'onthepackagesnamedbytheimportpaths.
Weusuallyusegofmt-winsteadofgofmt.Thelatterwillnotrewriteyoursourcefilesafterformattingcode.gofmt-wsrcformatsthewholeproject.
gogetThiscommandisforgettingremotepackages.Sofar,itsupportsBitBucket,Github,GoogleCodeandLaunchpad.Thereareactuallytwothingsthathappenafterweexecutethiscommand.ThefirstthingisthatGodownloadsthesourcecode,thenexecutesgoinstall.Beforeyouusethiscommand,makesureyouhaveinstalledalloftherelatedtools.
BitBucket(MercurialGit)Github(git)GoogleCode(Git,Mercurial,Subversion)Launchpad(Bazaar)
Inordertousethiscommand,youhavetoinstallthesetoolscorrectly.Don'tforgettoupdatethe$PATHvariable.Bytheway,italsosupportscustomizeddomainnames.Usegohelpimportpathformoredetailsaboutthis.
goinstallThiscommandcompilesallpackagesandgeneratesfiles,thenmovesthemto$GOPATH/pkgor$GOPATH/bin.
gotestThiscommandloadsallfileswhosenameinclude*_test.goandgeneratestestfiles,thenprintsinformationthatlookslikethefollowing.
okarchive/tar0.011sFAILarchive/zip0.022sokcompress/gzip0.033s...
Ittestsallyourtestfilesbydefault.Usecommandgohelptestflagformoredetails.
godocManypeoplesaythatwedon'tneedanythird-partydocumentationforprogramminginGo(actuallyI'vemadeaCHMalready).Gohasapowerfultooltomanagedocumentationnatively.
Gocommands
17
https://github.com/astaxie/godoc
Sohowdowelookuppackageinformationindocumentation?Forinstance,ifyouwanttogetmoredetailsaboutthebuiltinpackage,usethegodocbuiltincommand.Similarly,usethegodocnet/httpcommandtolookupthehttppackagedocumentation.Ifyouwanttoseemoredetailsaboutspecificfunctions,usethegodocfmtPrintfandgodoc-srcfmtPrintfcommandstoviewthesourcecode.
Executethegodoc-http=:8080command,thenopen127.0.0.1:8080inyourbrowser.Youshouldseealocalizedgolang.org.Itcannotonlyshowthestandardpackages'information,butalsopackagesinyour$GOPATH/pkg.It'sgreatforpeoplewhoaresufferingfromtheGreatFirewallofChina.
OthercommandsGoprovidesmorecommandsthanthosewe'vejusttalkedabout.
gofix//upgradecodefromanoldversionbeforego1toanewversionaftergo1goversion//getinformationaboutyourversionofGogoenv//viewenvironmentvariablesaboutGogolist//listallinstalledpackagesgorun//compiletemporaryfilesandruntheapplication
TherearealsomoredetailsaboutthecommandsthatI'vetalkedabout.Youcanusegohelptolookthemup.
LinksDirectoryPrevioussection:$GOPATHandworkspaceNextsection:Godevelopmenttools
Gocommands
18
GodevelopmenttoolsInthissection,I'mgoingtoshowyouafewIDEsthatcanhelpyoubecomeamoreefficientprogrammer,withcapabilitiessuchasintelligentcodecompletionandauto-formatting.Theyareallcross-platform,sothestepsIwillbeshowingyoushouldnotbeverydifferent,evenifyouarenotusingthesameoperatingsystem.
LiteIDELiteIDEisanopensource,lightweightIDEfordevelopingGoprojectsonly,developedbyvisualfc.
Figure1.4MainpanelofLiteIDE
LiteIDEfeatures.
Cross-platformWindowsLinuxMacOS
Cross-compileManagemultiplecompileenvironmentsSupportscross-compilationofGo
ProjectmanagementstandardDocumentationviewbasedon$GOPATHCompilationsystembasedon$GOPATHAPIdocumentationindexbasedon$GOPATH
GosourcecodeeditorCodeoutliningFullsupportofgocodeGodocumentationviewandAPIindexViewcodeexpressionusingF1FunctiondeclarationjumpusingF2GdbsupportAuto-formatwithgofmt
OthersMulti-languagePluginsystemTexteditorthemesSyntaxsupportbasedonKateintelligentcompletionbasedonfull-textCustomizedshortcutsMarkdownsupport
Real-timepreviewCustomizedCSSExportHTMLandPDFConvertandmergetoHTMLandPDF
LiteIDEinstallationInstallLiteIDE
Downloadpage
Godevelopmenttools
19
https://sourceforge.net/projects/liteide/files/
Sourcecode
YouneedtoinstallGofirst,thendownloadtheversionappropriateforyouroperatingsystem.Decompressthepackagetodirectlyuseit.
Installgocode
Youhavetoinstallgocodeinordertouseintelligentcompletion
goget-ugithub.com/nsf/gocode
Compilationenvironment
SwitchconfigurationinLiteIDEtosuityouroperatingsystem.InWindowsandusingthe64-bitversionofGo,youshouldchoosewin64astheconfigurationenvironmentinthetoolbar.Then,chooseOptions,findLiteEnvintheleftlistandopenfilewin64.envintherightlist.
GOROOT=c:\goGOBIN=GOARCH=amd64GOOS=windowsCGO_ENABLED=1
PATH=%GOBIN%;%GOROOT%\bin;%PATH%。。。
ReplaceGOROOT=c:\gotoyourGoinstallationpath,saveit.IfyouhaveMinGW64,addc:\MinGW64\bintoyourpathenvironmentvariableforcgosupport.
InLinuxandusingthe64-bitversionofGo,youshouldchooselinux64astheconfigurationenvironmentinthetoolbar.Then,chooseOptions,findLiteEnvintheleftlistandopenthelinux64.envfileintherightlist.
GOROOT=$HOME/goGOBIN=GOARCH=amd64GOOS=linuxCGO_ENABLED=1
PATH=$GOBIN:$GOROOT/bin:$PATH。。。
ReplaceGOROOT=$HOME/gotoyourGoinstallationpath,saveit.
$GOPATH$GOPATHisthepaththatcontainsalistofprojects.Openthecommandtool(orpressCtrl+`inLiteIDE),thentypegohelpgopathformoredetails.It'sveryeasytoviewandchange$GOPATHinLiteIDE.FollowView-SetupGOPATHtoviewandchangethesevalues.
SublimeTextHereI'mgoingtointroduceyoutheSublimeText3(Sublimeforshort)+GoSublime+gocode.Letmeexplainwhy.
Intelligentcompletion
Figure1.5Sublimeintelligentcompletion
Auto-formatsourcefilesProjectmanagement
Godevelopmenttools
20
https://github.com/visualfc/liteide
Figure1.6Sublimeprojectmanagement
Syntaxhighlight
Freetrialforeverwithnofunctionallimitations.Youmaybepromptedonceinawhiletoremindyoutopurchasealicense,butyoucansimplyignoreitifyouwish.Ofcourse,ifyoudofindthatitenhancesyourproductivityandyoureallyenjoyusingit,pleasepurchaseacopyofitandsupportitscontinueddevelopment!
First,downloadtheversionofSublimesuitableforyouroperatingsystem.
1. PressCtrl+`,openthecommandtoolandinputthefollowingcommands.
ApplicabletoSublimeText3:
importurllib.request,os;pf='PackageControl.sublime-package';ipp=sublime.installed_packages_path();urllib.request.install_opener(urllib.request.build_opener(urllib.request.ProxyHandler()));open(os.path.join(ipp,pf),'wb').write(urllib.request.urlopen('http://sublime.wbond.net/'+pf.replace('','%20')).read())
ApplicabletoSublimeText2:
importurllib2,os;pf='PackageControl.sublime-package';ipp=sublime.installed_packages_path();os.makedirs(ipp)ifnotos.path.exists(ipp)elseNone;urllib2.install_opener(urllib2.build_opener(urllib2.ProxyHandler()));open(os.path.join(ipp,pf),'wb').write(urllib2.urlopen('http://sublime.wbond.net/'+pf.replace('','%20')).read());print('PleaserestartSublimeTexttofinishinstallation')
RestartSublimeTextwhentheinstallationhasfinished.Youshouldthenfinda`PackageControl`optioninthe"Preferences"menu.
![](images/1.4.sublime3.png?raw=true)
Figure1.7SublimePackageControl
1. ToinstallGoSublime,SidebarEnhancementsandGoBuild,pressCtrl+Shift+ptoopenPackageControl,thentypepcip(shortfor"PackageControl:InstallPackage").
Figure1.8SublimeInstallPackages
Nowtypein"GoSublime",pressOKtoinstallthepackage,andrepeatthesamestepsforinstallingSidebarEnhancementsandGoBuild.Onceagain,restarttheeditorwhenitcompletestheinstallation.
2. Toverifythattheinstallationissuccessful,openSublime,thenopenthemain.gofiletoseeifithasthepropersyntaxhighlighting.Typeimporttoseeifcodecompletionpromptsappear.Aftertypingimport"fmt",typefmt.anywhereaftertheimportdeclarationtoseewhetherornotintelligentcodecompletionforfunctionswassuccessfullyenabled.
Ifeverythingisfine,you'reallset.
Ifnot,checkyour$PATHagain.Openaterminal,typegocode.Ifitdoesnotrun,your$PATHwasnotconfiguredcorrectly.
VimVimisapopulartexteditorforprogrammers,whichevolvedfromitsslimmerpredecessor,Vi.Ithasfunctionsforintelligentcompletion,compilationandjumpingtoerrors.
vim-goisvimaboveanopen-sourcegolanguageusingthemostextensivedevelopmentenvironmentplug-ins
Thepluginaddress:github.com/fatih/vim-go
Godevelopmenttools
21
http://www.sublimetext.com/https://github.com/fatih/vim-go
VimpluginmanagementarethemainstreamPathogenandVundle,Buttheaspectsthereofaredifferent.Pathogenistosolveeachplug-inaftertheinstallationoffilesscatteredtomultipledirectoriesandpoormanagementoftheexistence.Vundleistosolvetheautomaticsearchanddownloadplug-insexist.Thesetwoplug-inscanbeusedsimultaneously.
1.InstallVundle
mkdir~/.vim/bundlegitclonehttps://github.com/gmarik/Vundle.vim.git~/.vim/bundle/Vundle.vim
Edit.vimrc,Vundletherelevantconfigurationwillbeplacedinthebeginning(RefertotheVundledocumentationfordetails)
setnocompatible"beiMproved,requiredfiletypeoff"required
"settheruntimepathtoincludeVundleandinitializesetrtp+=~/.vim/bundle/Vundle.vimcallvundle#begin()
"letVundlemanageVundle,requiredPlugin'gmarik/Vundle.vim'
"AllofyourPluginsmustbeaddedbeforethefollowinglinecallvundle#end()"requiredfiletypepluginindenton"required
2.InstallVim-go
Edit~/.vimrc,Addalinebetweenvundle#beginandvundle#end:
Plugin'fatih/vim-go'
ExecutedwithinVim:PluginInstall
3.InstallYCM(YourCompleteMe)toAutoCompleteAddalineto~/.vimrc:
Plugin'Valloric/YouCompleteMe'
ExecutedwithinVim:PluginInstall
Figure1.8VimintelligentcompletionforGo
1. SyntaxhighlightingforGo
cp-r$GOROOT/misc/vim/*~/.vim/
2. Enablingsyntaxhighlighting
filetypepluginindentonsyntaxon
3. Installgocode
goget-ugithub.com/nsf/gocode
gocodewillbeinstalledin$GOBINasdefault
Godevelopmenttools
22
https://github.com/tpope/vim-pathogenhttps://github.com/VundleVim/Vundle.vimhttps://github.com/VundleVim/Vundle.vimhttps://github.com/nsf/gocode/
4. Configuregocode
~cd$GOPATH/src/github.com/nsf/gocode/vim~./update.sh~gocodesetpropose-builtinstruepropose-builtinstrue~gocodesetlib-path"/home/border/gocode/pkg/linux_amd64"lib-path"/home/border/gocode/pkg/linux_amd64"~gocodesetpropose-builtinstruelib-path"/home/border/gocode/pkg/linux_amd64"
Explanationofgocodeconfiguration:
propose-builtins:specifieswhetherornottoopenintelligentcompletion;falsebydefault.lib-path:gocodeonlysearchesforpackagesin$GOPATH/pkg/$GOOS_$GOARCHand$GOROOT/pkg/$GOOS_$GOARCH.Thissettingcanbeusedtoaddadditionalpaths.
5. Congratulations!Try:emain.gotoexperiencetheworldofGo!
EmacsEmacsistheso-calledWeaponofGod.Sheisnotonlyaneditor,butalsoapowerfulIDE.
Figure1.10EmacsmainpanelofGoeditor
1. Syntaxhighlighting
cp$GOROOT/misc/emacs/*~/.emacs.d/
2. Installgocode
goget-ugithub.com/nsf/gocode
gocodewillbeinstalledin$GOBINasdefault
3. Configuregocode
~cd$GOPATH/src/github.com/nsf/gocode/vim~./update.bash~gocodesetpropose-builtinstruepropose-builtinstrue~gocodesetlib-path"/home/border/gocode/pkg/linux_amd64"lib-path"/home/border/gocode/pkg/linux_amd64"~gocodesetpropose-builtinstruelib-path"/home/border/gocode/pkg/linux_amd64"
4. InstallAutoCompletionDownloadanduncompress
~makeinstallDIR=$HOME/.emacs.d/auto-complete
Configure~/.emacsfile
Godevelopmenttools
23
https://github.com/nsf/gocode/https://github.com/nsf/gocode/https://github.com/nsf/gocode/http://www.emacswiki.org/emacs/AutoComplete
;;auto-complete(require'auto-complete-config)(add-to-list'ac-dictionary-directories"~/.emacs.d/auto-complete/ac-dict")(ac-config-default)(local-set-key(kbd"M-/")'semantic-complete-analyze-inline)(local-set-key"."'semantic-complete-self-insert)(local-set-key">"'semantic-complete-self-insert)
Followthislinkformoredetails.
5. Configure.emacs
;;golangmode(require'go-mode-load)(require'go-autocomplete);;speedbar;;(speedbar1)(speedbar-add-supported-extension".go")(add-hook'go-mode-hook'(lambda();;gocode(auto-complete-mode1)(setqac-sources'(ac-source-go));;Imenu&Speedbar(setqimenu-generic-expression'(("type""^type*\\([^\t\n\r\f]*\\)"1)("func""^func*\\(.*\\){"1)))(imenu-add-to-menubar"Index");;Outlinemode(make-local-variable'outline-regexp)(setqoutline-regexp"//\\.\\|//[^\r\n\f][^\r\n\f]\\|pack\\|func\\|impo\\|cons\\|var.\\|type\\|\t\t*....")(outline-minor-mode1)(local-set-key"\M-a"'outline-previous-visible-heading)(local-set-key"\M-e"'outline-next-visible-heading);;Menubar(require'easymenu)(defconstgo-hooked-menu'("Gotools"["Gorunbuffer"got]["Goreformatbuffer"go-fmt-buffert]["Gocheckbuffer"go-fix-buffert]))(easy-menu-definego-added-menu(current-local-map)"Gotools"go-hooked-menu)
;;Other(setqshow-trailing-whitespacet)));;helperfunction(defungo()"runcurrentbuffer"(interactive)(compile(concat"gorun"(buffer-file-name))))
;;helperfunction(defungo-fmt-buffer()"rungofmtoncurrentbuffer"(interactive)(ifbuffer-read-only(progn(ding)(message"Bufferisreadonly"))(let((p(line-number-at-pos))(filename(buffer-file-name))(old-max-mini-window-heightmax-mini-window-height))(show-all)(if(get-buffer"*GoReformatErrors*")
Godevelopmenttools
24
http://www.emacswiki.org/emacs/AutoComplete
(progn(delete-windows-on"*GoReformatErrors*")(kill-buffer"*GoReformatErrors*")))(setqmax-mini-window-height1)(if(=0(shell-command-on-region(point-min)(point-max)"gofmt""*GoReformatOutput*"nil"*GoReformatErrors*"t))(progn(erase-buffer)(insert-buffer-substring"*GoReformatOutput*")(goto-char(point-min))(forward-line(1-p)))(with-current-buffer"*GoReformatErrors*"(progn(goto-char(point-min))(while(re-search-forward""nilt)(replace-matchfilename))(goto-char(point-min))(compilation-mode))))(setqmax-mini-window-heightold-max-mini-window-height)(delete-windows-on"*GoReformatOutput*")(kill-buffer"*GoReformatOutput*"))));;helperfunction(defungo-fix-buffer()"rungofixoncurrentbuffer"(interactive)(show-all)(shell-command-on-region(point-min)(point-max)"gotoolfix-diff"))
6. Congratulations,you'redone!Speedbarisclosedbydefault-removethecommentsymbolsintheline;;(speedbar1)toenablethisfeature,oryoucanuseitthroughM-xspeedbar.
EclipseEclipseisalsoagreatdevelopmenttool.I'llshowyouhowtouseittowriteGoprograms.
Figure1.1EclipsemainpanelforeditingGo
1. DownloadandinstallEclipse2. Downloadgoclipsehttp://code.google.com/p/goclipse/wiki/InstallationInstructions3. Downloadgocode
gocodeinGithub.
https://github.com/nsf/gocode
YouneedtoinstallgitinWindows,usuallyweusemsysgit
Installgocodeinthecommandtool
goget-ugithub.com/nsf/gocode
Youcaninstallfromsourcecodeifyoulike.
4. DownloadandinstallMinGW5. Configureplugins.
Windows->Preferences->Go
(1).ConfigureGocompiler
Godevelopmenttools
25
http://www.eclipse.org/https://code.google.com/p/goclipse/http://code.google.com/p/goclipse/wiki/InstallationInstructionshttps://code.google.com/p/msysgit/http://sourceforge.net/projects/mingw/files/MinGW/
Figure1.12GoSettinginEclipse
(2).Configuregocode(optional),setgocodepathtowherethegocode.exeis.
Figure1.13gocodeSetting
(3).Configuregdb(optional),setgdbpathtowherethegdb.exeis.
Figure1.14gdbSetting
6. Checktheinstallation
CreateanewGoprojectandhello.gofileasfollowing.
Figure1.15Createanewprojectandfile
Testinstallationasfollows.(youneedtotypecommandinconsoleinEclipse)
Figure1.16TestGoprograminEclipse
IntelliJIDEAPeoplewhohaveworkedwithJavashouldbefamiliarwiththisIDE.ItsupportsGosyntaxhighlightingandintelligentcodecompletion,implementedbyaplugin.
1. DownloadIDEA,thereisnodifferencebetweentheUltimateandCommunityeditions
2. InstalltheGoplugin.ChooseFile-Setting-Plugins,thenclickBrowserrepo.
3. Searchgolang,doubleclickdownloadandinstallandwaitforthedownloadtocomplete.
ClickApply,thenrestart.
4. NowyoucancreateaGoproject.
InputthepositionofyourGosdkinthenextstep-basicallyit'syour$GOROOT.
(SeeablogpostforsetupanduseIntelliJIDEAwithGostepbystep)
VisualStudioVSCodeThisisanawesometexteditorreleasedasopensourcecrossplatformmyMicrosoftwhichtakesthedevelopmentexperiencetoawholenewlevel,https://code.visualstudio.com/.Ithaseverythingamoderntexteditorisexpectedtohaveanddespitebeingbasedonthesamebackendthatatom.ioisbased,itisveryfast.
ItworkswithWindows,Mac,Linux.Ithasgopackagebuilt,itprovidescodelinting.
Godevelopmenttools
26
http://wuwen.org/tips-about-using-intellij-idea-and-go/https://code.visualstudio.com/
AtomAtomisanawesometexteditorreleasedasopensourcecrossplatform,builtonElectron,andbasedoneverythingweloveaboutourfavoriteeditors.Wedesignedittobedeeplycustomizable,butstillapproachableusingthedefaultconfiguration.
Download:https://atom.io/
GoglandGoglandisthecodenameforanewcommercialIDEbyJetBrainsaimedatprovidinganergonomicenvironmentforGodevelopment.
Theofficialversionisnotyetreleased。
Download:https://www.jetbrains.com/go/
LinksDirectoryPrevioussection:GocommandsNextsection:Summary
Godevelopmenttools
27
https://atom.io/https://www.jetbrains.com/go/
1.5SummaryInthischapter,wetalkedabouthowtoinstallGousingthreedifferentmethodsincludingfromsourcecode,thestandardpackageandviathird-partytools.ThenweshowedyouhowtoconfiguretheGodevelopmentenvironment,mainlycoveringhowtosetupyour$GOPATH.Afterthat,weintroducedsomestepsforcompilinganddeployingGoprograms.WethencoveredGocommands,includingthecompile,install,formatandtestcommands.Finally,therearemanypowerfultoolstodevelopGoprogramssuchasLiteIDE,SublimeText,VSCode,Atom,Goglang,Vim,Emacs,Eclipse,IntelliJIDEA,etc.YoucanchooseanyoneyoulikeexploringtheworldofGo.
LinksDirectoryPrevioussection:GodevelopmenttoolsNextchapter:Gobasicknowledge
Summary
28
2GobasicknowledgeGoisacompiledsystemprogramminglanguage,anditbelongstotheC-family.However,itscompilationspeedismuchfasterthanotherC-familylanguages.Ithasonly25keywords...evenlessthanthe26lettersoftheEnglishalphabet!Let'stakealookatthesekeywordsbeforewegetstarted.
breakdefaultfuncinterfaceselectcasedefergomapstructchanelsegotopackageswitchconstfallthroughifrangetypecontinueforimportreturnvar
Inthischapter,I'mgoingtoteachyousomebasicGoknowledge.YouwillfindouthowconcisetheGoprogramminglanguageis,andthebeautifuldesignofthelanguage.ProgrammingcanbeveryfuninGo.Afterwecompletethischapter,you'llbefamiliarwiththeabovekeywords.
LinksDirectoryPreviouschapter:Chapter1SummaryNextsection:"Hello,Go"
Gobasicknowledge
29
WhatmakesGodifferentfromotherlanguages?TheGoprogramminglanguagewascreatedwithonegoalinmind,tobeabletobuildscalableweb-applicationsforlargescaleaudiencesinalargeteam.Sothatisthereasontheymadethelanguageasstandardizedaspossible,hencethegofmttoolandthestrictusageguidelinestothelanguagewasforthesakeofnothavingtwofactionsinthedeveloperbase,inotherlanguagestherearereligiouswarsonwheretokeeptheopeningbrace?
publicstaticvoidmain(){
}
orpublicstaticvoidmain(){
}
orforpythonshouldweuse4spacesor6spacesoratabortwotabsandotheruserpreferences.IfyouknowpythonthenyoumightbeawareofPEP8,whichisasetofguidelinesabouthowtowriteelegantcode.
Whilethismightseemtobeashallowproblem,whenthecodebasegrowsandmoreandmorepeopleworkonthesamecodebaseitisbecomesincreasinglydifficulttomaintainthecode's"beauty."Weliveinaworldwhererobotscandriveacar,soweshouldn'tjustwritecode,weshouldwriteelegantcode.
Forotherlanguagestherearemanyvariableswhenitcomestowritingcode.Everylanguageisgoodforitsusecase,butGoisalittlespecialbecauseitwasdesignedatacompanywhichistheverysynonymoftheInternet(anddistributedcomputing).Typicallyinordertooptimizeprograms,developerschoosetowriteJavaoverPythonandC++overJava,butalmostallavailablelanguageswidelyinusewerewrittendecadesagowhen1GBstoragewasmuchpricier.Nowstorageandcomputingisrelativelycheapandcomputersaregettingmultiplescores,butthe"oldlanguages"arenotharnessingconcurrencyinawaythatgodoes.It'snotbecausethoselanguagesarebad;utilizingconcurrencywasn'tarelevantusecasewhiletheolderlanguagesevolved.
TomitigatealltheproblemsthatGooglefacedwithcurrenttools,theywroteasystemslanguagecalledGowhichyouareabouttolearn!Therearemanyadvantagestousinggolangandtherearedisadvantagestoo,foreverycoinhasbothsides.Oneofthesignificantimprovementsinincodeformatting.Googlehasdesignedthelanguagetoavoiddebatesoncodeformatting.Gocodewrittenbyanyoneintheworld(assumingtheyknowandusegofmt)willlookexactlythesame.Thiswon'tseemtomatteruntilyouworkinateam!Alsowhenthecompanyusesautomatedcoderevieworsomeotherfancytechnique,theformattedcodemaybreakinotherlanguageswhichdon'thavestrictandstandardformattingrules,butnotingo!
Gowasdesignedwithconcurrencyinmind,pleasenotethatparallelism!=concurrency,thereisanamazingpostbyRobPikeonthegolangblog,youwillfinditthere,itiswortharead.
AnotherveryimportantchangethatistheconceptofGOPATH.Gonearethedayswhenyouhadtocreateafoldercalledcodeandthencreateworkspacesforeclipseandwhatnot.Nowyouhavetokeeponefoldertreeforgocodewhichwillbeupdatedbythepackagemanagerautomatically.Itisalsorecommendedtocreatefolderswitheitheracustomdomainorthegithubdomain,forexampleIcreatedataskmanagerusinggolangsoIcreatedasetoffolders~/go/src/github.com/thewhitetulip/Tasks
Note:In*nixsystems~standsforhomedirectory,whichisthewindowsequivalentofC:\\Users\\username.Nowthe~/go/istheuniverseforthegocodeinyourmachine.Thisisasignificantimprovementoverotherlanguages;wecanstorethecodeefficientlywithouthassles.Whileitmightseemstrangeatfirst,thisapproachmakealotofsensethantheridiculouspackagenames,i.e.packagenamesgeneratedforotherlanguagesusingreversedomains.
Note:Alongwithsrctherearetwofolderspkgwhichisforpackagesandbinwhichisforbinary.
Hello,Go
30
https://blog.golang.org/concurrency-is-not-parallelismhttps://blog.golang.org/
ThisGOPATHadvantageisn'tjustrestrictedtostoringcodeinparticularfolder.Whenyouhavecreatedfivepackagesforyourproject,youdon'thavetoimportthemlike"import./db".Insteadyoucanuseimport"github.com/thewhitetulip/Tasks/db"sothatwhenexecutinggogetonmyrepo,thegotoolwillfindthepackagefromgithub.com/...pathifitwasn'tdownloadedinitially.Thisstandardizesalotofscrewedupthingsintheprogrammingdiscipline.(
Onthefifthline,weusethekeywordfunctodefinethemainfunction.Thebodyofthefunctionisinsideof{},justlikeC,C++andJava.
Asyoucansee,therearenoarguments.Wewilllearnhowtowritefunctionswithargumentsinjustasecond,andyoucanalsohavefunctionsthathavenoreturnvalueorhaveseveralreturnvalues.
Onthesixthline,wecalledthefunctionPrintfwhichisfromthepackagefmt.Thiswascalledbythesyntax.,whichisverylikePython-style.
Aswementionedinchapter1,thepackage'snameandthenameofthefolderthatcontainsthatpackagecanbedifferent.Herethecomesfromthenameinpackage,notthefolder'sname.
Youmaynoticethattheexampleabovecontainsmanynon-ASCIIcharacters.ThepurposeofshowingthisistotellyouthatGosupportsUTF-8bydefault.YoucanuseanyUTF-8characterinyourprograms.
Eachgofileisinsomepackage,andthatpackageshouldbeadistinctfolderintheGOPATH,butmainisaspecialpackagewhichdoesn'trequireamainfolder.Thisisoneaspectwhichtheyleftoutforstandardization!Butshouldyouchoosetomakeamainfolderthenyouhavetoensurethatyourunthebinaryproperly.Alsoonegocodecan'thavemorethanonemaingofile.
~/go/src/github.com/thewhitetulip/Tasks/main$gobuild~/go/src/github.com/thewhitetulip/Tasks$./main/main
thethinghereisthatwhenyourcodeisusingsomestaticfilesorsomethingelse,thenyououghttorunthebinaryfromtherootoftheapplicationasweseeinthesecondlineabove,Iamrunningthemainbinaryoutsidethemainpackage,sometimesyoumightwonderwhyyourapplicationisn'tworkingthenthismightbeoneofthepossibleproblems,pleasekeepthisinmind.
Onethingyouwillnoticehereisthatgodoesn'tseetousesemicolonstoendastatement,well,itdoes,justthereisaminorcatch,theprogrammerisn'texpectedtoputsemicolons,thecompileraddssemicolonstothegocodewhenitcompileswhichisthereasonthatthis(thankfully!)isasyntaxerror
funcmain(){}
becausethecompileraddsasemicolonattheendofmain()whichisasyntaxerrorandasstatedabove,ithelpsavoidreligiouswars,iwishtheycombinevimandemacsandcreateauniversaleditorwhich'llhelpsavesomemorewars!Butfornowwe'lllearnGo.
ConclusionGousespackage(likemodulesinPython)toorganizeprograms.Thefunctionmain.main()(thisfunctionmustbeinthemainpackage)istheentrypointofanyprogram.Gostandardizeslanguageandmostoftheprogrammingmethodology,savingtimeofdeveloperswhichthey'dhavewastedinreligiouswars.Therecanbeonlyonemainpackageandonlyonemainfunctioninsideagomainpackage.GosupportsUTF-8charactersbecauseoneofthecreatorsofGoisacreatorofUTF-8,soGohassupportedmultiplelanguagesfromthetimeitwasborn.
LinksDirectoryPrevioussection:GobasicknowledgeNextsection:Gofoundation
Hello,Go
32
Hello,Go
33
2.2GofoundationInthissection,wearegoingtoteachyouhowtodefineconstants,variableswithelementarytypesandsomeskillsinGoprogramming.
DefinevariablesTherearemanyformsofsyntaxthatcanbeusedtodefinevariablesinGo.
Thekeywordvaristhebasicformtodefinevariables,noticethatGoputsthevariabletypeafterthevariablename.
//defineavariablewithname“variableName”andtype"type"varvariableNametype
Definemultiplevariables.
//definethreevariableswhichtypesare"type"varvname1,vname2,vname3type
Defineavariablewithinitialvalue.
//defineavariablewithname“variableName”,type"type"andvalue"value"varvariableNametype=value
Definemultiplevariableswithinitialvalues.
/*Definethreevariableswithtype"type",andinitializetheirvalues.vname1isv1,vname2isv2,vname3isv3*/varvname1,vname2,vname3type=v1,v2,v3
Doyouthinkthatit'stootedioustodefinevariablesusethewayabove?Don'tworry,becausetheGoteamhasalsofoundthistobeaproblem.Thereforeifyouwanttodefinevariableswithinitialvalues,wecanjustomitthevariabletype,sothecodewilllooklikethisinstead:
/*Definethreevariableswithouttype"type",andinitializetheirvalues.vname1isv1,vname2isv2,vname3isv3*/varvname1,vname2,vname3=v1,v2,v3
Well,Iknowthisisstillnotsimpleenoughforyou.Let'sseehowwefixit.
/*Definethreevariableswithouttype"type"andwithoutkeyword"var",andinitializetheirvalues.vname1isv1,vname2isv2,vname3isv3*/vname1,vname2,vname3:=v1,v2,v3
Nowitlooksmuchbetter.Use:=toreplacevarandtype,thisiscalledashortassignment.Ithasonelimitation:thisformcanonlybeusedinsideofafunctions.Youwillgetcompileerrorsifyoutrytouseitoutsideoffunctionbodies.Therefore,weusuallyusevartodefineglobalvariables.
Gofoundation
34
_(blank)isaspecialvariablename.Anyvaluethatisgiventoitwillbeignored.Forexample,wegive35tob,anddiscard34.(Thisexamplejustshowyouhowitworks.Itlooksuselessherebecauseweoftenusethissymbolwhenwegetfunctionreturnvalues.)
_,b:=34,35
Ifyoudon'tusevariablesthatyou'vedefinedinyourprogram,thecompilerwillgiveyoucompilationerrors.Trytocompilethefollowingcodeandseewhathappens.
packagemain
funcmain(){variint}
ConstantsSo-calledconstantsarethevaluesthataredeterminedduringcompiletimeandyoucannotchangethemduringruntime.InGo,youcanusenumber,booleanorstringastypesofconstants.
Defineconstantsasfollows.
constconstantName=value//youcanassigntypeofconstantsifit'snecessaryconstPifloat32=3.1415926
Moreexamples.
constPi=3.1415926consti=10000constMaxThread=10constprefix="astaxie_"
Elementarytypes
Boolean
InGo,weusebooltodefineavariableasbooleantype,thevaluecanonlybetrueorfalse,andfalsewillbethedefaultvalue.(Youcannotconvertvariables'typebetweennumberandboolean!)
//samplecodevarisActivebool//globalvariablevarenabled,disabled=true,false//omittypeofvariables
functest(){varavailablebool//localvariablevalid:=false//briefstatementofvariableavailable=true//assignvaluetovariable}
Numericaltypes
Integertypesincludebothsignedandunsignedintegertypes.Gohasintanduintatthesametime,theyhavesamelength,butspecificlengthdependsonyouroperatingsystem.Theyuse32-bitin32-bitoperatingsystems,and64-bitin64-bitoperatingsystems.Goalsohastypesthathavespecificlengthincludingrune,int8,int16,int32,int64,byte,uint8,uint16,uint32,uint64.Notethatruneisaliasofint32andbyteisaliasofuint8.
Gofoundation
35
Oneimportantthingyoushouldknowthatyoucannotassignvaluesbetweenthesetypes,thisoperationwillcausecompileerrors.
varaint8
varbint32
c:=a+b
Althoughint32hasalongerlengththanint8,andhasthesametypeasint,youcannotassignvaluesbetweenthem.(cwillbeassertedastypeinthere)
Floattypeshavethefloat32andfloat64typesandnotypecalledfloat.Thelatteroneisthedefaulttypeifusingbriefstatement.
That'sall?No!Gosupportscomplexnumbersaswell.complex128(witha64-bitrealand64-bitimaginarypart)isthedefaulttype,ifyouneedasmallertype,thereisonecalledcomplex64(witha32-bitrealand32-bitimaginarypart).ItsformisRE+IMi,whereREisrealpartandIMisimaginarypart,thelastiistheimaginarynumber.Thereisaexampleofcomplexnumber.
varccomplex64=5+5i//output:(5+5i)fmt.Printf("Valueis:%v",c)
String
WejusttalkedabouthowGousestheUTF-8characterset.Stringsarerepresentedbydoublequotes""orbackticks ̀ `.
//samplecodevarfrenchHellostring//basicformtodefinestringvaremptyStringstring=""//defineastringwithemptystringfunctest(){no,yes,maybe:="no","yes","maybe"//briefstatementjapaneseHello:="Ohaiou"frenchHello="Bonjour"//basicformofassignvalues}
It'simpossibletochangestringvaluesbyindex.Youwillgeterrorswhenyoucompilethefollowingcode.
varsstring="hello"s[0]='c'
WhatifIreallywanttochangejustonecharacterinastring?Trythefollowingcode.
s:="hello"c:=[]byte(s)//convertstringto[]bytetypec[0]='c's2:=string(c)//convertbacktostringtypefmt.Printf("%s\n",s2)
Youusethe+operatortocombinetwostrings.
s:="hello,"m:="world"a:=s+mfmt.Printf("%s\n",a)
andalso.
Gofoundation
36
s:="hello"s="c"+s[1:]//youcannotchangestringvaluesbyindex,butyoucangetvaluesinstead.fmt.Printf("%s\n",s)
WhatifIwanttohaveamultiple-linestring?
m:=`helloworld`
̀ willnotescapeanycharactersinastring.
ErrortypesGohasoneerrortypeforpurposeofdealingwitherrormessages.Thereisalsoapackagecallederrorstohandleerrors.
err:=errors.New("emitmachodwarf:elfheadercorrupted")iferr!=nil{fmt.Print(err)}
Underlyingdatastructure
ThefollowingpicturecomesfromanarticleaboutGodatastructureinRussCox'sBlog.Asyoucansee,Goutilizesblocksofmemorytostoredata.
Figure2.1Gounderlyingdatastructure
Someskills
Definebygroup
Ifyouwanttodefinemultipleconstants,variablesorimportpackages,youcanusethegroupform.
Basicform.
import"fmt"import"os"
consti=100constpi=3.1415constprefix="Go_"
variintvarpifloat32varprefixstring
Groupform.
Gofoundation
37
http://research.swtch.com/godatahttp://research.swtch.com/
import("fmt""os")
const(i=100pi=3.1415prefix="Go_")
var(iintpifloat32prefixstring)
Unlessyouassignthevalueofconstantisiota,thefirstvalueofconstantinthegroupconst()willbe0.Iffollowingconstantsdon'tassignvaluesexplicitly,theirvalueswillbethesameasthelastone.Ifthevalueoflastconstantisiota,thevaluesoffollowingconstantswhicharenotassignedareiotaalso.
iotaenumerate
Gohasonekeywordcallediota,thiskeywordistomakeenum,itbeginswith0,increasedby1.
const(x=iota//x==0y=iota//y==1z=iota//z==2w//Ifthereisnoexpressionaftertheconstantsname,itusesthelastexpression,//soit'ssayingw=iotaimplicitly.Thereforew==3,andyandzbothcanomit"=iota"aswell.)
constv=iota//onceiotameetskeyword`const`,itresetsto`0`,sov=0.
const(e,f,g=iota,iota,iota//e=0,f=0,g=0valuesofiotaaresameinoneline.)
Somerules
ThereasonthatGoisconcisebecauseithassomedefaultbehaviors.
Anyvariablethatbeginswithacapitallettermeansitwillbeexported,privateotherwise.Thesameruleappliesforfunctionsandconstants,nopublicorprivatekeywordexistsinGo.
array,slice,map
array
arrayisanarrayobviously,wedefineoneasfollows.
vararr[n]type
in[n]type,nisthelengthofthearray,typeisthetypeofitselements.Likeotherlanguages,weuse[]togetorsetelementvalueswithinarrays.
Gofoundation
38
vararr[10]int//anarrayoftype[10]intarr[0]=42//arrayis0-basedarr[1]=13//assignvaluetoelementfmt.Printf("Thefirstelementis%d\n",arr[0])//getelementvalue,itreturns42fmt.Printf("Thelastelementis%d\n",arr[9])//itreturnsdefaultvalueof10thelementinthisarray,whichis0inthiscase.
Becauselengthisapartofthearraytype,[3]intand[4]intaredifferenttypes,sowecannotchangethelengthofarrays.Whenyouusearraysasarguments,functionsgettheircopiesinsteadofreferences!Ifyouwanttousereferences,youmaywanttouseslice.We'lltalkaboutlater.
It'spossibletouse:=whenyoudefinearrays.
a:=[3]int{1,2,3}//defineanintarraywith3elements
b:=[10]int{1,2,3}//defineaintarraywith10elements,ofwhichthefirstthreeareassigned.//Therestofthemusethedefaultvalue0.
c:=[...]int{4,5,6}//use`…`toreplacethelengthparameterandGowillcalculateitforyou.
Youmaywanttousearraysasarrays'elements.Let'sseehowtodothis.
//defineatwo-dimensionalarraywith2elements,andeachelementhas4elements.doubleArray:=[2][4]int{[4]int{1,2,3,4},[4]int{5,6,7,8}}
//Thedeclarationcanbewrittenmoreconciselyasfollows.easyArray:=[2][4]int{{1,2,3,4},{5,6,7,8}}
Arrayunderlyingdatastructure.
Figure2.2Multidimensionalarraymappingrelationship
sliceInmanysituations,thearraytypeisnotagoodchoice-forinstancewhenwedon'tknowhowlongthearraywillbewhenwedefineit.Thus,weneeda"dynamicarray".ThisiscalledsliceinGo.
sliceisnotreallyadynamicarray.It'sareferencetype.slicepointstoanunderlyingarraywhosedeclarationissimilartoarray,butdoesn'tneedlength.
//justlikedefininganarray,butthistime,weexcludethelength.varfslice[]int
Thenwedefineaslice,andinitializeitsdata.
slice:=[]byte{'a','b','c','d'}
slicecanredefineexistingslicesorarrays.sliceusesarray[i:j]toslice,whereiisthestartindexandjisendindex,butnoticethatarray[j]willnotbeslicedsincethelengthofthesliceisj-i.
Gofoundation
39
//defineanarraywith10elementswhosetypesarebytesvarar=[10]byte{'a','b','c','d','e','f','g','h','i','j'}
//definetwosliceswithtype[]bytevara,b[]byte
//'a'pointstoelementsfrom3rdto5thinarrayar.a=ar[2:5]//now'a'haselementsar[2],ar[3]andar[4]
//'b'isanothersliceofarrayarb=ar[3:5]//now'b'haselementsar[3]andar[4]
Noticethedifferencesbetweensliceandarraywhenyoudefinethem.Weuse[…]toletGocalculatelengthbutuse[]todefinesliceonly.
Theirunderlyingdatastructure.
Figure2.3Correspondencebetweensliceandarray
slicehassomeconvenientoperations.
sliceis0-based,ar[:n]equalstoar[0:n]Thesecondindexwillbethelengthofsliceifomitted,ar[n:]equalstoar[n:len(ar)].Youcanusear[:]toslicewholearray,reasonsareexplainedinfirsttwostatements.
Moreexamplespertainingtoslice
//defineanarrayvararray=[10]byte{'a','b','c','d','e','f','g','h','i','j'}//definetwoslicesvaraSlice,bSlice[]byte
//someconvenientoperationsaSlice=array[:3]//equalstoaSlice=array[0:3]aSlicehaselementsa,b,caSlice=array[5:]//equalstoaSlice=array[5:10]aSlicehaselementsf,g,h,i,jaSlice=array[:]//equalstoaSlice=array[0:10]aSlicehasallelements
//slicefromsliceaSlice=array[3:7]//aSlicehaselementsd,e,f,g,len=4,cap=7bSlice=aSlice[1:3]//bSlicecontainsaSlice[1],aSlice[2],soithaselementse,fbSlice=aSlice[:3]//bSlicecontainsaSlice[0],aSlice[1],aSlice[2],soithasd,e,fbSlice=aSlice[0:5]//slicecouldbeexpandedinrangeofcap,nowbSlicecontainsd,e,f,g,hbSlice=aSlice[:]//bSlicehassameelementsasaSlicedoes,whichared,e,f,g
sliceisareferencetype,soanychangeswillaffectothervariablespointingtothesamesliceorarray.Forinstance,inthecaseofaSliceandbSliceabove,ifyouchangethevalueofanelementinaSlice,bSlicewillbechangedaswell.
sliceislikeastructbydefinitionanditcontains3parts.
Apointerthatpointstowhereslicestarts.Thelengthofslice.Capacity,thelengthfromstartindextoendindexofslice.
Array_a:=[10]byte{'a','b','c','d','e','f','g','h','i','j'}Slice_a:=Array_a[2:5]
Theunderlyingdatastructureofthecodeaboveasfollows.
Gofoundation
40
Figure2.4Arrayinformationofslice
Therearesomebuilt-infunctionsforslice.
lengetsthelengthofslice.capgetsthemaximumlengthofsliceappendappendsoneormoreelementstoslice,andreturnsslice.copycopieselementsfromoneslicetotheother,andreturnsthenumberofelementsthatwerecopied.
Attention:appendwillchangethearraythatslicepointsto,andaffectotherslicesthatpointtothesamearray.Also,ifthereisnotenoughlengthfortheslice((cap-len)==0),appendreturnsanewarrayforthisslice.Whenthishappens,otherslicespointingtotheoldarraywillnotbeaffected.
map
mapbehaveslikeadictionaryinPython.Usetheformmap[keyType]valueTypetodefineit.
Let'sseesomecode.The'set'and'get'valuesinmaparesimilartoslice,howevertheindexinslicecanonlybeoftype'int'whilemapcanusemuchmorethanthat:forexampleint,string,orwhateveryouwant.Also,theyareallabletouse==and!=tocomparevalues.
//usestringasthekeytype,intasthevaluetype,and`make`initializeit.varnumbersmap[string]int//anotherwaytodefinemapnumbers:=make(map[string]int)numbers["one"]=1//assignvaluebykeynumbers["ten"]=10numbers["three"]=3
fmt.Println("Thethirdnumberis:",numbers["three"])//getvalues//Itprints:Thethirdnumberis:3
Somenoteswhenyouusemap.
mapisdisorderly.Everytimeyouprintmapyouwillgetdifferentresults.It'simpossibletogetvaluesbyindex-youhavetousekey.mapdoesn'thaveafixedlength.It'sareferencetypejustlikeslice.lenworksformapalso.Itreturnshowmanykeysthatmaphas.It'squiteeasytochangethevaluethroughmap.Simplyusenumbers["one"]=11tochangethevalueofkeyoneto11.
Youcanuseformkey:valtoinitializemap'svalues,andmaphasbuilt-inmethodstocheckifthekeyexists.
Usedeletetodeleteanelementinmap.
//Initializeamaprating:=map[string]float32{"C":5,"Go":4.5,"Python":4.5,"C++":2}//maphastworeturnvalues.Forthesecondreturnvalue,ifthekeydoesn't//exist,'ok'returnsfalse.Itreturnstrueotherwise.csharpRating,ok:=rating["C#"]ifok{fmt.Println("C#isinthemapanditsratingis",csharpRating)}else{fmt.Println("WehavenoratingassociatedwithC#inthemap")}
delete(rating,"C")//deleteelementwithkey"c"
AsIsaidabove,mapisareferencetype.Iftwomapspointtosameunderlyingdata,anychangewillaffectbothofthem.
Gofoundation
41
m:=make(map[string]string)m["Hello"]="Bonjour"m1:=mm1["Hello"]="Salut"//nowthevalueofm["hello"]isSalut
make,newmakedoesmemoryallocationforbuilt-inmodels,suchasmap,slice,andchannel,whilenewisfortypes'memoryallocation.
new(T)allocateszero-valuetotypeT'smemory,returnsitsmemoryaddress,whichisthevalueoftype*T.ByGo'sdefinition,itreturnsapointerwhichpointstotypeT'szero-value.
newreturnspointers.
Thebuilt-infunctionmake(T,args)hasdifferentpurposesthannew(T).makecanbeusedforslice,map,andchannel,andreturnsatypeTwithaninitialvalue.Thereasonfordoingthisisbecausetheunderlyingdataofthesethreetypesmustbeinitializedbeforetheypointtothem.Forexample,aslicecontainsapointerthatpointstotheunderlyingarray,lengthandcapacity.Beforethesedataareinitialized,sliceisnil,soforslice,mapandchannel,makeinitializestheirunderlyingdataandassignssomesuitablevalues.
makereturnsnon-zerovalues.
Thefollowingpictureshowshownewandmakearedifferent.
Figure2.5Underlyingmemoryallocationofmakeandnew
Zero-valuedoesnotmeanemptyvalue.It'sthevaluethatvariablesdefaulttoinmostcases.Hereisalistofsomezero-values.
int0int80int320int640uint0x0rune0//theactualtypeofruneisint32byte0x0//theactualtypeofbyteisuint8float320//lengthis4bytefloat640//lengthis8byteboolfalsestring""
LinksDirectoryPrevioussection:"Hello,Go"Nextsection:Controlstatementsandfunctions
Gofoundation
42
2.3ControlstatementsandfunctionsInthissection,wearegoingtotalkaboutcontrolstatementsandfunctionoperationsinGo.
ControlstatementThegreatestinventioninprogrammingisflowcontrol.Becauseofthem,youareabletousesimplecontrolstatementsthatcanbeusedtorepresentcomplexlogic.Therearethreecategoriesofflowcontrol:conditional,cyclecontrolandunconditionaljump.
if
ifwillmostlikelybethemostcommonkeywordinyourprograms.Ifitmeetstheconditions,thenitdoessomethinganditdoessomethingelseifnot.
ifdoesn'tneedparenthesesinGo.
ifx>10{fmt.Println("xisgreaterthan10")}else{fmt.Println("xislessthanorequalto10")}
ThemostusefulthingconcerningifinGoisthatitcanhaveoneinitializationstatementbeforetheconditionalstatement.Thescopeofthevariablesdefinedinthisinitializationstatementareonlyavailableinsidetheblockofthedefiningif.
//initializex,thencheckifxgreaterthanifx:=computedValue();x>10{fmt.Println("xisgreaterthan10")}else{fmt.Println("xislessthan10")}
//thefollowingcodewillnotcompilefmt.Println(x)
Useif-elseformultipleconditions.
ifinteger==3{fmt.Println("Theintegerisequalto3")}elseifinteger<3{fmt.Println("Theintegerislessthan3")}else{fmt.Println("Theintegerisgreaterthan3")}
gotoGohasagotokeyword,butbecarefulwhenyouuseit.gotoreroutesthecontrolflowtoapreviouslydefinedlabelwithinthebodyofsamecodeblock.
Controlstatementsandfunctions
43
funcmyFunc(){i:=0Here://labelendswith":"fmt.Println(i)i++gotoHere//jumptolabel"Here"}
Thelabelnameiscasesensitive.
for
foristhemostpowerfulcontrollogicinGo.Itcanreaddatainloopsanditerativeoperations,justlikewhile.
forexpression1;expression2;expression3{//...}
expression1,expression2andexpression3areallexpressions,whereexpression1andexpression3arevariabledefinitionsorreturnvaluesfromfunctions,andexpression2isaconditionalstatement.expression1willbeexecutedoncebeforelooping,andexpression3willbeexecutedaftereachloop.
Examplesaremoreusefulthanwords.
packagemain
import"fmt"
funcmain(){sum:=0;forindex:=0;index<10;index++{sum+=index}fmt.Println("sumisequalto",sum)}//Print:sumisequalto45
Sometimesweneedmultipleassignments,butGodoesn'thavethe,operator,soweuseparallelassignmentlikei,j=i+1,j-1.
Wecanomitexpression1andexpression3iftheyarenotnecessary.
sum:=1for;sum<1000;{sum+=sum}
Omit;aswell.Feelfamiliar?Yes,it'sidenticaltowhile.
sum:=1forsum<1000{sum+=sum}
Therearetwoimportantoperationsinloopswhicharebreakandcontinue.breakjumpsoutoftheloop,andcontinueskipsthecurrentloopandstartsthenextone.Ifyouhavenestedloops,usebreakalongwithlabels.
Controlstatementsandfunctions
44
forindex:=10;index>0;index--{ifindex==5{break//orcontinue}fmt.Println(index)}//breakprints10、9、8、7、6//continueprints10、9、8、7、6、4、3、2、1
forcanreaddatafromarray,slice,mapandstringwhenitisusedtogetherwithrange.
fork,v:=rangemap{fmt.Println("map'skey:",k)fmt.Println("map'sval:",v)}
BecauseGosupportsmulti-valuereturnsandgivescompileerrorswhenyoudon'tusevaluesthatweredefined,youmaywanttouse_todiscardcertainreturnvalues.
for_,v:=rangemap{fmt.Println("map'sval:",v)}
Withgoyoucanaswellcreateaninfiniteloop,whichisequivalenttowhiletrue{...}inotherlanguges.
for{//yourlogic}
switchSometimesyoumayfindthatyouareusingtoomanyif-elsestatementstoimplementsomelogic,whichmaymakeitdifficulttoreadandmaintaininthefuture.Thisistheperfecttimetousetheswitchstatementtosolvethisproblem.
switchsExpr{caseexpr1:someinstructionscaseexpr2:someotherinstructionscaseexpr3:someotherinstructionsdefault:othercode}
ThetypeofsExpr,expr1,expr2,andexpr3mustbethesame.switchisveryflexible.Conditionsdon'thavetobeconstantsanditexecutesfromtoptobottomuntilitmatchesconditions.Ifthereisnostatementafterthekeywordswitch,thenitmatchestrue.
i:=10switchi{case1:fmt.Println("iisequalto1")case2,3,4:fmt.Println("iisequalto2,3or4")case10:fmt.Println("iisequalto10")default:fmt.Println("AllIknowisthatiisaninteger")}
Controlstatementsandfunctions
45
Inthefifthline,weputmanyvaluesinonecase,andwedon'tneedtoaddthebreakkeywordattheendofcase'sbody.Itwilljumpoutoftheswitchbodyonceitmatchedanycase.Ifyouwanttocontinuetomatchingmorecases,youneedtousethefallthroughstatement.
integer:=6switchinteger{case4:fmt.Println("integer
packagemain
import"fmt"
//returngreatervaluebetweenaandbfuncmax(a,bint)int{ifa>b{returna}returnb}
funcmain(){x:=3y:=4z:=5
max_xy:=max(x,y)//callfunctionmax(x,y)max_xz:=max(x,z)//callfunctionmax(x,z)
fmt.Printf("max(%d,%d)=%d\n",x,y,max_xy)fmt.Printf("max(%d,%d)=%d\n",x,z,max_xz)fmt.Printf("max(%d,%d)=%d\n",y,z,max(y,z))//callfunctionhere}
Intheaboveexample,therearetwoargumentsinthefunctionmax,theirtypesarebothintsothefirsttypecanbeomitted.Forinstance,a,bintinsteadofaint,bint.Thesamerulesapplyforadditionalarguments.Noticeherethatmaxonlyhasonereturnvalue,soweonlyneedtowritethetypeofitsreturnvalue-thisistheshortformofwritingit.
Multi-valuereturn
OnethingthatGoisbetteratthanCisthatitsupportsmulti-valuereturns.
We'llusethefollowingexamplehere.
packagemain
import"fmt"
//returnresultsofA+BandA*BfuncSumAndProduct(A,Bint)(int,int){returnA+B,A*B}
funcmain(){x:=3y:=4
xPLUSy,xTIMESy:=SumAndProduct(x,y)
fmt.Printf("%d+%d=%d\n",x,y,xPLUSy)fmt.Printf("%d*%d=%d\n",x,y,xTIMESy)}
Theaboveexamplereturnstwovalueswithoutnames-youhavetheoptionofnamingthemalso.Ifwenamedthereturnvalues,wewouldjustneedtousereturntoreturnthevaluessincetheyareinitializedinthefunctionautomatically.Noticethatifyourfunctionsaregoingtobeusedoutsideofthepackage,whichmeansyourfunctionnamesstartwithacapitalletter,you'dbetterwritecompletestatementsforreturn;itmakesyourcodemorereadable.
funcSumAndProduct(A,Bint)(addint,multipliedint){add=A+Bmultiplied=A*Breturn}
Controlstatementsandfunctions
47
Variadicfunctions
Gosupportsfunctionswithavariablenumberofarguments.Thesefunctionsarecalled"variadic",whichmeansthefunctionallowsanuncertainnumbersofarguments.
funcmyfunc(arg...int){}
arg…inttellsGothatthisisafunctionthathasvariablearguments.Noticethattheseargumentsaretypeint.Inthebodyoffunction,theargbecomesasliceofint.
for_,n:=rangearg{fmt.Printf("Andthenumberis:%d\n",n)}
Passbyvalueandpointers
Whenwepassanargumenttothefunctionthatwascalled,thatfunctionactuallygetsthecopyofourvariablessoanychangewillnotaffecttotheoriginalvariable.
Let'sseeoneexampleinordertoprovewhati'msaying.
packagemain
import"fmt"
//simplefunctiontoadd1toafuncadd1(aint)int{a=a+1//wechangevalueofareturna//returnnewvalueofa}
funcmain(){x:=3
fmt.Println("x=",x)//shouldprint"x=3"
x1:=add1(x)//calladd1(x)
fmt.Println("x+1=",x1)//shouldprint"x+1=4"fmt.Println("x=",x)//shouldprint"x=3"}
Canyouseethat?Eventhoughwecalledadd1withx,theoriginvalueofxdoesn'tchange.
Thereasonisverysimple:whenwecalledadd1,wegaveacopyofxtoit,notthexitself.
NowyoumayaskhowIcanpasstherealxtothefunction.
Weneedusepointershere.Weknowvariablesarestoredinmemoryandtheyhavesomememoryaddresses.So,ifwewanttochangethevalueofavariable,wemustchangeitsmemoryaddress.Thereforethefunctionadd1hastoknowthememoryaddressofxinordertochangeitsvalue.Herewepass&xtothefunction,andchangetheargument'stypetothepointertype*int.Beawarethatwepassacopyofthepointer,notcopyofvalue.
Controlstatementsandfunctions
48
packagemain
import"fmt"
//simplefunctiontoadd1toafuncadd1(a*int)int{*a=*a+1//wechangedvalueofareturn*a//returnnewvalueofa}
funcmain(){x:=3
fmt.Println("x=",x)//shouldprint"x=3"
x1:=add1(&x)//calladd1(&x)passmemoryaddressofx
fmt.Println("x+1=",x1)//shouldprint"x+1=4"fmt.Println("x=",x)//shouldprint"x=4"}
Nowwecanchangethevalueofxinthefunctions.Whydoweusepointers?Whataretheadvantages?
Allowsustousemorefunctionstooperateononevariable.Lowcostbypassingmemoryaddresses(8bytes),copyisnotanefficientway,bothintermsoftimeandspace,topassvariables.channel,sliceandmaparereferencetypes,sotheyusepointerswhenpassingtofunctionsbydefault.(Attention:Ifyouneedtochangethelengthofslice,youhavetopasspointersexplicitly)
deferGohasawelldesignedkeywordcalleddefer.Youcanhavemanydeferstatementsinonefunction;theywillexecuteinreverseorderwhentheprogramexecutestotheendoffunctions.Inthecasewheretheprogramopenssomeresourcefiles,thesefileswouldhavetobeclosedbeforethefunctioncanreturnwitherrors.Let'sseesomeexamples.
funcReadWrite()bool{file.Open("file")//DosomeworkiffailureX{file.Close()returnfalse}
iffailureY{file.Close()returnfalse}
file.Close()returntrue}
Wesawsomecodebeingrepeatedseveraltimes.defersolvesthisproblemverywell.Itdoesn'tonlyhelpyoutowritecleancodebutalsomakesyourcodemorereadable.
Controlstatementsandfunctions
49
funcReadWrite()bool{file.Open("file")deferfile.Close()iffailureX{returnfalse}iffailureY{returnfalse}returntrue}
Iftherearemorethanonedefers,theywillexecutebyreverseorder.Thefollowingexamplewillprint43210.
fori:=0;i<5;i++{deferfmt.Printf("%d",i)}
Functionsasvaluesandtypes
FunctionsarealsovariablesinGo,wecanusetypetodefinethem.Functionsthathavethesamesignaturecanbeseenasthesametype.
typetypeNamefunc(input1inputType1,input2inputType2[,...])(result1resultType1[,...])
What'stheadvantageofthisfeature?Theansweristhatitallowsustopassfunctionsasvalues.
packagemain
import"fmt"
typetestIntfunc(int)bool//defineafunctiontypeofvariable
funcisOdd(integerint)bool{returninteger%2!=0}
funcisEven(integerint)bool{returninteger%2==0}
//passthefunction`f`asanargumenttoanotherfunctionfuncfilter(slice[]int,ftestInt)[]int{varresult[]intfor_,value:=rangeslice{iff(value){result=append(result,value)}}returnresult}
varslice=[]int{1,2,3,4,5,7}
funcmain(){odd:=filter(slice,isOdd)even:=filter(slice,isEven)
fmt.Println("slice=",slice)fmt.Println("Oddelementsofsliceare:",odd)fmt.Println("Evenelementsofsliceare:",even)}
Controlstatementsandfunctions
50
It'sveryusefulwhenweuseinterfaces.AsyoucanseetestIntisavariablethathasafunctionastypeandthereturnedvaluesandargumentsoffilterarethesameasthoseoftestInt.Therefore,wecanhavecomplexlogicinourprograms,whilemaintainingflexibilityinourcode.
PanicandRecover
Godoesn'thavetry-catchstructurelikeJavadoes.Insteadofthrowingexceptions,Gousespanicandrecovertodealwitherrors.However,youshouldn'tusepanicverymuch,althoughit'spowerful.
Panicisabuilt-infunctiontobreakthenormalflowofprogramsandgetintopanicstatus.WhenafunctionFcallspanic,Fwillnotcontinueexecutingbutitsdeferfunctionswillcontinuetoexecute.ThenFgoesbacktothebreakpointwhichcausedthepanicstatus.Theprogramwillnotterminateuntilallofthesefunctionsreturnwithpanictothefirstlevelofthatgoroutine.paniccanbeproducedbycallingpanicintheprogram,andsomeerrorsalsocausepaniclikearrayaccessoutofboundserrors.
Recoverisabuilt-infunctiontorecovergoroutinesfrompanicstatus.Callingrecoverindeferfunctionsisusefulbecausenormalfunctionswillnotbeexecutedwhentheprogramisinthepanicstatus.Itcatchespanicvaluesiftheprogramisinthepanicstatus,anditgetsniliftheprogramisnotinpanicstatus.
Thefollowingexampleshowshowtousepanic.
varuser=os.Getenv("USER")
funcinit(){ifuser==""{panic("novaluefor$USER")}}
Thefollowingexampleshowshowtocheckpanic.
functhrowsPanic(ffunc())(bbool){deferfunc(){ifx:=recover();x!=nil{b=true}}()f()//iffcausespanic,itwillrecoverreturn}
mainfunctionandinitfunction
Gohastworetentionswhicharecalledmainandinit,whereinitcanbeusedinallpackagesandmaincanonlybeusedinthemainpackage.Thesetwofunctionsarenotabletohaveargumentsorreturnvalues.Eventhoughwecanwritemanyinitfunctionsinonepackage,Istronglyrecommendwritingonlyoneinitfunctionforeachpackage.
Goprogramswillcallinit()andmain()automatically,soyoudon'tneedtocallthembyyourself.Foreverypackage,theinitfunctionisoptional,butpackagemainhasoneandonlyonemainfunction.
Programsinitializeandbeginexecutionfromthemainpackage.Ifthemainpackageimportsotherpackages,theywillbeimportedinthecompiletime.Ifonepackageisimportedmanytimes,itwillbeonlycompiledonce.Afterimportingpackages,programswillinitializetheconstantsandvariableswithintheimportedpackages,thenexecutetheinitfunctionifitexists,andsoon.Afteralltheotherpackagesareinitialized,programswillinitializeconstantsandvariablesinthemainpackage,thenexecutetheinitfunctioninsidethepackageifitexists.Thefollowingfigureshowstheprocess.
Figure2.6FlowofprogramsinitializationinGo
Controlstatementsandfunctions
51
import
WeuseimportveryofteninGoprogramsasfollows.
import("fmt")
Thenweusefunctionsinthatpackageasfollows.
fmt.Println("helloworld")
fmtisfromGostandardlibrary,itislocatedwithin$GOROOT/pkg.Gosupportsthird-partypackagesintwoways.
1. Relativepathimport"./model"//loadpackageinthesamedirectory,Idon'trecommendthisway.2. Absolutepathimport"shorturl/model"//loadpackageinpath"$GOPATH/pkg/shorturl/model"
Therearesomespecialoperatorswhenweimportpackages,andbeginnersarealwaysconfusedbytheseoperators.
1. Dotoperator.Sometimeweseepeopleusefollowingwaytoimportpackages.
import(."fmt")
Thedotoperatormeansyoucanomitthepackagenamewhenyoucallfunctionsinsideofthatpackage.Nowfmt.Printf("Helloworld")becomestoPrintf("Helloworld").
2. Aliasoperation.Itchangesthenameofthepackagethatweimportedwhenwecallfunctionsthatbelongtothatpackage.
import(f"fmt")
Nowfmt.Printf("Helloworld")becomestof.Printf("Helloworld").3. _operator.Thisistheoperatorthatisdifficulttounderstandwithoutsomeoneexplainingittoyou.
import("database/sql"_"github.com/ziutek/mymysql/godrv")
The_operatoractuallymeanswejustwanttoimportthatpackageandexecuteitsinitfunction,andwearenotsureifwewanttousethefunctionsbelongingtothatpackage.
LinksDirectoryPrevioussection:GofoundationNextsection:struct
Controlstatementsandfunctions
52
2.4struct
structWecandefinenewtypesofcontainersofotherpropertiesorfieldsinGojustlikeinotherprogramminglanguages.Forexample,wecancreateatypecalledpersontorepresentaperson,withfieldsnameandage.Wecallthiskindoftypeastruct.
typepersonstruct{namestringageint}
Lookhoweasyitistodefineastruct!
Therearetwofields.
nameisastringusedtostoreaperson'sname.ageisaintusedtostoreaperson'sage.
Let'sseehowtouseit.
typepersonstruct{namestringageint}
varPperson//pispersontype
P.name="Astaxie"//assign"Astaxie"tothefield'name'ofpP.age=25//assign25tofield'age'ofpfmt.Printf("Theperson'snameis%s\n",P.name)//accessfield'name'ofp
Therearethreemorewaystoinitializeastruct.
Assigninitialvaluesbyorder
P:=person{"Tom",25}
Usetheformatfield:valuetoinitializethestructwithoutorder
P:=person{age:24,name:"Bob"}
Defineananonymousstruct,theninitializeit
P:=struct{namestring;ageint}{"Amy",18}
Let'sseeacompleteexample.
struct
53
packagemain
import"fmt"
//defineanewtypetypepersonstruct{namestringageint}
//structispassedbyvalue//comparetheageoftwopeople,thenreturntheolderpersonanddifferencesofagefuncOlder(p1,p2person)(person,int){ifp1.age>p2.age{returnp1,p1.age-p2.age}returnp2,p2.age-p1.age}
funcmain(){vartomperson
tom.name,tom.age="Tom",18bob:=person{age:25,name:"Bob"}paul:=person{"Paul",43}
tb_Older,tb_diff:=Older(tom,bob)tp_Older,tp_diff:=Older(tom,paul)bp_Older,bp_diff:=Older(bob,paul)
fmt.Printf("Of%sand%s,%sisolderby%dyears\n",tom.name,bob.name,tb_Older.name,tb_diff)fmt.Printf("Of%sand%s,%sisolderby%dyears\n",tom.name,paul.name,tp_Older.name,tp_diff)fmt.Printf("Of%sand%s,%sisolderby%dyears\n",bob.name,paul.name,bp_Older.name,bp_diff)}
embeddedfieldsinstructI'vejustintroducedtoyouhowtodefineastructwithfieldnamesandtype.Infact,Gosupportsfieldswithoutnames,butwithtypes.Wecalltheseembeddedfields.
Whentheembeddedfieldisastruct,allthefieldsinthatstructwillimplicitlybethefieldsinthestructinwhichithasbeenembedded.
Let'sseeoneexample.
struct
54
packagemain
import"fmt"
typeHumanstruct{namestringageintweightint}
typeStudentstruct{Human//embeddedfield,itmeansStudentstructincludesallfieldsthatHumanhas.specialtystring}
funcmain(){//instantiateandinitializeastudentmark:=Student{Human{"Mark",25,120},"ComputerScience"}
//accessfieldsfmt.Println("Hisnameis",mark.name)fmt.Println("Hisageis",mark.age)fmt.Println("Hisweightis",mark.weight)fmt.Println("Hisspecialtyis",mark.specialty)
//modifymark'sspecialtymark.specialty="AI"fmt.Println("Markchangedhisspecialty")fmt.Println("Hisspecialtyis",mark.specialty)
fmt.Println("Markbecomeold.Heisnotanathleteanymore")mark.age=46mark.weight+=60fmt.Println("Hisageis",mark.age)fmt.Println("Hisweightis",mark.weight)}
Figure2.7EmbeddinginStudentandHuman
WeseethatwecanaccesstheageandnamefieldsinStudentjustlikewecaninHuman.Thisishowembeddedfieldswork.It'sverycool,isn'tit?Holdon,there'ssomethingcooler!YoucanevenuseStudenttoaccessHumaninthisembeddedfield!
mark.Human=Human{"Marcus",55,220}mark.Human.age-=1
AllthetypesinGocanbeusedasembeddedfields.
struct
55
packagemain
import"fmt"
typeSkills[]string
typeHumanstruct{namestringageintweightint}
typeStudentstruct{Human//structasembeddedfieldSkills//stringsliceasembeddedfieldint//built-intypeasembeddedfieldspecialtystring}
funcmain(){//initializeStudentJanejane:=Student{Human:Human{"Jane",35,100},specialty:"Biology"}//accessfieldsfmt.Println("Hernameis",jane.name)fmt.Println("Herageis",jane.age)fmt.Println("Herweightis",jane.weight)fmt.Println("Herspecialtyis",jane.specialty)//modifyvalueofskillfieldjane.Skills=[]string{"anatomy"}fmt.Println("Herskillsare",jane.Skills)fmt.Println("Sheacquiredtwonewones")jane.Skills=append(jane.Skills,"physics","golang")fmt.Println("Herskillsnoware",jane.Skills)//modifyembeddedfieldjane.int=3fmt.Println("Herpreferrednumberis",jane.int)}
Intheaboveexample,wecanseethatalltypescanbeembeddedfieldsandwecanusefunctionstooperateonthem.
Thereisonemoreproblemhowever.IfHumanhasafieldcalledphoneandStudenthasafieldwithsamename,whatshouldwedo?
Gouseaverysimplewaytosolveit.Theouterfieldsgetupperaccesslevels,whichmeanswhenyouaccessstudent.phone,wewillgetthefieldcalledphoneinstudent,nottheoneintheHumanstruct.Thisfeaturecanbesimplyseenasfieldoverloading.
struct
56
packagemain
import"fmt"
typeHumanstruct{namestringageintphonestring//Humanhasphonefield}
typeEmployeestruct{Humanspecialtystringphonestring//phoneinemployee}
funcmain(){Bob:=Employee{Human{"Bob",34,"777-444-XXXX"},"Designer","333-222"}
fmt.Println("Bob'sworkphoneis:",Bob.phone)fmt.Println("Bob'spersonalphoneis:",Bob.Human.phone)}
LinksDirectoryPrevioussection:ControlstatementsandfunctionsNextsection:Object-oriented
struct
57
Object-orientedWetalkedaboutfunctionsandstructsinthelasttwosections,butdidyoueverconsiderusingfunctionsasfieldsofastruct?Inthissection,Iwillintroduceyoutoanotherformoffunctionthathasareceiver,whichiscalledamethod.
methodSupposeyoudefinea"rectangle"structandyouwanttocalculateitsarea.We'dtypicallyusethefollowingcodetoachievethisgoal.
packagemain
import"fmt"
typeRectanglestruct{width,heightfloat64}
funcarea(rRectangle)float64{returnr.width*r.height}
funcmain(){r1:=Rectangle{12,2}r2:=Rectangle{9,4}fmt.Println("Areaofr1is:",area(r1))fmt.Println("Areaofr2is:",area(r2))}
Theaboveexamplecancalculatearectangle'sarea.Weusethefunctioncalledarea,butit'snotamethodoftherectanglestruct(likeclassmethodsinclassicobject-orientedlanguages).Thefunctionandstructaretwoindependentthingsasyoumaynotice.
It'snotaproblemsofar.However,ifyoualsohavetocalculatetheareaofacircle,square,pentagon,oranyotherkindofshape,youaregoingtoneedtoaddadditionalfunctionswithverysimilarnames.
Figure2.8Relationshipbetweenfunctionandstruct
Obviouslythat'snotcool.Also,theareashouldreallybethepropertyofacircleorrectangle.
Thisiswhereamethodcomestoplay.Themethodisafunctionaffiliatedwithatype.Ithassimilarsyntaxasfunctionexcept,afterthefunckeywordhasaparametercalledthereceiver,whichisthemainbodyofthatmethod.
Usingthesameexample,Rectangle.Area()belongsdirectlytorectangle,insteadofasaperipheralfunction.Morespecifically,length,widthandArea()allbelongtorectangle.
AsRobPikesaid.
"Amethodisafunctionwithanimplicitfirstargument,calledareceiver."
Syntaxofmethod.
func(rReceiverType)funcName(parameters)(results)
Let'schangeourexampleusingmethodinstead.
Object-oriented
58
packagemain
import("fmt""math")
typeCirclestruct{radiusfloat64}
typeRectanglestruct{width,heightfloat64}
//methodfunc(cCircle)Area()float64{returnc.radius*c.radius*math.Pi}
//methodfunc(rRectangle)Area()float64{returnr.width*r.height}
funcmain(){c1:=Circle{10}c2:=Circle{25}r1:=Rectangle{9,4}r2:=Rectangle{12,2}
fmt.Println("Areaofc1is:",c1.Area())fmt.Println("Areaofc2is:",c2.Area())fmt.Println("Areaofr1is:",r1.Area())fmt.Println("Areaofr2is:",r2.Area())}
Notesforusingmethods.
Ifthenameofmethodsarethesamebuttheydon'tsharethesamereceivers,theyarenotthesame.Methodsareabletoaccessfieldswithinreceivers.Use.tocallamethodinthestruct,thesamewayfieldsarecalled.
Figure2.9Methodsaredifferentindifferentstructs
Intheexampleabove,theArea()methodsbelongtobothRectangleandCirclerespectively,sothereceiversareRectangleandCircle.
Onethingthat'sworthnotingisthatthemethodwithadottedlinemeansthereceiverispassedbyvalue,notbyreference.Thedifferencebetweenthemisthatamethodcanchangeitsreceiver'svalueswhenthereceiverispassedbyreference,anditgetsacopyofthereceiverwhenthereceiverispassedbyvalue.
Canthereceiveronlybeastruct?Ofcoursenot.Anytypecanbethereceiverofamethod.Youmaybeconfusedaboutcustomizedtypes.Structisaspecialkindofcustomizedtype-therearemorecustomizedtypes.
Usethefollowingformattodefineacustomizedtype.
typetypeNametypeLiteral
Examplesofcustomizedtypes:
Object-oriented
59
typeageinttypemoneyfloat32typemonthsmap[string]int
m:=months{"January":31,"February":28,..."December":31,}
Ihopethatyouknowhowtousecustomizedtypesnow.SimilartotypedefinC,weuseagestosubstituteintintheaboveexample.
Let'sgetbacktotalkingaboutmethod.
Youcanuseasmanymethodsincustomtypesasyouwant.
packagemain
import"fmt"
const(WHITE=iotaBLACKBLUEREDYELLOW)
typeBoxstruct{width,height,depthfloat64colorColor}typeColorbytetypeBoxList[]Box//asliceofboxes
//methodfunc(bBox)Volume()float64{returnb.width*b.height*b.depth}
//methodwithapointerreceiverfunc(b*Box)SetColor(cColor){b.color=c}
//methodfunc(blBoxList)BiggestsColor()Color{v:=0.00k:=Color(WHITE)for_,b:=rangebl{ifb.Volume()>v{v=b.Volume()k=b.color}}returnk}
//methodfunc(blBoxList)PaintItBlack(){fori,_:=rangebl{bl[i].SetColor(BLACK)}}
//methodfunc(cColor)String()string{
Object-oriented
60
strings:=[]string{"WHITE","BLACK","BLUE","RED","YELLOW"}returnstrings[c]}
funcmain(){boxes:=BoxList{Box{4,4,4,RED},Box{10,10,1,YELLOW},Box{1,1,20,BLACK},Box{10,10,1,BLUE},Box{10,30,1,WHITE},Box{20,20,20,YELLOW},}
fmt.Printf("Wehave%dboxesinourset\n",len(boxes))fmt.Println("Thevolumeofthefirstoneis",boxes[0].Volume(),"cm³")fmt.Println("Thecolorofthelastoneis",boxes[len(boxes)-1].color.String())fmt.Println("Thebiggestoneis",boxes.BiggestsColor().String())
//Let'spaintthemallblackboxes.PaintItBlack()
fmt.Println("Thecolorofthesecondoneis",boxes[1].color.String())fmt.Println("Obviously,now,thebiggestoneis",boxes.BiggestsColor().String())}
Wedefinesomeconstantsandcustomizedtypes.
UseColorasaliasofbyte.DefineastructBoxwhichhasfieldsheight,width,lengthandcolor.DefineastructBoxListwhichhasBoxasitsfield.
Thenwedefinedsomemethodsforourcustomizedtypes.
Volume()usesBoxasitsreceiverandreturnsthevolumeofBox.SetColor(cColor)changesBox'scolor.BiggestsColor()returnsthecolorwhichhasthebiggestvolume.PaintItBlack()setscolorforallBoxinBoxListtoblack.String()useColorasitsreceiver,returnsthestringformatofcolorname.
Isitmuchclearerwhenweusewordstodescribeourrequirements?Weoftenwriteourrequirementsbeforewestartcoding.
Usepointerasreceiver
Let'stakealookatSetColormethod.ItsreceiverisapointerofBox.Yes,youcanuse*Boxasareceiver.Whydoweuseapointerhere?BecausewewanttochangeBox'scolorinthismethod.Thus,ifwedon'tuseapointer,itwillonlychangethevalueinsideacopyofBox.
Ifweseethatareceiveristhefirstargumentofamethod,it'snothardtounderstandhowitworks.
Youmightbeaskingwhywearen'tusing(*b).Color=cinsteadofb.Color=cintheSetColor()method.EitheroneisOKherebecauseGoknowshowtointerprettheassignment.DoyouthinkGoismorefascinatingnow?
Youmayalsobeaskingwhetherweshoulduse(&bl[i]).SetColor(BLACK)inPaintItBlackbecausewepassapointertoSetColor.Again,eitheroneisOKbecauseGoknowshowtointerpretit!
Inheritanceofmethod
Welearnedaboutinheritanceoffieldsinthelastsection.Similarly,wealsohavemethodinheritanceinGo.Ifananonymousfieldhasmethods,thenthestructthatcontainsthefieldwillhaveallthemethodsfromitaswell.
Object-oriented
61
packagemain
import"fmt"
typeHumanstruct{namestringageintphonestring}
typeStudentstruct{Human//anonymousfieldschoolstring}
typeEmployeestruct{Humancompanystring}
//defineamethodinHumanfunc(h*Human)SayHi(){fmt.Printf("Hi,Iam%syoucancallmeon%s\n",h.name,h.phone)}
funcmain(){sam:=Employee{Human{"Sam",45,"111-888-XXXX"},"GolangInc"}mark:=Student{Human{"Mark",25,"222-222-YYYY"},"MIT"}
sam.SayHi()mark.SayHi()}
MethodOverridingIfwewantEmployeetohaveitsownmethodSayHi,wecandefineamethodthathasthesamenameinEmployee,anditwillhideSayHiinHumanwhenwecallit.
Object-oriented
62
packagemain
import"fmt"
typeHumanstruct{namestringageintphonestring}
typeStudentstruct{Humanschoolstring}
typeEmployeestruct{Humancompanystring}
func(h*Human)SayHi(){fmt.Printf("Hi,Iam%syoucancallmeon%s\n",h.name,h.phone)}
func(e*Employee)SayHi(){fmt.Printf("Hi,Iam%s,Iworkat%s.Callmeon%s\n",e.name,e.company,e.phone)//Yesyoucansplitinto2lineshere.}
funcmain(){sam:=Employee{Human{"Sam",45,"111-888-XXXX"},"GolangInc"}mark:=Student{Human{"Mark",25,"222-222-YYYY"},"MIT"}
sam.SayHi()mark.SayHi()}
YouareabletowriteanObject-orientedprogramnow,andmethodsuseruleofcapitallettertodecidewhetherpublicorprivateaswell.
LinksDirectoryPrevioussection:structNextsection:interface
Object-oriented
63
2.6Interface
InterfaceOneofthesubtlestdesignfeaturesinGoareinterfaces.Afterreadingthissection,youwilllikelybeimpressedbytheirimplementation.
Whatisaninterface
Inshort,aninterfaceisasetofmethodsthatweusetodefineasetofactions.
Liketheexamplesinprevioussections,bothStudentandEmployeecanSayHi(),buttheydon'tdothesamething.
Let'sdosomemorework.We'lladdonemoremethodSing()tothem,alongwiththeBorrowMoney()methodtoStudentandtheSpendSalary()methodtoEmployee.
Now,StudenthasthreemethodscalledSayHi(),Sing()andBorrowMoney(),andEmployeehasSayHi(),Sing()andSpendSalary().
ThiscombinationofmethodsiscalledaninterfaceandisimplementedbybothStudentandEmployee.So,StudentandEmployeeimplementtheinterface:SayHi()andSing().Atthesametime,Employeedoesn'timplementtheinterface:BorrowMoney(),andStudentdoesn'timplementtheinterface:SpendSalary().ThisisbecauseEmployeedoesn'thavethemethodBorrowMoney()andStudentdoesn'thavethemethodSpendSalary().
TypeofInterfaceAninterfacedefinesasetofmethods,soifatypeimplementsallthemethodswesaythatitimplementstheinterface.
interface
64
typeHumanstruct{namestringageintphonestring}
typeStudentstruct{Humanschoolstringloanfloat32}
typeEmployeestruct{Humancompanystringmoneyfloat32}
//defineinterfacestypeMeninterface{SayHi()Sing(lyricsstring)Guzzle(beerSteinstring)}
typeYoungChapinterface{SayHi()Sing(songstring)BorrowMoney(amountfloat32)}
typeElderlyGentinterface{SayHi()Sing(songstring)SpendSalary(amountfloat32)}
func(h*Human)SayHi(){fmt.Printf("Hi,Iam%syoucancallmeon%s\n",h.name,h.phone)}
func(h*Human)Sing(lyricsstring){fmt.Println("Lala,lalala,lalalalala...",lyrics)}
func(h*Human)Guzzle(beerSteinstring){fmt.Println("GuzzleGuzzleGuzzle...",beerStein)}
//EmployeeoverloadsSayHifunc(e*Employee)SayHi(){fmt.Printf("Hi,Iam%s,Iworkat%s.Callmeon%s\n",e.name,e.company,e.phone)//Yesyoucansplitinto2lineshere.}
func(s*Student)BorrowMoney(amountfloat32){s.loan+=amount//(againandagainand...)}
func(e*Employee)SpendSalary(amountfloat32){e.money-=amount//Morevodkaplease!!!Getmethroughtheday!}
Weknowthataninterfacecanbeimplementedbyanytype,andonetypecanimplementma
Recommended