Using Coroutines to Create Efficient, High-Concurrency Web Applications
Table of Contents - Programmer Books · Concurrency Summary Web foundation Web working principles...
Transcript of Table of Contents - Programmer Books · Concurrency Summary Web foundation Web working principles...
-
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:[email protected]://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