ptg16105617 From the Library of YIGUANG HU ptg16105617 The Go Programming Language From the Library of YIGUANG HU ptg16105617 This page intentionally left blank From the Library of YIGUANG HU ptg16105617 The Go Programming Language Alan A. A. Donovan Google Inc. Brian W. Kernighan Princeton University New York • Boston • Indianapolis • San Francisco Toronto • Montreal • London • Munich • Paris • Madrid Capetown • Sydney • Tokyo • Singapore • Mexico City From the Library of YIGUANG HU ptg16105617 Many of the designations used by manufacturers and sellers to distinguish their products are claimed as trademarks. Where those designations appear in this book, and the publisher was aware of a trade- mark claim, the designations have been printed with initial capital letters or in all capitals. T e authors and publisher have taken care in the preparation of this book, but make no expressed or implied warranty of any kind and assume no responsibility for errors or omissions. No liability is assumed for incidental or consequential damages in connection with or arising out of the use of the information or programs contained herein. For information about buying this title in bulk quantities, or for special sales opportunities (which may include electronic versions; custom cover designs; and content particular to your business, train- ing goals, marketing focus, or branding interests), please contact our corporate sales department at corpsales@pearsoned.com or (800) 382-3419. For government sales inquiries, please contact governmentsales@pearsoned.com. For questions about sales outside the United States, please contact international@pearsoned.com. Visit us on the Web: informit.com/aw Library of Congress Control Number: 2015950709 Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan All rights reserved. Printed in the United States of America. T is publication is protected by copyright, and permission must be obtained from the publisher prior to any prohibited reproduction, storage in a retrieval system, or transmission in any form or by any means, electronic, mechanical, photocopying, recording, or likewise. To obtain permission to use material from this work, please submit a written request to Pearson Education, Inc., Permissions Department, 200 Old Tappan Road, Old Tappan, New Jersey 07675, or you may fax your request to (201) 236-3290. Front cover: Millau Viaduct, Tarn valley, southern France. A paragon of simplicity in modern engi- neering design, the viaduct replaced a convoluted path from capital to coast with a direct route over the clouds. © Jean-Pierre Lescourret/Corbis. Back cover: the original Go gopher. © 2009 Renée French. Used under Creative Commons Attribu- tions 3.0 license. Typeset by the authors in Minion Pro, Lato, and Consolas, using Go, grof , ghostscript, and a host of other open-source Unix tools. Figures were created in Google Drawings. ISBN-13: 978-0-13-419044-0 ISBN-10: 0-13-419044-0 Text printed in the United States on recycled paper at RR Donnelley in Crawfordsville, Indiana. First printing, October 2015 From the Library of YIGUANG HU ptg16105617 Fo r Leil a an d Me g The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 This page intentionally left blank From the Library of YIGUANG HU ptg16105617 Cont ents Pr eface xi TheOrigins ofGoxii TheGoPro jec t xiii Organizat ionofthe Bookxv Wh ere toFindMoreInfor mat ionxvi Ac knowledgments xvii 1. Tutorial1 1.1. Hel lo, Wor ld1 1.2. Command-L ineArguments 4 1.3. FindingDup lic ateLines 8 1.4. Animated GIFs 13 1.5. FetchingaURL 15 1.6. FetchingURLs Con cur rently17 1.7. A We b Server 19 1.8. Loose End s 23 2. Pro gramStr ucture27 2.1. Names 27 2.2. Declarat ions 28 2.3. Var iables 30 2.4. Assig nments 36 2.5. Typ e Decl arat ions 39 2.6. Packages andFiles 41 2.7. Scope 45 vii The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 viii CONTENTS 3. Basic Data Typ es51 3.1. Int egers 51 3.2. Float ing-Point Numbers 56 3.3. Complex Numbers 61 3.4. Boole ans63 3.5. Str ings64 3.6. Con stants75 4. Com positeTyp es81 4.1. Arrays 81 4.2. Slices 84 4.3. Maps 93 4.4. Str ucts99 4.5. JSON107 4.6. Text andHTMLTempl ates113 5. Func tions 119 5.1. FunctionDeclarat ions 119 5.2. Rec ursion121 5.3. MultipleRetur n Values 124 5.4. Erro rs127 5.5. FunctionValues 132 5.6. Anony mou s Func tions 135 5.7. Var iadic Functions 142 5.8. Defer red FunctionCal ls143 5.9. Panic 148 5.10. Recov er151 6. Metho ds 155 6.1. Met hod Declarat ions 155 6.2. Met hodswit h aPoint erReceiver158 6.3. ComposingTyp es by Str uct Emb edding161 6.4. Met hod Values andExpressions 164 6.5. Example: Bit Vec tor Typ e 165 6.6. Encapsulat ion168 7. Interfaces171 7.1. Int erfaces as Contrac ts 171 7.2. Int erface Typ es 174 7.3. Int erface Satisfac tion175 7.4. ParsingFlags wit h flag.Value 179 7.5. Int erface Values 181 The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 CONTENTSix 7.6. Sor tingwit h sort.Interface 186 7.7. The http.Handler Interface 191 7.8. The error Interface 196 7.9. Example: ExpressionEvaluator197 7.10. Typ e As ser tions 205 7.11. Discriminat ingError s with Typ e As ser tions 206 7.12. Quer yingBeh avior s with Int erface Typ e As ser tions 208 7.13. Typ e Sw itch es210 7.14. Example: Token-B ased XML Decoding213 7.15. A Fe w Wo rds ofAdv ice 216 8. Gor o utines and Channels 217 8.1. Goroutines217 8.2. Example: Con cur rentClo ckSer ver 219 8.3. Example: Con cur rentEch o Server 222 8.4. Channel s 225 8.5. Looping inParal lel234 8.6. Example: Con cur rentWeb Craw ler 239 8.7. Multiplexingwit h select 244 8.8. Example: Con cur rentDirec tor y Traversal247 8.9. Cancellat ion251 8.10. Example: ChatSer ver 253 9. Concurrency withShared Vari ables257 9.1. Race Con dit ion s 257 9.2. Mut ual Exc lusion: sync.Mutex 262 9.3. Read/Write Mut exes: sync.RWMutex 266 9.4. Memor y Sy nchro nizat ion267 9.5. Lazy Initializat ion: sync.Once 268 9.6. TheRace Detec tor 271 9.7. Example: Con cur rentNon-Blo cking Cache 272 9.8. Goroutinesand Threads 280 10. Pack ages and the GoTool283 10.1. Int roduc tion283 10.2. Imp ort Pat hs284 10.3. ThePackageDeclarat ion285 10.4. Imp ort Declarat ions 285 10.5. Blank Imp orts286 10.6. Packages andNaming289 10.7. TheGoTool290 The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 xCONTENTS 11. Testing 301 11.1. The go test To ol302 11.2. Test Func tions 302 11.3. Cov erage318 11.4. Benchmark Func tions 321 11.5. Profiling323 11.6. Example Func tions 326 12. Reflecti on329 12.1. Why Reflec tion?329 12.2. reflect.Type and reflect.Value 330 12.3. Display,aRec ursiveValue Print er333 12.4. Example: Enco dingS-E xpressions 338 12.5. Setting Var iables wit h reflect.Value 341 12.6. Example: DecodingS-E xpressions 344 12.7. AccessingStr uct Field Tags 348 12.8. Displaying the Met hodsofaTyp e 351 12.9. A Wo rdofCaution 352 13. Low-L evel Pro gramming353 13.1. unsafe.Sizeof, Alignof,and Offsetof 354 13.2. unsafe.Pointer 356 13.3. Example: DeepEquivalence 358 13.4. Cal lingCCodewit h cgo 361 13.5. Another WordofCaution 366 Index367 The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 Pref ace ‘‘Go is anopensourc e prog rammi n g lang uagethatmak esiteasytobui ldsimpl e,rel iab le, an d efficientsof tware.’’ (Fro m theGoweb sit e at golang.org) Go was conceive d in Septemb er2007 byRob ert Gries emer,Rob Pike, and Ken Thomps on, all at Google, and was announced inNov emb er2009. Thegoals ofthe langu ageand its accom- pany ing tools weretobeexpressive, efficient in bot h comp ilation and exe cut ion,and effec tive in writing reliableand robustprograms. Go bears a sur face simi lar ity toC and,likeC,isatoolfor prof essionalprogrammers, achie v- ingmaximum effe ctwit h minimum means.But it ismuchmorethananupdated versionof C. Itbor rowsand adaptsgood ide as from manyother langu ages, whi leavoidingfeaturesthat have led tocomplexity and unreliablecode. Its facilities for con cur rency are new and efficient, andits approach to dat aabstrac tionand obj e ct-oriente d prog rammingisunu sually flexible. It hasaut omat ic memory managementor garb age col lec tion. Go isesp eci ally wel l suit edfor bui ldinginf rastr ucturelikenet wor ked ser vers, andtools and systems for prog rammers, but it istruly a general-pur pos e language and find s us e in domains as divers e as graphics, mobileapp lic ations,and machinelearning. Ithas becom e popu lar as a repl acementfor unt ypedscr ipt ing langu ages because itbal ances expressivenesswit h safety : Go programstypic ally run fasterthanprogramswritt enindynamic langu ages andsuf fer far fe wer crashesdue tounexp ected typ e er ror s. Go isanopen-s ource pro jec t,sosourcecodefor itscompi ler,librar ies,andtools is fre ely avai l- able toany one.Contr ibution s to the pro jec t come fro m an active worldw ide community.Go runs onUnix-li kesystems—Linux, Fre eBSD, OpenBSD, Mac OS X—andonPlan9and Micros oft Windows. Programswritt eninone ofthese env iro nmentsgeneral lywor k without mo dification on the others. xi The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 xii PREFACE Thisbookismeant tohelpyou start usingGoeffec tive lyrig htaway andtouse itwel l,tak ing full advantage ofGo’slangu agefeaturesand stand ard librar ies to write clear, idiomatic, and efficientprograms. TheOrigins ofGo Like biolog ical species, successf ullangu ages beget offspring thatincor poratethe advantagesof their ancestors;int erbre e dingsom etimesleads tosur prisingstrengt hs; and, ver y occasionally, aradic al ne w fe ature ariseswit houtpre cedent. Wecan lear n alot about why a langu ageisthe way itisand whatenv iro nment ithas beenadapt edfor bylooking atthese influences. The figurebelow shows the most imp ortantinfluences ofearlier programminglangu ages on thedesig n of Go. Go issom etimesdes crib edasa‘‘C-li kelangu age,’’ or as ‘‘Cfor the 21stcentury.’’ Fr omC,Go in her ite d itsexpressionsyntax, cont rol-flow statements, basic dat a types, cal l-by-value param- eter passing, point ers,and above all,C’semp hasisonprogramsthatcompi letoefficient machinecodeand cooperatenatural lywit h theabstrac tions ofcur rentoperat ingsystems. The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 THE ORIGINS OF GO xiii Butthere are other ancestors inGo’sfami lytre e.One maj orstreamofinfluence comesfro m languagesbyNik lausWir th, beg inningwit h Pascal.Modula-2 inspired the packagecon cept. Ob ero n eliminated the distinc tionbet weenmoduleint erface files andmoduleimp lementation files. Obero n-2 influence d thesyntaxfor packages, imports, anddeclarat ions,and Obj e ct Ob ero n prov ide d thesyntaxfor met hod declarat ions. Anot her lineage among Go’sancestors,and one thatmakes Godistinc tiveamong recent prog ramminglangu ages, isa sequence oflit tle-k now n research langu ages deve lop edatBel l Labs, allins pired bythe con ceptof commu nicating sequent ial pro cesses (CSP) fro m To ny Ho are’sseminal 1978 pap er on the found ation s of con cur rency.InCSP,aprogram isaparal lel comp osition of processesthathavenoshare d st ate;the pro cessescommunic ateand synchro- nize usingchannel s.But Hoare’sCSP was a for mal langu agefor des cribingthe fundament al concepts ofcon cur rency,not a programminglangu agefor writing exe cut ableprograms. RobPikeand othersbegan toexp erimentwit h CSPimp lementation s as actu allangu ages. The firs t was cal le d Sque ak (‘‘Alangu agefor communic atingwit h mice’’), whichprovide d alan- gu agefor handlingmou seand key board events, wit h st aticallycre ate d ch annel s.Thiswas fo llowe d by Newsque ak, whichoffered C-li kestatement and expressionsyntaxand Pas cal-li ke type not ation.Itwas a purelyfunctionallangu agewit h garb agecol lec tion,again aimed at managing key board , mous e,and windowevents. Channel s became firs t-class values, dynami- callycre ate d andstorable in variables. ThePlan9operat ingsystemcar r iedthese ide as forwardinalangu agecal le d Alef.Alef tried to makeNewsque ak aviablesystemprogramminglangu age, but itsomissionofgarb agecol- le ction made conc urrency too painf ul. Ot her cons tructions inGoshowthe influence ofnon-ancestral genes hereand there;for example iota is loosely fro m APL, andlexic al scop e with neste d func tions isfro m Scheme (andmostlangu ages since). Heretoo wefind nove l mu tat ions.Go’sinnovat ive slices provide dy namic arrays wit h efficientrandomaccessbut als o permit sop histicate d sh aring ar rangementsreminiscentoflin ked lists. And the defer st atement isnew wit h Go. TheGoProject Al l prog ramminglangu ages reflec t theprogrammingphi losop hyoftheir creators,whichoften includes a significant component ofreactiontothe perceive d shortcomings ofearlier lan- gu ages. TheGopro jec t was bor neoffrust rat ionwit h several sof twaresystems atGooglethat were suf fer ingfro m an explosionofcomplexity.(Thispro blem isbynomeans unique to Go ogle.) As Rob Pikeput it, ‘‘comp lexity ismultiplic ative’’: fixingapro blem bymak ingone par t of the systemmorecomplex slowlybut surelyaddscomplexity toother par ts. Wi thcon stant pres- sure toadd featuresand opt ion s andconfigurat ions,and toshipcodequickly, it’seasy to neglec t simplicity,eventhoug h in the lon g runsimplicity isthe key togood sof tware. The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 xiv PREFACE Simp licity requires morewor k at the beg inningofapro jec t to reduce an ideatoits essenceand more dis cip lineoverthe lifet imeofapro jec t to distinguish good changesfro m badorper ni- cious ones. Wit h sufficienteffor t,agood change can beaccommodated wit houtcompromis- ingwhatFre d Brooks cal le d the ‘‘conceptu alint egr ity’’ of the desig n butabad change cannot, andaper nicious change trades simplicity for itsshallow cou sin, conv enience.Onlythrough simplicity ofdesig n canasystemremain stable, sec ure , andcoh erent asitgrows. TheGopro jec t includes the langu ageits elf,its tools and stand ard librar ies, andlastbut not le ast, a cultural agenda ofradic alsimplicity.Asarecenthig h-leve l language , Go has the bene- fitofhindsig ht, andthe basics aredon e we ll: ithas garbagecol lec tion,apackagesystem, firs t- cl ass functions,lexic al scop e,asystemcal l interface,and immut ablestr ingsinwhichtext is general lyencoded inUTF-8. But it has comp arat ive lyfew featuresand isunlikelytoadd more . Fo r inst ance, ithas noimp licitnumer icconv ersions,nocon str uctor s or destr uctor s,no op erator overloading, nodefau ltparameter values, noinher itance, nogener ics, no exception s, no macros, nofunctionannot ation s,and no thread-lo cal storage. The langu ageismatureand st able, and guarante esbackwards compatibi lit y:older Goprogramscan becompi led and run with newer versions ofcompi lersand stand ard librar ies. Go has enough ofatyp e systemtoavoid mostofthe carelessmistakesthatplague program- mers indynamic langu ages, but it has a simpler typ esystemthancomparable typ edlangu ages. Thisappro ach can som etimesleadtoisolate d pockets of ‘‘untyped’’ prog rammingwit hin a broader framewor k of typ es, andGoprogrammersdonot gotothe lengt hsthatC++ or Haskel l prog rammersdotoexpress safet y prop erties as typ e-bas edpro ofs. But inprac tice Go givesprogrammersmuchofthe safet y andrun-t imeper for mance benefits ofarel ative ly st ron g type systemwit houtthe burden ofacomplex one. Go encourages an awarenessofcontemp orar y comp utersystemdesig n, partic ularlythe importance oflocality.Its bui lt-in dat a typesand most librar y data str uctures arecraf ted to work natural lywit houtexplicitinitializat ionorimp licitcon str uctor s,sorel ative lyfew mem- or y al location s andmemor y wr itesare hidden in the code. Go’saggregatetyp es (str uctsand ar rays) hold their elements direc tly,requir inglessstorageand fewer allo cat ions and point er indirec tion s than langu ages thatuse indirec t fields.And since the moder ncomp uterisapar- al lelmachine, Gohas conc urrency featuresbas edonCSP,asmention edearlier.The var iable- size stacksofGo’slig htweig htthreads or goro utines areinitial lysmall enoug h that creating one goro utine ische apand cre ating a millionisprac tic al. Go’sstand ard librar y,often descr ibedascomingwit h ‘‘batt eries include d,’’ prov ides cle an buildingblo cks andAPIsfor I/O,text pro cessing, graphics, cryptography,net wor king, and dist ribut edapp lic ations,wit h supp ort for manystand ard file for mats andpro tocol s.The librar iesandtools make extensive use ofconvent ion toreduce the need for configurat ionand explanation,thu s simplif yingprogram logic andmak ingdiverse Go programsmoresimi lar to each other andthu s easier tolearn.Pro jec tsbui ltusingthe go to oluse onlyfile andidentifier namesand anocc asionalspeci al commenttodeter mineall the librar ies, exec utables, tests, benchmarks, examples, platfor m-specificvar iants, anddocumentation for a proj e ct; the Go source its elf cont ainsthe bui ld sp ecification. The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 THE GO PROJECTxv Or ganization ofthe Book We assume thatyou haveprogrammed inone ormoreother langu ages, whether comp ile dli ke C, C++, andJava, orint erprete d li kePyt hon,Ruby, and JavaS crip t,sowewon’tspell out every- thing as if for a tot albeg inner.Sur face sy ntaxwill befami liar, as will var iables andcon stants, expressions,control flow,and functions. Chapter1 isatut orialonthe basic cons tructsofGo, int roduce d thro ugh a dozen programsfor ever ydaytasks like readingand writing files, for matting text, creating images, andcommuni- cating wit h Internet clients andser vers. Chapter2 des crib esthe str uctural elements ofaGoprogram—de clarat ions,var iables, new types, packages and files, andscope.Chapt er3 dis cussesnumbers,boole ans, str ings, andcon- st ants, andexplainshow topro cessUnico de.Chapt er4 des crib escomposite typ es, that is, typesbui ltupfro m simpler onesusingarrays, maps, str ucts, and sli ces,Go’sappro ach to dy namic lists. Chapt er5 cov ers functions and dis cusseserror handling, panic and recover, andthe defer st atement. Chapters 1 through 5 are thu s thebasics, things thatare par t of any mainst reamimp erat ive language . Go’ssyntaxand sty lesom etimesdif fer fro m ot her langu ages, but mostprogram- mers will pickthemupquickly. The remainingchapt ers focus ontopics where Go’sappro ach is lessconvent ion al: met hods, interfaces, conc urrency,packages, testing , andreflec tion. Go has an unusualappro ach to obj e ct-oriente d prog ramming. There are noclass hierarchies, or indeed any class es; comp lex obj e ctbeh avior s arecre ate d from simpler onesbycomposition, notinher itance. Met hodsmay beass oci ated wit h anyuser-define d type,not juststr uctures, andthe rel ation shipbet weencon crete typ es andabstrac t types(interfaces)isimp licit, soa concrete typ e maysat isf y an interface thatthe typ e’sdesig ner was unawareof. Met hodsare covere d in Chapt er6and int erfaces in Chapt er7. Chapter8 presentsGo’sappro ach to con cur rency,whichisbas edonthe ide a of communic at- ingsequential pro cesses(CSP), embodie d by goroutinesand channel s.Chapt er9 explainsthe more tradition alasp ectsofcon cur rency bas edonshare d var iables. Chapter10des crib espackages, the mech anism for organizinglibrar ies. Thischapt erals o shows how tomakeeffec tive use ofthe go to ol, whichprovides for compi lat ion, testing , benchmarking , prog ram formatting , do cumentation,and manyother tasks, allwit hin a single command. Chapter11deals wit h test ing , whereGotakes a not ably lig htweig htappro ach,avoiding abstrac tion-l aden framewor ksinfavor of simplelibrar ies andtools.The testing librar ies prov ide a found ation atopwhichmorecomplex abstrac tions can bebui lt if necessary. Chapter12dis cussesreflec tion,the abi lit y of a prog ram to examineits own represent ation during exe cut ion.Reflec tion isapow erfultool, thoug h on e to beusedcaref ully; thischapt er explains findingthe rig htbal ance byshowing how itisusedtoimp lementsom e importantGo librar ies. Chapter13explainsthe gor y det ails oflow-le vel programmingthatusesthe unsafe packagetosteparo und Go’styp esystem, andwhenthatisappro priate. The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 xvi PREFACE Each chapterhas a numberofexercis esthatyou can use totestyourunderst andingofGo, and to explore extensions and alt ernat ivestothe examples fro m thebook. Al l butthe most trivialcodeexamples in the bookare avai lable for dow nlo ad from the public Gitrep ository at gopl.io.Eachexampleisidentified byits packageimp ort pat handmay be conv enientlyfetch ed, bui lt, andins tal le d usingthe go get command. You’ll need tocho ose a direc tor y to beyourGowor ksp ace andset the GOPATH enviro nment var iable topoint toit. The go to olwill cre ate the direc tor y if necessary.For example: $export GOPATH=$HOME/gobook #choose workspace directory $goget gopl.io/ch1/helloworld #fetch, build, install $$GOPATH/bin/helloworld #run Hello, BF To run the examples, you will need atleast version1.5 ofGo. $goversion go version go1.5 linux/amd64 Fo llowthe ins tructions at https://golang.org/doc/install if the go to olonyourcom- puterisolder ormissing. WheretoFind MoreInformation Thebestsourcefor moreinfor mat ionabout Goisthe offici al we b site, https://golang.org, whichprovides accesstothe documentation,includingthe Go Programmi n g Lang uageSpecifi- cati on,stand ard packages, andthe like. There are als o tutorialsonhow towrite Goand how to write itwel l,and a wide variet y of onlinetext andvide o resources thatwill bevaluablecom- plements tothisbook. TheGoBlog at blog.golang.org pu blishessom e of the bestwriting on Go, wit h ar ticles onthe state ofthe langu age, plans for the fut ure , reportsonconferences, andin-depth explanation s of a wide variet y of Go-rel ate dtopics. Oneofthe most usefulasp ectsofonlineaccesstoGo(andareg rettablelimitation of a pap er book) isthe abi lit y to run Goprogramsfro m theweb pages thatdes crib e them. Thisfunc- tion ality isprovide d by the GoPlayg round at play.golang.org,and may beemb edde d within other pages, suchasthe home pageat golang.org or the documentation pages ser ved by the godoc to ol. ThePlayg round makes itconvenienttoper for m simpleexp eriments toche ckone’sunder- st andingofsyntax, semantics, orlibrar y packages wit h short programs, andinmanyways takesthe place ofare ad-e val-print loop (REPL) in other langu ages. Its persistentURLs are greatfor sharing snipp ets ofGocodewit h ot hers, for rep ortingbugs ormak ingsug gestion s. Builtatopthe Playg round,the GoTourat tour.golang.org is a sequence ofshort int erac tive lessons onthe basic ideas andcon str uctions ofGo, anorderly wal k thro ugh the langu age. Theprimary shortcomingofthe Playg round and the Touristhatthe y al lowonlystand ard librar ies to beimp orted,and manylibrar y fe atures—networ king, for example—arerestr icted The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 WHERE TOFIND MORE INFORMATION xvii forprac tic al or sec urity reasons.The y also requireaccesstothe Int ernet tocompi leand run each program. Sofor moreelaborateexp eriments, you will havetorun Goprogramsonyour ow n comp uter. For tunatelythe dow nlo ad processisstraig htfor ward, soitshouldnot take more thanafew minut estofetch the Godistr ibution fro m golang.org andstart writing and runningGoprogramsofyourown. SinceGoisanopen-s ource pro jec t,you can readthe codefor any typ e or function in the stan- dard librar y on lineat https://golang.org/pkg;the samecodeispar t of the dow nlo ade d dist ribut ion.Use thisto figureout how som ethingwor ks, ortoanswerquestion s ab out det ails,ormerelytosee how exp erts write reallygood Go. Acknowledgments RobPikeand RussCox,coremembers ofthe Goteam, readthe manus cript several times wit h greatcare; their comments oneverythingfro m word choice tooveral l st ruc tureand organiza- tion havebeeninvaluable. Whi le prep aringthe Jap anes e transl ation,Yoshi kiShibata wentfar beyond the cal l of duty; his met iculou s eyespott ednumerou s inconsistencies in the Eng lish text anderror s in the code. Wegre atlyappre ciate thoro ugh revie wsandcriticalcommentson theent ire manus cript fro m Br ian Goetz, Corey Kos ak, Ar noldRobbins, JoshBle e cherSny der, andPeter Weinberger. We are indebte d to SameerAjmani,Itt aiBal aban, Dav idCrawshaw, BillyDon ohue, Jon athan Feinberg , Andrew Gerrand, Rob ert Gries emer,JohnLinder man, Minux Ma, Bryan Mills, Bal a Nataraj an, Cosmos Nicolaou , Paul Stanifor th, Nigel Tao,and HowardTrickey for many helpf ulsug gestion s.Weals o than k DavidBrai lsfordand RaphLevien for typ esetting adv ice. OureditorGregDoenchatAddison-Wesle y gotthe bal l ro llingoriginallyand has beencon- tinuou sly helpf uleversince.The AWpro duc tionteam—Jo hnFuller,Day naIsley,Julie Nahi l, Chut i Pras ertsith,and Barb ara Wo o d—hasbeenoutst anding; author s couldnot hop e forbet- tersup por t. AlanDon ovan wishestothank:SameerAjmani,Chr isDemet riou, WaltDrummon d,and Reid TatgeatGooglefor allow ing him timetowrite;Steph enDon ovan, for his adv ice andtimely encouragement; andabove all,his wifeLei laKazemi,for her unhesitating ent husi asm and unwaver ingsup por t forthispro jec t,despit e thelon g hoursofdistrac tionand abs ente eism from fami lylifethatitent ailed. Br ian Ker nighanisdeeply gratef ultofriends and col leagues for their pat ience andforbearance as hemov edslowlyalong the pat h to underst anding, and esp eci ally tohis wifeMeg , whohas been unfailinglysup por tiveofbook-w rit ing and somuchels e. Ne w Yo rk Oc tob er2015 The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 This page intentionally left blank From the Library of YIGUANG HU ptg16105617 1 Tutorial Thischapt erisatourofthe basic comp onentsofGo. Wehop e to provide enough infor mat ion andexamples toget you off the gro und and doing usefulthings as quicklyaspossible. The examples here, and indeed inthe whole book, areaimed attasks thatyou mig hthavetodoin therealwor ld. Inthischapt erwe’ll trytogiveyou a taste ofthe diversity ofprogramsthatone mig htwrite inGo, ranging fro m simplefile pro cessingand a bit of graphics tocon cur rent Internet clients andser vers. Wecer tain lywon’texplain everythinginthe firs t ch apt er, but studying suchprograms in a new langu agecan be an effec tive way toget started. Wh enyou’re learninganew langu age, there’sanatural tendency towrite codeasyou wou ld have writt enitinalangu ageyou already know. Beawareofthisbiasasyou learn Goand try to avoid it. We’ve tried toillustrateand explain how towrite good Go, souse the codehereas aguide whenyou’re writing your own. 1.1. Hello, World We’ll start wit h thenow-t radition al ‘‘hel lo, wor ld’’ example, whichapp earsatthe beg inningof TheCProgrammi n g Lang uage,publishe d in 1978. Cisone ofthe most direc t influences on Go,and ‘‘hel lo, wor ld’’ illustrates a numberofcentral ideas. gopl.io/ch1/helloworld package main import "fmt" func main() { fmt.Println("Hello, BF") } 1 The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 2CHAPTER 1. TUTORIAL Go isacompi led langu age. The Gotoolchain conv ertsasourceprogram andthe things it dep ends onint o inst ruc tions inthe nat ive machinelangu ageofacomputer. These tools are accessedthrough a singlecommand cal le d go that has a numberofsub command s.The sim- plestofthese sub command s is run,whichcompi les the sourcecodefro m on e or moresource files whose names endin .go,lin ks it wit h librar ies, then runsthe resulting exe cut able file. (Wewill use $ as the command pro mpt throughoutthe book.) $gorun helloworld.go No t surprisingly, thisprints Hello, BF Go nat ive lyhandles Unico de,soitcan pro cesstext in allthe wor ld’slangu ages. If the program ismorethanaone-shotexp eriment, it’slikelythatyou wou ldwanttocompi le it once andsavethe compi led resultfor later use.Thatisdon e with go build: $gobuild helloworld.go Thiscre atesanexe cut ablebinar yfile cal le d helloworld that can berun anytimewit houtfur- ther pro cessing: $./helloworld Hello, BF We havelab ele d each sig nificant exampleasareminder thatyou can obt ain the codefro m the book’ssourcecoderep ository at gopl.io: gopl.io/ch1/helloworld If you run go get gopl.io/ch1/helloworld,itwill fetch the sourcecodeand place itinthe correspondingdirec tor y.There’smoreabout thistopic in Sec tion 2.6 andSec tion 10.7. Let’snow tal k ab out the program its elf.Gocodeisorganize dinto packages, whichare simi lar to librar ies or modules in other langu ages. A packagecon sists ofone ormore .go source files in a singledirec tor y that define whatthe packagedoes. Eachsource file beg inswit h a package de clarat ion, here package main,thatstateswhichpackagethe file belon gsto, fol low edbyalist of other packages thatitimp orts, andthenthe declarat ions ofthe program thatare store d in that file. TheGostand ard librar y hasover100 packages for commontasks like inp utand out put, sorting, and text manipu lat ion. For ins tance,the fmt packagecontainsfunctions for printing formatte d output and scanninginp ut. Println is one ofthe basic out put functions in fmt;it pr intsone ormorevalues, sep arated byspaces, wit h anewlinecharac ter at the end sothatthe values appear as a singlelineofout put. Package main is speci al.Itdefinesastand alone exe cut ableprogram, not a librar y.Wit hin package main the func tion main is als o sp eci al—it’swhere exe cut ion of the program beg ins. Wh ate ver main do es is whatthe program does. Of course, main wi l l normal lycal l up on func- tion s in other packages to do muchofthe wor k,such as the function fmt.Println. The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 SECTION 1.1. HELLO, WORLD 3 We musttel l thecompi ler whatpackages areneeded bythissourcefile; that’sthe roleofthe import de clarat ionthatfol lowsthe package de clarat ion. The ‘‘hel lo, wor ld’’ prog ram us es on lyone functionfro m on e ot her package, but mostprogramswill imp ort morepackages. Yo u mu stimp ort exac tly the packages you need.Aprog ram wi l l notcompi leifthere are missingimp ortsorifthere are unnecessary ones. Thisstr ict requirementpre vents references to unu sed packages fro m acc umulat ing as programsevo l ve. The import de clarat ions mustfol low the package de clarat ion. After that, a program consists of the declarat ions offunctions,var iables, cons tants, andtyp es (introduce d by the key words func, var, const,and type); for the most par t, theorder ofdeclarat ions doesnot matter. This prog ram is about asshort aspossiblesince itdeclaresonlyone function, whichintur n calls on lyone other function. Tosavespace,wewill som etimesnot showthe package and import de clarat ions whenpresent ing examples, but the y areinthe sourcefile andmustbethere to comp ile the code. Afunctiondeclarat ioncon sists ofthe key word func,the nameofthe function, a parameter list (empt y for main), a resultlist(also emp tyhere), andthe bodyofthe function—thestate- mentsthatdefine whatitdoes—enclos edinbraces. We’ll takeaclos er lo okatfunctions in Chapter5. Go doesnot requiresemicolons atthe end s of statementsordeclarat ions,exceptwhere two or more app ear onthe sameline. Ineffec t,newlines fol low ing cer tain tokensare converted int o semicolons,sowhere newlines areplace d matt ers to pro per parsingofGocode. For ins tance, theopeningbrace { of the functionmustbeonthe samelineasthe end ofthe func de clara- tion,not onalinebyits elf,and inthe expression x+y,anewlineisper mitt edafter but not before the + op erator. Go takes a stron g st anceoncodefor matting . The gofmt to olrewritescodeint o thestand ard format, andthe go to ol’s fmt su bcommandapp lies gofmt to all the files in the specified pack- age, orthe onesinthe cur rentdirec tor y by defau lt. All Gosourcefiles in the bookhavebeen runthrough gofmt,and you shouldget into the habit of doing the samefor yourown code. Decl aring a stand ard for mat by fiat eliminates a lotofpoint lessdeb ate about trivia and,more importantly, enables a variet y of aut omated sourcecodetransfor mat ions thatwou ldbe infeasible if arbit rar y formatting were allow ed. Many text editors can beconfigured torun gofmt each timeyou saveafile,sothatyoursource co de is always pro perly for matte d. Arel ate d to ol, goimports,addition allymanages the ins er- tion and removal ofimp ort declarat ions asneeded.Itisnot par t of the stand ard distr ibution butyou can obt ain itwit h this command: $goget golang.org/x/tools/cmd/goimports Fo r most users,the usu alway todow nlo adandbui ld packages, run their tests, showtheir doc- umentation,and soon, iswit h the go to ol, whichwe’ll look at in Sec tion 10.7. The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 4CHAPTER 1. TUTORIAL 1.2. Command-Line Arguments Most programspro cesssom e inputtopro duce som e output;that’sprett y much the definition of computing . Buthow doesaprogram get inputdat a on whichtooperate? Som e prog rams generatetheir own data,but moreoften, inputcom esfro m an exter nal source: a file,anet wor k connec tion,the out put of another program, a useratakey board , command-linearguments, or the like. The next few examples will dis cusssom e of these alt ernat ives, startingwit h com- mand-linearguments. The os packageprovides functions and other values for dealingwit h theoperat ingsystemina pl atfor m-indep endentfashion. Command-linearguments areavai lable toaprogram in a var iable named Args that ispar t of the os package; thu s itsnameany where outside the os packageis os.Args. Thevar iable os.Args is a sli ce of str ings. Slices areafundament alnot ion inGo, and we’ll tal k alot moreabout themsoon. For now,thin k of a slice as a dynamic ally size d sequence s of ar ray elements where indiv idu alelements can beaccessedas s[i] andacontiguous subse- quence as s[m:n].The numberofelements isgiven by len(s).Asinmostother program- minglangu ages, allindexinginGouses half-open intervalsthatinclude the firs t index but exclude the last, because itsimplifies logic. For example, the slice s[m:n],where 0 ≤ m ≤ n ≤ len(s),contains n-m elements. The firs t elementof os.Args, os.Args[0],isthe nameofthe command its elf; the other ele- mentsare the arguments thatwerepresent edtothe program whenitstarted exe cut ion.A slice expressionofthe for m s[m:n] yields a slice thatreferstoelements m thro ugh n-1,sothe elements weneed for our next exampleare those inthe slice os.Args[1:len(os.Args)].If m or n is omitt ed, itdefau lts to0or len(s) resp ectively, sowecan abbreviate the desired slice as os.Args[1:]. Here’sanimp lementation of the Unix echo command, whichprintsits command-lineargu- mentsonasingleline. Itimp ortstwo packages, whichare given as a parenthesize dlist rat her than as individu al import de clarat ions.Eit her for m is legal,but convent ion allythe listfor m is us ed. The order ofimp ortsdoesn’tmatter; the gofmt to olsor tsthe packagenames into alph abeticalorder.(Wh enthere are several versions ofanexample, wewill often number them soyou can besureofwhichone we’re tal kingabout.) gopl.io/ch1/echo1 // Echo1 prints its command-line arguments. package main import ( "fmt" "os" ) The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 SECTION 1.2. COMMAND-LINE ARGUMENTS5 func main() { var s, sep string for i := 1; i < len(os.Args); i++ { s+=sep + os.Args[i] sep = " " } fmt.Println(s) } Comments beg in with //.All text fro m a // to the end ofthe lineiscomment ary for prog rammersand isignored bythe compi ler.Byconvent ion,wedes crib e each package in a commentimmediate lypre cedingits packagedeclarat ion; for a main package, thiscomment is on e or morecompletesentences thatdes crib e theprogram as a whole. The var de clarat iondeclarestwo var iables s and sep,oftyp e string.Avar iable can beini- tialize d as par t of itsdeclarat ion. Ifitisnot explicitlyinitialize d,itisimp licitlyinitialize d to the zero value forits typ e,whichis 0 fornumer ic typesand the emp tystr ing "" forstr ings. Thus inthisexample, the declarat ionimp licitlyinitializes s and sep to emp tystr ings. We’ll have moretosay aboutvar iables anddeclarat ions inChapt er2. Fo r numb ers,Goprovides the usu alarithmeticand log ical operator s.Whenapp lie d to st rings, how ever, the + op erator concatenate s thevalues, sothe expression sep + os.Args[i] repres ents the con catenat ionofthe str ings sep and os.Args[i].The statement weusedin theprogram, s+=sep + os.Args[i] is an assig nment statement that conc atenatesthe old value of s with sep and os.Args[i] and assig nsitbackto s;itisequivalentto s=s+sep + os.Args[i] Theoperator += is an assig nment operator.Eacharithmeticand log ical operator like + or * has acor respondingassig nmentoperator. The echo prog ramcouldhaveprint edits out put inaloopone pie ce at a time, but thisversion insteadbui ldsupastr ing byrep eatedlyapp endingnew text tothe end.The str ing s st artslife empt y,thatis, wit h value "",and eachtripthrough the loopaddssom e text toit; afterthe firs t it erat ion, a space isals o inserted sothatwhenthe loopis finishe d,there isone space bet ween each argument. Thisisaquadrat ic processthatcou ldbecostlyifthe numberofarguments is large , butfor echo,that’sunlikely. We’ll showanumberofimp rov edversions of echo in this ch apt erand the next thatwill dealwit h anyrealinefficiency. Theloopindex variable i is declare d in the firs t part ofthe for lo op. The := sy mbolispar t of a sh ort var iab ledeclarati on,astatement thatdeclaresone ormorevar iables andgives them appropriatetyp es basedonthe initializer values; there’smoreabout this in the next chapt er. Theincrement statement i++ adds1to i;it’sequivalentto i+=1whichisintur n equivalent to i=i+1.There’sacor respondingdecrement statement i-- that subtrac ts 1. Thes e are The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 6CHAPTER 1. TUTORIAL st atements, not expressions asthe y areinmostlangu ages in the C fami ly, so j=i++ is illegal, andthe y arepostfixonly, so --i is not legal either. The for lo opisthe onlyloopstatement inGo. Ithas a numberoffor ms, one ofwhichis illustrated here: for initialization; condition; post { // zero or more statements } Parent hes es arenever usedaro und the three componentsofafor lo op. The braces are mand atory,how ever, and the openingbrace mustbeonthe sameline as the post st atement. Theopt ion al initialization st atement isexe cut edbeforethe loopstarts. Ifitispresent,it mu stbeasimp lestatement,thatis, a short var iable decl arat ion, an incrementorassig nment st atement,orafunctioncal l.The condition is a boole an expressionthatisevaluate d at the beginningofeachiterat ionofthe loop; if itevaluatesto true,the statementscontrol led bythe lo opare exe cut ed. The post st atement isexe cut edafter the bodyofthe loop, thenthe con di- tion isevaluate d again. Theloopend s when the con dit ion becom esfalse. Anyofthese par ts maybeomitt ed. Ifthere isno initialization andno post,the semi- colons may also beomitt ed: // a traditional "while" loop for condition { // ... } If the con dit ion isomitt edent ire ly in any ofthese for ms, for examplein // a traditional infinite loop for { // ... } theloopisinfinite, thoug h lo ops ofthisfor m maybeter minated insom e ot her way,likea break or return st atement. Anot her for m of the for lo opiterates overara nge of values fro m adat a type likeast ringora slice.Toillustrate, here’sasecon d versionof echo: gopl.io/ch1/echo2 // Echo2 prints its command-line arguments. package main import ( "fmt" "os" ) The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 SECTION 1.2. COMMAND-LINE ARGUMENTS7 func main() { s, sep := "", "" for _, arg := range os.Args[1:] { s+=sep + arg sep = " " } fmt.Println(s) } In eachiterat ionofthe loop, range produces a pair ofvalues: the index andthe value ofthe elementatthatindex. Inthisexample, wedon’tneed the index, but the syntaxofarange lo op re quires thatifwedealwit h theelement, wemustdealwit h theindex too.One ide a wouldbe to assig n theindex to an obv iou sly temporar y var iable like temp andignoreits value,but Go do es notper mitunu sed local variables, sothiswou ldresult in a compi lat ionerror. Thesolut ion istouse the bl ank ident ifier,whose nameis _ (t hat is, an underscore). Theblank identifier may beusedwhene ver synt axrequires a variablenamebut prog ramlog ic do es not, forins tance todis cardanunwante d lo opindex whenwerequireonlythe elementvalue.Most Go programmerswou ldlikelyuse range and _ to write the echo prog ram as abov e,since the indexingover os.Args is imp licit, not explicit, andthu s easier toget rig ht. Thisversionofthe program usesa short var iable decl arat iontodeclare and initialize s and sep,but wecou ldequ allywel l have declare d thevar iables sep arately. There are several ways to declare a str ing var iable; these are all equivalent: s:="" var s string var s = "" var s string = "" Whyshouldyou preferone for m to another? The firs t form,ashort var iable decl arat ion, is themostcompact,but it may beusedonlywit hin a function, not for package-le vel var iables. Thesecon d form relies ondefau ltinitializat iontothe zerovalue for str ings, whichis "".The thirdfor m is rarelyusedexceptwhendeclaring multiplevar iables. Thefourthfor m is explicit ab out the var iable’styp e,whichisredundant whenitisthe sameasthatofthe initial value but ne cessary inother cas es wherethe y arenot ofthe sametyp e.Inprac tice,you shouldgeneral ly us e on e of the firs t twofor ms, wit h explicitinitializat iontosay thatthe initial value is importantand imp licitinitializat iontosay thatthe initial value doesn’tmatter. As not edabove , each timearo und the loop, the str ing s gets comp letelynew contents. The += st atement makes a new str ing bycon catenat ingthe old str ing , aspace charac ter,and the next argument, thenassig nsthe newstr ing to s.The old cont entsof s arenolon g erinuse,sothe y wi l l be garb age-collec ted indue course. If the amountofdat a invo l vedislarge , this cou ldbecostly. A simpler andmoreefficient solut ion wou ldbetouse the Join func tionfro m the strings package: The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 8CHAPTER 1. TUTORIAL gopl.io/ch1/echo3 func main() { fmt.Println(strings.Join(os.Args[1:], " ")) } Final ly, ifwedon’tcareabout for mat but justwanttosee the values, perhaps for debug ging, we canlet Println format the results for us: fmt.Println(os.Args[1:]) Theout put of thisstatement islikewhatwewou ldget fro m strings.Join,but wit h sur- ro undingbrackets. Any slice may beprint edthisway. Exercis e1.1: Mo dif y the echo prog ram to als o pr int os.Args[0],the nameofthe command that invo ked it. Exercis e1.2: Mo dif y the echo prog ram to print the index andvalue ofeachofits arguments, on e perline. Exercis e1.3: Experiment tomeasure the dif ference in runningtimebet weenour pot ent ial ly inefficientversions and the one thatuses strings.Join.(Section1.6 illustrates par t of the time package, and Sec tion 11.4 shows how towrite benchmark tests for systematicper- formance evaluation.) 1.3. Finding DuplicateLines Prog ramsfor file copy ing , pr int ing , searching, sor ting, count ing , andthe likeall haveasimi lar st ruc ture: a loop overthe inp ut, som e comp utation on eachelement, andgenerat ionofout put on the flyoratthe end.We’ll showthree var iants ofaprogram cal le d dup;itispar tly ins pired by the Unix uniq command, whichlooks for adj acentdup lic atelines. Thestr uctures and packages usedare model s that can beeasi lyadapt ed. The firs t versionof dup pr intseachlinethatapp earsmorethanonceinthe stand ard inp ut, preceded byits count. Thisprogram introduces the if st atement,the map data typ e,and the bufio package. gopl.io/ch1/dup1 // Dup1 prints the text of each line that appears more than // once in the standard input, preceded by its count. package main import ( "bufio" "fmt" "os" ) The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 SECTION 1.3. FINDING DUPLICATE LINES 9 func main() { counts := make(map[string]int) input := bufio.NewScanner(os.Stdin) for input.Scan() { counts[input.Text()]++ } // NOTE: ignoring potential errors from input.Err() for line, n := range counts { if n > 1 { fmt.Printf("%d\t%s\n", n, line) } } } As wit h for,parenthes es arenever usedaro und the con dit ion inan if st atement,but braces arerequired for the body. There can beanopt ion al else part thatisexe cut edifthe con dit ion is false. A map holdsaset ofkey/value pairsand provides cons tant-t imeoperat ions tostore , retr ieve, or testfor aniteminthe set. Thekey may beofany typ e whos evalues can comp are d with ==, st rings beingthe most commonexample; the value may beofany typ e at all. Inthisexample, thekeysare str ingsand the values are ints. Thebui lt-in function make createsanew emp ty map; ithas other usestoo.Maps aredis cussed at lengt h in Sec tion 4.3. Each time dup re ads a lineofinp ut, the lineisusedasakey int o themap andthe cor- resp ondingvalue isincrement ed. The statement counts[input.Text()]++ is equivalentto thes e twostatements: line := input.Text() counts[line] = counts[line] + 1 It’snot a pro blem if the map doesn’tyet cont ain thatkey.The firs t time a newlineisseen, the expression counts[line] on the rig ht-handside evaluatestothe zerovalue for itstyp e,which is 0 for int. To print the results, weuse another range-b ased for lo op, thistimeoverthe counts map. As before , each iterat ionpro duces two results, a key and the value ofthe map elementfor that ke y.The order ofmap iterat ionisnot specified,but inprac tice itisrandom, varying fro m on e runtoanother.Thisdesig n is int ent ion al, since itpre vents programsfro m re lying onany par- ticularorder ingwhere non e is guarante e d. Onwardtothe bufio package, whichhelps makeinp utand out put efficientand convenient. Oneofits mostusefulfeaturesisatyp e called Scanner that reads inp utand bre aks itint o lines or words;it’soften the easiestway topro cessinp utthatcom esnatural ly in lines. Theprogram usesashort var iable decl arat iontocre ate a new var iable input that referstoa bufio.Scanner: input := bufio.NewScanner(os.Stdin) The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 10 CHAPTER 1. TUTORIAL Thescanner reads fro m theprogram’sstand ard inp ut. Eachcal l to input.Scan() re ads the next lineand remov esthe newlinecharac ter fro m theend;the resultcan beret rie ved bycal l- ing input.Text().The Scan func tionretur ns true if there isalineand false when there is no more inp ut. Thefunction fmt.Printf,like printf in C andother langu ages, pro duces for matte d output from a listofexpressions.Its firs t argumentisafor mat str ing thatspecifies how subsequent arguments shouldbefor matte d. Thefor mat ofeachargumentisdeter mined byaconversion ch arac ter,aletterfol low ing a percentsig n. Fo r example, %d formats an integeroperandusing de cimal not ation,and %s exp ands tothe value ofastr ing operand. Printf hasoveradozen suchconversions,whichGoprogrammerscal l verb s.Thistable isfar from a completespecification but illustrates manyofthe featuresthatare avai lable: %d de cimal integer %x, %o, %b integer in hexade cimal,octal,binar y %f, %g, %e floating-p ointnumber: 3.141593 3.141592653589793 3.141593e+00 %t boole an: true or false %c rune (Unico deco de point) %s st ring %q quot edstr ing "abc" or rune 'c' %v anyvalue in a natural for mat %T type ofany value %% literal percentsig n(nooperand) Thefor mat str ing in dup1 also containsatab \t andanewline \n.Str ing lit eralsmay cont ain such es cap e sequ ences forrepresent ing other wis e invisiblecharac ters. Printf do es notwrite a ne wlinebydefau lt. Byconvent ion,for matting functions whose names endin f,suchas log.Printf and fmt.Errorf,use the for matting rules of fmt.Printf,where asthose whose namesend in ln fo llow Println,for matting their arguments as if by %v,fol low edbya ne wline. Many programsreadeit her fro m their stand ard inp ut, as abov e,orfro m asequence ofnamed files. Thenext versionof dup canreadfro m thestand ard inp utorhandlealistoffile names, using os.Open to openeachone: gopl.io/ch1/dup2 // Dup2 prints the count and text of lines that appear more than once // in the input. It reads from stdin or from a list of named files. package main import ( "bufio" "fmt" "os" ) The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 SECTION 1.3. FINDING DUPLICATE LINES 11 func main() { counts := make(map[string]int) files := os.Args[1:] if len(files) == 0 { countLines(os.Stdin, counts) }else { for _, arg := range files { f, err := os.Open(arg) if err != nil { fmt.Fprintf(os.Stderr, "dup2: %v\n", err) continue } countLines(f, counts) f.Close() } } for line, n := range counts { if n > 1 { fmt.Printf("%d\t%s\n", n, line) } } } func countLines(f *os.File, counts map[string]int) { input := bufio.NewScanner(f) for input.Scan() { counts[input.Text()]++ } // NOTE: ignoring potential errors from input.Err() } Thefunction os.Open returnstwo values. The firs t is anopenfile (*os.File)thatisusedin su bsequentreads bythe Scanner. Thesecon d resu ltof os.Open is a value ofthe bui lt-in error type.If err equals the speci al built-in value nil,the file was opene d successf ully. The file isread, and whenthe end ofthe inputisreach ed, Close clos es thefile andreleasesany res ources. On theother hand, if err is not nil,som ethingwentwro ng. Inthatcas e,the error value descr ibesthe pro blem. Our sim- ple-minde d er ror handlingprintsamessage onthe stand ard error streamusing Fprintf and theverb %v,whichdispl ays a value ofany typ e in a default for mat, and dup then car r ies on with thenext file; the continue st atement goestothe next iterat ionofthe enclosing for lo op. In the int erestsofkeeping codesamples toareasonablesize,our early examples areint ent ion- al lysom ewhat cavalier abouterror handling. Cle arly wemustche ckfor anerror fro m os.Open;how ever, weare ignor ing the lesslikelypossibi lit y that an erro r couldocc ur while re adingthe file wit h input.Scan.Wewill not e pl aces where we’ve skipp ederror che cking , andwewill goint o thedet ails oferror handling in Sec tion 5.4. No tice thatthe cal l to countLines precedes its decl arat ion. Functions and other package-le vel entities may bedeclare d in anyorder. The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 12 CHAPTER 1. TUTORIAL Amap isareference to the dat a st ruc turecre ate d by make.Whenamap ispassedtoafunc- tion,the functionreceivesa copyofthe reference,soany changesthe cal le d func tionmakes to theunderly ing dat a st ruc turewill bevisible through the cal ler’smap reference too.Inour example, the values inserted int o the counts mapby countLines areseenby main. Theversions of dup ab ove operateina‘‘st reaming’’ mo deinwhichinp utisreadand bro ken into lines as needed,soinprincip lethese programscan handleanarbit rar y amount ofinp ut. An alt ernat ive appro ach istoreadthe ent ire inp utint o memory inone big gulp,split it int o lines allatonce, thenpro cessthe lines. Thefol low ing version, dup3,operates in thatfashion. It int roduces the function ReadFile (f rom the io/ioutil package), whichreads the ent ire cont entsofaname d file,and strings.Split,whichsplitsastr ing int o aslice ofsubst rings. (Split is the opp osite of strings.Join,whichwesaw earlier.) We’ve simplified dup3 some what. First,itonlyreads name d files, not the stand ard inp ut, since ReadFile re quires a file nameargument. Secon d,wemov edthe count ing ofthe lines back into main,since itisnow needed inonlyone place. gopl.io/ch1/dup3 package main import ( "fmt" "io/ioutil" "os" "strings" ) func main() { counts := make(map[string]int) for _, filename := range os.Args[1:] { data, err := ioutil.ReadFile(filename) if err != nil { fmt.Fprintf(os.Stderr, "dup3: %v\n", err) continue } for _, line := range strings.Split(string(data), "\n") { counts[line]++ } } for line, n := range counts { if n > 1 { fmt.Printf("%d\t%s\n", n, line) } } } ReadFile returnsabyteslice thatmustbeconverted int o a string so itcan besplit by strings.Split.Wewill dis cussstr ingsand byteslices at lengt h in Sec tion 3.5.4. The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 SECTION 1.4. ANIMATED GIFS13 Un der the cov ers, bufio.Scanner, ioutil.ReadFile,and ioutil.WriteFile us e the Read and Write methodsof *os.File,but it’srarethatmostprogrammersneed toaccessthose lower-le vel routinesdirec tly.The hig her-le vel functions likethose fro m bufio and io/ioutil areeasier touse. Exercis e1.4: Mo dif y dup2 to print the names ofall files in whicheachdup lic ated lineocc urs. 1.4. Animated GIFs Thenext program demon strates basic usage ofGo’sstand ard image packages, whichwe’ll use to cre ate a sequence ofbit-mappedimagesand thenencodethe sequence as a GIF animat ion. Theimages, cal le d Li ssajous figure s,wereastaplevisualeffec t in sci-fifilmsofthe 1960s. They arethe paramet ric cur ves pro duce d by har monic osci l lat ionintwo dimensions,suchastwo sinewaves fed int o the x and y inputs of an oscillos cope.Figure1.1 shows som e examples. Figure 1.1. Fo urLissajous figures. Thereare several new con str uctsinthiscode, including const de clarat ions,str uct typ es,and comp osite lit erals. Unlikemostofour examples, thisone als o invo l vesfloating-p ointcom- putation s.We’ll dis cussthese topics onlybrieflyhere, pushingmostdet ails off tolater chap- ters,since the primary goalrig htnow istogiveyou anide a of whatGolooks like and the kind s of things thatcan bedon e easi lywit h thelangu ageand its librar ies. gopl.io/ch1/lissajous // Lissajous generates GIF animations of random Lissajous figures. package main import ( "image" "image/color" "image/gif" "io" "math" "math/rand" "os" ) The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 14 CHAPTER 1. TUTORIAL var palette = []color.Color{color.White, color.Black} const ( whiteIndex = 0 // first color in palette blackIndex = 1 // next color in palette ) func main() { lissajous(os.Stdout) } func lissajous(out io.Writer) { const ( cycles = 5//number of complete x oscillator revolutions res = 0.001 // angular resolution size = 100 // image canvas covers [-size..+size] nframes = 64 // number of animation frames delay = 8//delay between frames in 10ms units ) freq := rand.Float64() * 3.0 // relative frequency of y oscillator anim := gif.GIF{LoopCount: nframes} phase := 0.0 // phase difference for i := 0; i < nframes; i++ { rect := image.Rect(0, 0, 2*size+1, 2*size+1) img := image.NewPaletted(rect, palette) for t := 0.0; t < cycles*2*math.Pi; t += res { x:=math.Sin(t) y:=math.Sin(t*freq + phase) img.SetColorIndex(size+int(x*size+0.5), size+int(y*size+0.5), blackIndex) } phase += 0.1 anim.Delay = append(anim.Delay, delay) anim.Image = append(anim.Image, img) } gif.EncodeAll(out, &anim) // NOTE: ignoring encoding errors } Af ter importingapackagewhose pat h hasmultiplecomponents, like image/color,werefer to the packagewit h anamethatcom esfro m thelastcomponent.Thu s thevar iable color.White belongstothe image/color packageand gif.GIF belongsto image/gif. A const de clarat ion(§3.6) gives names tocon stants, thatis, values thatare fixe d at comp ile time,suchasthe numer ical parametersfor cyc les, frames, anddel ay. Like var de clarat ions, const de clarat ions may appear at packagelevel (so the names arevisible throughoutthe pack- age) orwit hin a function(so the names arevisible onlywit hin thatfunction). Thevalue ofa cons tantmustbeanumber, str ing , or boole an. Theexpressions []color.Color{...} and gif.GIF{...} are comp osite lit era ls (§4.2, §4.4.1), acompact not ation for ins tantiat ingany ofGo’scomposite typ es from a sequence ofelement values. Here, the firs t on e is a slice andthe secon don e is a st ruc t. The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 SECTION 1.5. FETCHING A URL 15 Thetyp e gif.GIF is a str uct typ e (§4.4). A st ruc t is a gro upofvalues cal le d fiel ds,often ofdif- ferent typ es, that arecol lec ted toget her in a singleobj e ctthatcan betre ate d as a unit. The var iable anim is a str uct oftyp e gif.GIF.The str uct lit eral createsastr uct value whose Loop- Count fieldisset to nframes;all other fields have the zerovalue for their typ e.The indiv idu al fields ofastr uct can beaccessedusingdot not ation,asinthe finaltwo assig nments which explicitlyupdatethe Delay and Image fields of anim. The lissajous func tionhas two neste d lo ops. Theout erlooprunsfor 64iterat ions,each producingasingleframeofthe animat ion. Itcre atesanew 201&201 imagewit h apalette of twocolor s,white and black.All pixel s areinitial lyset tothe palette’szerovalue (the zerot h colorinthe palette), whichweset towhite. Eachpassthrough the inner loop generates a new imagebysetting som epixe lstoblack.The resultisapp ended,usingthe bui lt-in append func- tion (§4.2.1), toalistofframes in anim,along wit h aspecified del ayof80ms. Final lythe sequence offrames anddel ays isencoded int o GIF for mat andwritt entothe out put stream out.The typ e of out is io.Writer,whichlets uswrite to a wide range ofpossibledestina- tion s, as we’ll showsoon. Theinner loop runsthe two oscillator s.The x os cillator isjustthe sinefunction. The y os cil- latorisals o asinus oid,but itsfre quency rel ative tothe x os cillator isarandomnumber between0and 3,and its phase rel ative tothe x os cillator isinitial lyzerobut incre aseswit h each frameofthe animat ion. Thelooprunsunt i l the x os cillator has comp leted five full cycles. Ateachstep, itcal ls SetColorIndex to color the pixel cor respondingto(x, y)black, which is at position 1 inthe palette. The main func tioncal lsthe lissajous func tion, direc ting ittowrite to the stand ard out put, so thiscommand pro duces an animated GIF wit h frames like those inFigure1.1: $gobuild gopl.io/ch1/lissajous $./lissajous >out.gif Exercis e1.5: Change the Lissajous program’scolor palette to gre enonblack,for adde d authenticity.Tocre ate the web color #RRGGBB,use color.RGBA{0xRR,0xGG,0xBB,0xff}, whereeachpair ofhexade cimal digitsrepresentsthe int ensit y of the red,gre en, orbluecom- ponent ofthe pixel. Exercis e1.6: Mo dif y theLissajous program topro duce images in multiplecolor s by adding more values to palette andthendispl aying thembychang ing the thirdargumentof Set- ColorIndex in som e interest ing way. 1.5. Fet ching a URL Fo r many app lic ations,accesstoinfor mat ionfro m theInt ernet isasimp ortantasaccesstothe lo cal file system. Goprovides a collec tion of packages, gro upedunder net,thatmakeiteasy to sendand receive infor mat ionthrough the Int ernet, makelow-le vel networ k connec tion s, andset upser vers, for whichGo’scon cur rency features(introduce d in Chapt er8)are par tic u- larlyuseful. The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 16 CHAPTER 1. TUTORIAL To illustratethe minimum necessary toret rie veinfor mat ionoverHTTP, here’sasimple prog ram called fetch that fetch esthe content ofeachspecified URL andprintsitasuninter- preted text; it’sins pired bythe invaluableutilit y curl.Obv iou sly one wou ldusu allydomore with suchdat a, butthisshows the basic idea. Wewill use thisprogram fre quentlyinthe book. gopl.io/ch1/fetch // Fetch prints the content found at a URL. package main import ( "fmt" "io/ioutil" "net/http" "os" ) func main() { for _, url := range os.Args[1:] { resp, err := http.Get(url) if err != nil { fmt.Fprintf(os.Stderr, "fetch: %v\n", err) os.Exit(1) } b, err := ioutil.ReadAll(resp.Body) resp.Body.Close() if err != nil { fmt.Fprintf(os.Stderr, "fetch: reading %s: %v\n", url, err) os.Exit(1) } fmt.Printf("%s", b) } } Thisprogram introduces functions fro m twopackages, net/http and io/ioutil.The http.Get func tionmakes an HTTP requestand,ifthere isnoerror,retur nsthe resultinthe resp ons e st ruc t resp.The Body fieldof resp cont ainsthe ser ver respons e as a readable st ream. Next, ioutil.ReadAll re ads the ent ire resp ons e;the resultisstore d in b.The Body st reamisclos edtoavoid leak ingres ources, and Printf wr itesthe respons e to the stand ard output. $gobuild gopl.io/ch1/fetch $./fetch http://gopl.io The Go Programming Language ... If the HTTPrequestfai ls, fetch reportsthe fai lureins tead: The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 SECTION 1.6. FETCHING URLS CONCURRENTLY17 $./fetch http://bad.gopl.io fetch: Get http://bad.gopl.io: dial tcp: lookup bad.gopl.io: no such host In eit her erro r case, os.Exit(1) caus esthe pro cesstoexitwit h astatu s co de of 1. Exercis e1.7: Thefunctioncal l io.Copy(dst, src) re ads fro m src andwritesto dst.Use it insteadof ioutil.ReadAll to copythe respons e bodyto os.Stdout withoutrequir inga buffer large enoug h to holdthe ent ire stream. Besuretoche ckthe error resultof io.Copy. Exercis e1.8: Mo dif y fetch to add the prefix http:// to eachargumentURL if itismissing. Yo u mig htwanttouse strings.HasPrefix. Exercis e1.9: Mo dif y fetch to als o pr int the HTTPstatu s co de,found in resp.Status. 1.6. Fet ching URLsConcurrently Oneofthe most int erest ing and nove l aspectsofGoisits sup por t forcon cur rentprogram- ming. Thisisalarge topic, towhichChapt er8 and Chapt er9 are devot ed, sofor now we’ll give youjustataste ofGo’smain conc urrency mechanisms, goroutinesand channel s. Thenext program, fetchall,doesthe samefetch ofaURL’scontentsasthe pre vious example, butitfetch esmanyURLs, allcon cur rently, sothatthe pro cesswill takenolon g erthanthe longest fetch rat her thanthe sum ofall the fetch times. Thisversionof fetchall discards the resp ons esbut rep ortsthe size andelaps edtimefor eachone: gopl.io/ch1/fetchall // Fetchall fetches URLs in parallel and reports their times and sizes. package main import ( "fmt" "io" "io/ioutil" "net/http" "os" "time" ) func main() { start := time.Now() ch := make(chan string) for _, url := range os.Args[1:] { go fetch(url, ch) // start a goroutine } for range os.Args[1:] { fmt.Println(<-ch) // receive from channel ch } fmt.Printf("%.2fs elapsed\n", time.Since(start).Seconds()) } The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 18 CHAPTER 1. TUTORIAL func fetch(url string, ch chan<- string) { start := time.Now() resp, err := http.Get(url) if err != nil { ch <- fmt.Sprint(err) // send to channel ch return } nbytes, err := io.Copy(ioutil.Discard, resp.Body) resp.Body.Close() // don'tleak resources if err != nil { ch <- fmt.Sprintf("while reading %s: %v", url, err) return } secs := time.Since(start).Seconds() ch <- fmt.Sprintf("%.2fs %7d %s", secs, nbytes, url) } Here’s an example: $gobuild gopl.io/ch1/fetchall $./fetchall https://golang.org http://gopl.io https://godoc.org 0.14s 6852 https://godoc.org 0.16s 7261 https://golang.org 0.48s 2475 http://gopl.io 0.48s elapsed A goro utine is a con cur rentfunctionexe cut ion.Ach ann el is a communic ationmechanism that allows one goroutine topassvalues ofaspecified typ e to another goroutine.The function main runs inagoroutine and the go st atement cre atesaddition algoroutines. The main func tioncre atesachannel ofstr ingsusing make.For eachcommand-lineargument, the go st atement inthe firs t range loopstartsanew goroutine thatcal ls fetch asy nchro nou sly to fetch the URL using http.Get.The io.Copy func tionreads the bodyofthe respons e and discards itbywriting tothe ioutil.Discard output stream. Copy returnsthe bytecount, along wit h anyerror thatocc urre d.Aseachresultarrives, fetch send s asummar ylineonthe ch annel ch.The secon d range loopin main re ceivesand printsthose lines. Wh enone goroutine att emp tsasendorreceive onachannel,itblo cks until another goroutine attemp tsthe cor respondingreceive orsendoperat ion, at whichpoint the value istransfer red andbot h goro utinespro ceed.Inthisexample, each fetch send s avalue (ch <- expre ssi on)on thechannel ch,and main re ceivesall ofthem(<-ch). Hav ing main do allthe print ing ens ures that out put fro m each goroutine ispro cessedasaunit, wit h no dangerofint erleaving iftwo goro utines finish atthe sametime. Exercis e1.10: Findaweb sit e that pro duces a large amountofdat a. Invest igatecachingby running fetchall twice in successiontosee whether the rep orted time changesmuch. Do youget the samecontent eachtime? Modif y fetchall to print its out put toafile soitcan be examined. The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 SECTION 1.7. AWEB SERVER 19 Exercis e1.11: Tr y fetchall with lon g erargumentlists, suchassamples fro m thetop million we b sitesavai lable at alexa.com.How doesthe program beh ave ifawe b site justdoesn’t resp ond?(Section8.9 descr ibesmechanismsfor coping in suchcas es.) 1.7. A WebServer Go’slibrar ies makesiteasy towrite a web ser ver thatrespond s to clientrequests like those made by fetch.Inthissec tion,we’ll showaminimal ser ver thatretur nsthe pat hcomp onent of the URL usedtoaccessthe ser ver.Thatis, if the requestisfor http://local- host:8000/hello,the respons e wi l l be URL.Path = "/hello". gopl.io/ch1/server1 // Server1 is a minimal "echo" server. package main import ( "fmt" "log" "net/http" ) func main() { http.HandleFunc("/", handler) // each request calls handler log.Fatal(http.ListenAndServe("localhost:8000", nil)) } // handler echoes the Path component of the request URL r. func handler(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "URL.Path = %q\n", r.URL.Path) } Theprogram isonlyahandf uloflines long because librar y func tions domostofthe wor k. The main func tionconne cts a handler functiontoincomingURLs thatbeg in with /,whichis al l URLs, andstartsaser ver listeningfor incomingrequests onpor t 8000. A re questisrep- resent edasastr uct oftyp e http.Request,whichcontainsanumberofrel ate d fields,one of whichisthe URL ofthe incomingrequest. Whenarequestarrives, itisgiven tothe handler func tion, whichext racts the pat h comp onent (/hello)fro m therequestURL andsends it back asthe respons e,using fmt.Fprintf.Web ser verswill beexplained indet ailin Section7.7. Let’sstart the ser ver in the backg round.OnMac OS X orLinux, add an ampers and (&)tothe command; onMicros oft Windows, you will need torun the command wit houtthe amp ers and in a sep aratecommand window. $gorun src/gopl.io/ch1/server1/main.go & We can thenmakeclientrequests fro m thecommand line: The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 20 CHAPTER 1. TUTORIAL $gobuild gopl.io/ch1/fetch $./fetch http://localhost:8000 URL.Path = "/" $./fetch http://localhost:8000/help URL.Path = "/help" Alternat ive ly, wecan accessthe ser ver fro m aweb brows er, as shown inFigure1.2. Figure 1.2. Arespons e from the ech o server. It’seasy toadd featurestothe ser ver.One usefuladdition isaspecificURL thatretur nsa st atu s of som e sort.For example, thisversiondoesthe sameech o butals o counts the number of requests; a requesttothe URL /count returnsthe count sofar,exc luding /count re quests themselves: gopl.io/ch1/server2 // Server2 is a minimal "echo" and counter server. package main import ( "fmt" "log" "net/http" "sync" ) var mu sync.Mutex var count int func main() { http.HandleFunc("/", handler) http.HandleFunc("/count", counter) log.Fatal(http.ListenAndServe("localhost:8000", nil)) } // handler echoes the Path component of the requested URL. func handler(w http.ResponseWriter, r *http.Request) { mu.Lock() count++ mu.Unlock() fmt.Fprintf(w, "URL.Path = %q\n", r.URL.Path) } The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 SECTION 1.7. AWEB SERVER 21 // counter echoes the number of calls so far. func counter(w http.ResponseWriter, r *http.Request) { mu.Lock() fmt.Fprintf(w, "Count %d\n", count) mu.Unlock() } Theser ver has two handlers, andthe requestURL deter mines whichone iscal le d: arequest for /count invo kes counter andall othersinv oke handler.Ahand ler pattern that ends wit h aslash match esany URL thathas the pattern asaprefix. Behindthe scenes, the ser ver runs thehandler for eachincomingrequestinasep arategoroutine sothatitcan ser vemultiple re quests simultane ously.How ever, iftwo con cur rentrequests try toupdate count at the same time,itmig htnot beincrement edcon sistent ly; the program wou ldhaveaser ious bug cal le da ra c e condit ion (§9.1). Toavoid thispro blem, wemustens ure that at mostone goroutine accessesthe var iable at a time, whichisthe pur pos e of the mu.Lock() and mu.Unlock() calls that bracketeachaccessof count.We’ll lookmoreclos ely atcon cur rency wit h sh are d var i- ables in Chapt er9. As a richerexample, the handler functioncan rep ort onthe headersand for m data that it re ceives, mak ingthe ser ver usefulfor ins pec ting and debug gingrequests: gopl.io/ch1/server3 // handler echoes the HTTP request. func handler(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "%s %s %s\n", r.Method, r.URL, r.Proto) for k, v := range r.Header { fmt.Fprintf(w, "Header[%q] = %q\n", k, v) } fmt.Fprintf(w, "Host = %q\n", r.Host) fmt.Fprintf(w, "RemoteAddr = %q\n", r.RemoteAddr) if err := r.ParseForm(); err != nil { log.Print(err) } for k, v := range r.Form { fmt.Fprintf(w, "Form[%q] = %q\n", k, v) } } Thisusesthe fields ofthe http.Request st ruc t to pro duce out put likethis: GET /?q=query HTTP/1.1 Header["Accept-Encoding"] = ["gzip, deflate, sdch"] Header["Accept-Language"] = ["en-US,en;q=0.8"] Header["Connection"] = ["keep-alive"] Header["Accept"] = ["text/html,application/xhtml+xml,application/xml;..."] Header["User-Agent"] = ["Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5)..."] Host = "localhost:8000" RemoteAddr = "127.0.0.1:59911" Form["q"] = ["query"] The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 22 CHAPTER 1. TUTORIAL No tice how the cal l to ParseForm is neste d within an if st atement.Goallowsasimplestate- ment suchasalocal variabledeclarat iontopre cedethe if condit ion,whichispar tic ularly us efulfor error handling as in thisexample. Wecou ldhavewritt enitas err := r.ParseForm() if err != nil { log.Print(err) } butcom biningthe statementsisshorter andreduces the scope ofthe var iable err,whichis go o d prac tice.We’ll define scope inSec tion 2.7. In these programs, we’ve seenthree ver y dif ferenttyp es us edasout put streams.The fetch prog ram copied HTTPrespons e data to os.Stdout,afile,asdid the lissajous prog ram. The fetchall prog ram thre w therespons e away (whi le counting its lengt h) by copying itto thetrivialsin k ioutil.Discard.And the web ser ver abov e us ed fmt.Fprintf to write to an http.ResponseWriter repres enting the web brows er. Although these three typ es dif fer in the det ails ofwhatthe y do,the y al l satisf y acommon interface,allow ing any ofthemtobeusedwhere ver an out put streamisneeded.Thatint er- face,cal le d io.Writer,isdis cussed in Sec tion 7.1. Go’sint erface mechanism isthe topic ofChapt er7,but togiveanide a of whatit’scap able of, let’ssee how easy itistocom bine the web ser ver wit h the lissajous func tionsothatani- mate d GIFs arewritt ennot tothe stand ard out put,but tothe HTTPclient. Justadd these lines tothe web ser ver : handler := func(w http.ResponseWriter, r *http.Request) { lissajous(w) } http.HandleFunc("/", handler) or equivalently: http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { lissajous(w) }) Thesecon d argumenttothe HandleFunc func tioncal limmediate lyabove isafunc tionlit era l, that is, an anonymou s func tiondefine d at its point ofuse.Wewill explain itfur therin Section5.6. Once you’ve made thischange , visit http://localhost:8000 in yourbrows er.Eachtimeyou lo ad thepage, you’ll see a new animat ionlikethe one inFigure1.3. Exercis e1.12: Mo dif y theLissajous ser ver toreadparameter values fro m theURL. For exam- ple, you mig htarrange itsothataURL like http://localhost:8000/?cycles=20 sets the numb erofcyc les to 20 ins teadofthe defau lt5.Use the strconv.Atoi func tiontoconvert the st ringparameter into anint eger. You can see its document ation wit h go doc strconv.Atoi. The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 SECTION 1.8. LOOSE ENDS 23 Figure 1.3. Animated Lissajous figures in a brows er. 1.8. Loose Ends Thereisalot moretoGothanwe’ve cov ere d in thisquickint roduc tion. Hereare som e topics we’ve barelytouch eduponoromitt edent ire ly, wit h ju stenoug h discussionthatthe y wi l l be fami liar whenthe y make brief appearances beforethe full treatment. Contro l flow : We cov ere d thetwo fundament alcontrol-flow statements, if and for,but not the switch st atement,whichisamulti-way branch.Here’sasmall example: switch coinflip() { case "heads": heads++ case "tails": tails++ default: fmt.Println("landed on edge!") } Theresultofcal ling coinflip is compare d to the value ofeachcas e.Cas esareevaluate d from toptobot tom,sothe firs t matchingone isexe cut ed. The opt ion aldefau ltcas e match esifnon e of the other cas es do es; it may beplace danywhere . Casesdonot fal l thro ugh fro m on e to the next as in C-like langu ages (thoug h thereisararelyused fallthrough st atement thatover- rides thisbeh avior). A switch do es notneed anoperand; itcan justlistthe cas es, each ofwhichisaboole an expression: The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 24 CHAPTER 1. TUTORIAL func Signum(x int) int { switch { case x > 0: return +1 default: return 0 case x < 0: return -1 } } Thisfor m is cal le da taglessswitch;it’sequivalentto switch true. Like the for and if st atements, a switch mayinclude an opt ion alsimplestatement—ashort var iable decl arat ion, an incrementorassig nmentstatement,orafunctioncal l—that can be us edtoset a value beforeitisteste d. The break and continue st atementsmodif y theflow ofcontrol . A break caus escontrol to resume atthe next statement after the inner most for, switch,or select st atement (which we’ll see later), andaswesaw in Sec tion 1.3, a continue caus esthe inner most for lo opto st art its next iterat ion. Statementsmay belab ele d so that break and continue canrefer to them, for ins tance tobre akout of several neste d lo ops at onceortostart the next iterat ionof theout ermostloop. There isevenagoto st atement,thoug h it’sint ended for machine-gener- ated code, not regu lar use byprogrammers. Na med types: A type de clarat ionmakes itpossibletogiveaname toanexist ing typ e.Since st ruc t typesare often long , they are nearlyalways named.Afami liar exampleisthe definition of a Point type for a 2-D graphics system: type Point struct { X, Y int } var p Point Type declarat ions and named typ esarecov ere d in Chapt er2. Po int ers: Go provides point ers,thatis, values thatcontain the addressofavar iable.Insom e languages, not ably C,point ers are relative lyuncon strained.Inother langu ages, point ers are disguisedas ‘‘references,’’ andthere’snot muchthatcan bedon e with them exceptpassthem around.Gotakes a position som ewhereinthe midd le.Point ers are explicitlyvisible.The & op erator yieldsthe addressofavar iable,and the * op erator ret rie ves the var iable thatthe pointerrefersto, but there isnopoint erarithmetic. We’ll explain point ers inSec tion 2.3.2. Me thods and inte rfa ces: Amet hod isafunctionass oci ated wit h anamed typ e; Go isunu sual in thatmet hodsmay beatt ach edtoalmostany named typ e.Met hodsare cov ere d in Chap- ter6.Int erfaces areabstrac t typesthatlet ustre atdif ferentcon crete typ es in the sameway basedonwhatmet hodsthe y have , nothow the y arerepresent edorimp lemente d. Interfaces arethe subjec t of Chapt er7. The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 SECTION 1.8. LOOSE ENDS 25 Pa ckage s: Go com eswit h an extensive stand ard librar y of usefulpackages, andthe Gocom- munity has create d andshare d many more. Programmingisoften moreabout usingexist ing packages thanabout writing originalcodeofone’sown.Throughoutthe book, wewill point outacoupleofdozen ofthe most imp ortantstand ard packages, but there are manymorewe don’thavespace tomention,and wecannot provide anyt hingremot ely likeacompleterefer- ence for any package. Before you emb ark onany new program, it’sagood ide a to see ifpackages already exist that mig hthelpyou get yourjob don e more easi ly. You can find anindex ofthe stand ard librar y packages at https://golang.org/pkg andthe packages cont ribut edbythe community at https://godoc.org.The go doc to olmakes these documents easi lyaccessiblefro m the commandline: $godoc http.ListenAndServe package http // import "net/http" func ListenAndServe(addr string, handler Handler) error ListenAndServe listens on the TCP network address addr and then calls Serve with handler to handle requests on incoming connections. ... Comm ents: We havealready mention eddocumentation commentsatthe beg inningofa prog ram or package. It’sals o go o d st yle towrite a comment beforethe declarat ionofeach func tiontospecif y itsbeh avior.These convent ion s areimp ortant, because the y areusedby to ols like go doc and godoc to locateand displ aydocumentation (§10.7.4). Fo r comments thatspanmultiplelines orapp ear wit hin an expressionorstatement,there is also the /* ... */ notation fami liar fro m ot her langu ages. Suchcommentsare som etimes us edatthe beg inningofafile for a large blo ckofexplanatory text toavoid a // on every line. Wi thin a comment, // and /* have nospeci al me aning, socomments do not nest. The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 This page intentionally left blank From the Library of YIGUANG HU ptg16105617 2 ProgramStructure In Go, asinany other programminglangu age, one bui ldslarge programsfro m asmall set of basic cons tructs. Var iables store values. Simpleexpressions are com bine d into largerones with operat ions likeaddition and subtrac tion. Basic typ es arecol lec ted int o ag gregates like ar rays andstr ucts. Expressions are usedinstatementswhose exe cut ion order isdeter mined by control-flow statementslike if and for.Statementsare gro upedint o func tions for is olation and reuse.Functions are gat hered int o source files andpackages. We saw examples ofmostofthese inthe pre vious chapt er. Inthischapt er, we’ll goint o more det ailabout the basic str uctural elements ofaGoprogram. Theexampleprogramsare int en- tion allysimple, sowecan focus onthe langu agewit houtgetting sidet racke d by complic ated algor it hms ordat a st ruc tures. 2.1. Names Thenames ofGofunctions,var iables, cons tants, typ es, st atement lab els,and packages fol low a simplerule: a namebeg inswit h aletter(that is, anyt hingthatUnico de de emsa letter) oran underscoreand may haveany numberofaddition alletters,dig its, andunderscores. Cas e mat- ters: heapSort and Heapsort aredif ferentnames. Go has 25 ke yword s li ke if and switch that may beusedonlywhere the syntaxper mits; the y can’tbeused as names. break default func interface select case defer go map struct chan else goto package switch const fallthrough if range type continue for import return var 27 The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 28 CHAPTER 2. PROGRAM STRUCTURE In addition,there are about three dozen pred eclare d nameslike int and true forbui lt-in con- st ants, typ es,andfunctions: Cons tants: true false iota nil Types: int int8 int16 int32 int64 uint uint8 uint16 uint32 uint64 uintptr float32 float64 complex128 complex64 bool byte rune string error Func tions: make len cap new append copy close delete complex real imag panic recover Thes e namesare not res erve d,soyou may use themindeclarat ions.We’ll see a handf ulof pl aces where rede claring one ofthemmakes sense,but bewareofthe pot ent ial for confusion. If anent ity isdeclare d within a function, itis local to thatfunction. Ifdeclare d outside ofa func tion, how ever, itisvisible in all files ofthe packagetowhichitbelon gs. Thecas e of the firs t letterofanamedeter mines its visibilit y acrosspackagebound aries. Ifthe namebeg ins with anupp er-case letter, itis expor ted,whichmeans thatitisvisible andaccessibleoutside of itsown packageand may berefer red tobyother par ts of the program, as wit h Printf in the fmt package. Packagenames thems elves arealways in lowercas e. Thereisnolimitonnamelengt h, butconvent ion and sty leinGoprogramsleantowardshort names, especi ally for local variables wit h smal l scop es; you are muchmorelikelytosee var i- ables named i than theLoopIndex.General ly, the largerthe scope ofaname, the lon g erand more meaningf ul it shouldbe. St ylist ically, Goprogrammersuse ‘‘camel cas e’’ when for mingnames bycom biningwords;that is,int erior capit alletters are preferred overint erior underscores. Thus the stand ard librar ies have functions wit h nameslike QuoteRuneToASCII and parseRequestLine butnever quote_rune_to_ASCII or parse_request_line.The letters ofacronymsand initialismslike ASCII andHTMLare always rendered inthe samecas e,soafunctionmig htbecal le d html- Escape, HTMLEscape,or escapeHTML,but not escapeHtml. 2.2. Declarations A decl arati on namesaprogram entity and specifies som e or all ofits pro per ties. Thereare four maj orkinds ofdeclarat ions: var, const, type,and func.We’ll tal k ab out var iables and types in thischapt er, con stants in Chapt er 3, and functions inChapt er5. AGoprogram isstore d in one ormorefiles whose names endin .go.Each file beg inswit h a package de clarat ionthatsays whatpackagethe file ispar t of . The package de clarat ionis fo llowe d by any import de clarat ions,and thenasequence of pack age-level de clarat ions of types, variables, cons tants, andfunctions,inany order.For example, thisprogram decl aresa cons tant, a function, andacoupleofvar iables: The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 SECTION 2.2. DECLARATIONS 29 gopl.io/ch2/boiling // Boiling prints the boiling point of water. package main import "fmt" const boilingF = 212.0 func main() { var f = boilingF var c = (f - 32) * 5 / 9 fmt.Printf("boiling point = %g°F or %g°C\n", f, c) // Output: // boiling point = 212°F or 100°C } Thecon stant boilingF is a package-le vel declarat ion(as is main), where asthe var iables f and c arelocal tothe function main.The nameofeachpackage-le vel ent ity isvisible not only thro ughoutthe sourcefile thatcontainsits decl arat ion, but throughoutall the files ofthe pack- age. Bycontrast, localdeclarat ions are visible onlywit hin the functioninwhichthe y are de clare d andperhaps onlywit hin a smal l part ofit. Afunctiondeclarat ionhas a name, a listofparameters(thevar iables whose values are prov ide d by the function’scal lers), an opt ion allistofresults, andthe functionbody, which cont ainsthe statementsthatdefine whatthe functiondoes. Theresultlistisomitt edifthe func tiondoesnot retur n anyt hing. Exe cut ion of the functionbeg inswit h thefirs t st atement andcontinues until itencount ers a retur n st atement orreach esthe end ofafunctionthathas no results. Control and any results arethenretur ned tothe cal ler. We’ve seenafair numberoffunctions already and there are lotsmoretocom e,includingan extensive dis cussioninChapt er5,sothisisonlyasketch.The function fToC belowenc apsu- latesthe temperatureconversionlog ic so thatitisdefine d on lyoncebut may beusedfro m mu ltipleplaces. Here main callsittwice,usingthe values oftwo dif ferentlocal cons tants: gopl.io/ch2/ftoc // Ftoc prints two Fahrenheit-to-Celsius conversions. package main import "fmt" func main() { const freezingF, boilingF = 32.0, 212.0 fmt.Printf("%g°F = %g°C\n", freezingF, fToC(freezingF)) // "32°F = 0°C" fmt.Printf("%g°F = %g°C\n", boilingF, fToC(boilingF)) // "212°F = 100°C" } func fToC(f float64) float64 { return (f - 32) * 5 / 9 } The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 30 CHAPTER 2. PROGRAM STRUCTURE 2.3. Variables A var de clarat ioncre atesavar iable ofapar tic ulartyp e,att ach esanametoit, andsets its ini- tial value.Eachdeclarat ionhas the general for m var name type = expression Either the typ e or the = expression part may beomitt ed, but not bot h.Ifthe typ e is omitt ed, it isdeter mined bythe initializer expression. Ifthe expressionisomitt ed, the initial value is the zero value forthe typ e,whichis 0 fornumbers, false forboole ans, "" forstr ings, and nil forint erfaces andreference typ es(slice,point er, map,channel,function). Thezerovalue ofan ag gregatetyp e li ke an array orastr uct has the zerovalue ofall ofits elements or fields. Thezero-value mechanism ensuresthatavar iable always holds a wel l-define d value ofits typ e; in Gothere isnosuchthingasanuninitialize d var iable.Thissimplifies code andoften ensuressensiblebeh avior of bound ary con dit ion s withoutext ra work.For example, var s string fmt.Println(s) // "" pr intsanemp tystr ing , rat her thancausingsom e kind oferror or unp redic table beh avior.Go prog rammersoften gotosom e ef for t to makethe zerovalue ofamorecomplic ated typ e me aningf ul,sothatvar iables beg inlife in a usefulstate. It ispossibletodeclare and opt ion allyinitialize a set ofvar iables in a singledeclarat ion, wit h a matchinglistofexpressions.Omitt ing the typ e al lows decl arat ionofmultiplevar iables ofdif- ferent typ es: var i, j, k int // int, int, int var b, f, s = true, 2.3, "four" // bool, float64, string Init ializersmay belit eral values orarbit rar y expressions.Package-le vel var iables areinitial- ize d before main begins (§2.6.2), andlocal variables areinitialize d as their decl arat ions are encountere d during functionexe cut ion. Aset ofvar iables can also beinitialize d by cal lingafunctionthatretur nsmultiplevalues: var f, err = os.Open(name) // os.Open returns a file and an error 2.3.1. Short Variable Declarations Wi thin a function, an alternatefor m called a sh ort var iab ledeclarati on maybeusedtodeclare andinitialize localvar iables. Ittakes the for m name := expression,and the typ e of name is deter mined bythe typ e of expression.Hereare three ofthe manyshort var iable decl arat ions in the lissajous func tion(§1.4): anim := gif.GIF{LoopCount: nframes} freq := rand.Float64() * 3.0 t:=0.0 The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 SECTION 2.3. VARIABLES 31 Becaus e of their bre vit y and flexibi lit y,short var iable decl arat ions are usedtodeclare and ini- tialize the maj ority oflocal variables. A var de clarat iontends toberes erve d forlocal variables that need anexplicittyp e that differs fro m that ofthe initializer expression, orfor whenthe var iable will beassig ned a value later andits initial value isunimportant. i:=100 // an int var boiling float64 = 100 // a float64 var names []string var err error var p Point As wit h var de clarat ions,multiplevar iables may bedeclare d andinitialize d in the sameshort var iable decl arat ion, i, j := 0, 1 butdeclarat ions wit h mu ltipleinitializer expressions shouldbeusedonlywhenthe yhelpread- abilit y,such as for short and natural gro upingslikethe initializat ionpar t of a for lo op. Ke epinmindthat := is a declarat ion, where as = is anassig nment. A mu lti-var iable decl ara- tion shouldnot beconfusedwit h a tupl e assig nment (§2.4.1), in whicheachvar iable onthe lef t-handside isassig ned the cor respondingvalue fro m therig ht-handside: i, j = j, i // swap values of i and j Like ordinar y var de clarat ions,short var iable decl arat ions may beusedfor cal lstofunctions li ke os.Open that retur n twoormorevalues: f, err := os.Open(name) if err != nil { return err } // ...use f... f.Close() Onesubtlebut imp ortantpoint:ashort var iable decl arat iondoesnot necessarily decl are al l the var iables onits left-handside.Ifsom e of themwerealready declare d in the same lexic al block (§2.7), thenthe short var iable decl arat ionactslikean assig nment to those var iables. In the codebelow,the firs t st atement declaresbot h in and err.The secon d de clares out but on lyassig nsavalue tothe exist ing err var iable. in, err := os.Open(infile) // ... out, err := os.Create(outfile) Ashort var iable decl arat ionmustdeclare atleast one newvar iable,how ever, sothiscodewill notcompi le: f, err := os.Open(infile) // ... f, err := os.Create(outfile) // compile error: no new variables The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 32 CHAPTER 2. PROGRAM STRUCTURE The fixistouse anordinar yassig nmentfor the secon d st atement. Ashort var iable decl arat ionactslikeanassig nmentonlytovar iables thatwerealready de clare d in the samelexic al block; decl arat ions inanout erblo ckare ignored.We’ll see exam- ples ofthis at the end ofthe chapt er. 2.3.2. Pointers A variab le is a pie ce of storagecontainingavalue.Var iables create d by declarat ions are iden- tified byaname, suchas x,but manyvar iables areidentified onlybyexpressions like x[i] or x.f.All these expressions readthe value ofavar iable,exceptwhenthe y appear onthe lef t- hand side of an assig nment, in whichcas e anew value isassig ned tothe var iable. A pointer value isthe ad dre ss of a var iable.Apointeristhu s thelocat ionatwhichavalue is stored.Not every value has an address, but every var iable does. Wit h apoint er, wecan read or update the value ofavar iable in direc tly,wit houtusingorevenknowing the nameofthe var iable, if indeed ithas a name. If a var iable isdeclare d var x int,the expression &x (‘‘addressof x’’)yieldsapoint ertoan integervar iable,thatis, a value oftyp e *int,whichispro nounced ‘‘pointertoint.’’ If this value iscal le d p,wesay ‘‘p points to x,’’ or equivalently ‘‘p cont ainsthe addressof x.’’ Thevar i- able towhich p points iswritt en *p.The expression *p yields the value ofthatvar iable,an int,but since *p denot esavar iable,itmay also app ear onthe lef t-handside ofanassig nment, in whichcas e theassig nmentupdates the var iable. x:=1 p:=&x//p,oftype *int, points to x fmt.Println(*p) // "1" *p = 2 // equivalent to x = 2 fmt.Println(x) // "2" Each component ofavar iable ofaggregatetyp e—afieldofastr uct oranelementofanarray— is als o avar iable andthu s has an addresstoo. Variables aresom etimesdes crib edas ad dre ssabl e values. Expressions thatdenot e var iables are theonlyexpressions towhichthe ad dre ss-of op erator & maybeapp lie d. Thezerovalue for a point erofany typ e is nil.The test p!=nil is trueif p points toavar i- able.Point ers are comparable; two point ers are equ alifand onlyifthe y pointtothe same var iable orbot h arenil. var x, y int fmt.Println(&x == &x, &x == &y, &x == nil) // "true false false" It isper fec tly safefor a functiontoretur n theaddressofalocal variable. For ins tance,inthe co de below, the local variable v create d by thispar tic ularcal l to f wi l l remain in existence even af ter the cal l hasretur ned,and the point er p wi l l st i l l refertoit: The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 SECTION 2.3. VARIABLES 33 var p = f() func f() *int { v:=1 return &v } Each cal l of f returnsadistinc t value: fmt.Println(f() == f()) // "false" Becaus e apoint ercontainsthe addressofavar iable,passingapoint erargumenttoafunction makesitpossiblefor the functiontoupdatethe var iable thatwas indirec tly passed. For exam- ple, thisfunctionincrementsthe var iable thatits argumentpointstoand retur nsthe new value ofthe var iable soitmay beused in an expression: func incr(p *int) int { *p++ // increments what p points to; does not change p return *p } v:=1 incr(&v) // side effect: v is now 2 fmt.Println(incr(&v)) // "3" (and v is 3) Each timewetakethe addressofavar iable orcopyapoint er, wecre ate new aliases or ways to identify the samevar iable.For example, *p is anali as for v.Point erali asingisusefulbecause it allowsustoaccessavar iable wit houtusingits name, but thisisadou ble-e dged sword:to find all the statementsthataccessavar iable,wehavetoknowall its alias es. It’snot justpoint- ersthatcre ate ali ases; aliasingals o occurs whenwecopyvalues ofother reference typ es li ke slices, maps, andchannel s,and evenstr ucts, arrays, andint erfaces thatcontain these typ es. Po int ers are key tothe flag package, whichusesaprogram’scommand-linearguments toset thevalues ofcer tain variables dist ribut edthroughoutthe program. Toillustrate, thisvar iat ion on the earlier echo commandtakes two opt ion al flags: -n caus es echo to omitthe trai ling ne wlinethatwou ldnor mal lybeprint ed, and -s sep caus esittosep aratethe out put argu- mentsbythe contentsofthe str ing sep insteadofthe defau ltsinglespace.Since thisisour four thversion, the packageiscal le d gopl.io/ch2/echo4. gopl.io/ch2/echo4 // Echo4 prints its command-line arguments. package main import ( "flag" "fmt" "strings" ) var n = flag.Bool("n", false, "omit trailing newline") var sep = flag.String("s", " ", "separator") The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 34 CHAPTER 2. PROGRAM STRUCTURE func main() { flag.Parse() fmt.Print(strings.Join(flag.Args(), *sep)) if !*n { fmt.Println() } } Thefunction flag.Bool createsanew flag variableoftyp e bool.Ittakes three arguments: the name ofthe flag ("n"), the var iable’sdefau ltvalue (false), andamessage thatwill beprint ed if the userprovides an invalid argument, an invalid flag , or -h or -help.Simi larly, flag.String takesaname, a defau ltvalue,and a mess age , andcre atesastring var iable.The var iables sep and n arepoint ers to the flag variables, whichmustbeaccessedindirec tly as *sep and *n. Wh enthe program isrun, itmustcal l flag.Parse before the flags areused, to updatethe flag var iables fro m their default values. Thenon-flag arguments areavai lable fro m flag.Args() as a slice ofstr ings. If flag.Parse encounters anerror,itprintsausage message and cal ls os.Exit(2) to terminatethe program. Let’srun som e test cas es on echo: $gobuild gopl.io/ch2/echo4 $./echo4 a bc def abcdef $./echo4 -s / a bc def a/bc/def $./echo4 -n a bc def abcdef$ $./echo4 -help Usage of ./echo4: -n omit trailing newline -s string separator (default " ") 2.3.3. The new Function Anot her way tocre ate a var iable istouse the bui lt-in function new.The expression new(T) createsan unname d variab le of typ e T,initializes ittothe zerovalue of T,and retur nsits address, whichisavalue oftyp e *T. p:=new(int) // p, of type *int, points to an unnamed int variable fmt.Println(*p) // "0" *p = 2 // sets the unnamed int to 2 fmt.Println(*p) // "2" Avar iable create d with new is nodif ferentfro m an ordinar y lo cal variablewhose addressis taken, exceptthatthere’snoneed toinv ent (anddeclare)adummyname, and wecan use new(T) in an expression. Thus new is onlyasyntactic conv enience,not a fundament alnot ion: The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 SECTION 2.3. VARIABLES 35 thetwo newInt func tions below haveidenticalbeh avior s. func newInt() *int { func newInt() *int { return new(int) var dummy int }return &dummy } Each cal l to new returnsadistinc t var iable wit h aunique address: p:=new(int) q:=new(int) fmt.Println(p == q) // "false" Thereisone exception tothisrule: two var iables whose typ e carries noinfor mat ionand is thereforeofsize zero, suchas struct{} or [0]int,may,dep endingonthe imp lementation, have the sameaddress. The new func tionisrel ative lyrarelyusedbecause the most commonunnamed var iables areof st ruc t types, for whichthe str uct lit eral synt ax(§4.4.1) ismore flexible. Since new is a pre declare d func tion, not a key word, it’spossibletoredefine the namefor somethingels e within a function, for example: func delta(old, new int) int { return new - old } Of course,wit hin delta,the bui lt-in new func tionisunavai lable. 2.3.4. Lifetime ofVariables The li fetim e of a var iable isthe int erval oftimedur ingwhichitexistsasthe program exec utes. Thelifet imeofapackage-le vel var iable isthe ent ire exe cut ion of the program. Bycontrast, lo cal variables havedynamic lifet imes: a new ins tance iscre ate d each timethe declarat ion st atement isexe cut ed, and the var iable livesonunt i l it becom es unre ach abl e,atwhichpoint its storagemay berec ycled.Functionparametersand results arelocal variables too;the y arecre- ated eachtimetheir enclosingfunctioniscal le d. Fo r example, inthisexcer ptfro m theLissajous program ofSec tion 1.4, for t := 0.0; t < cycles*2*math.Pi; t += res { x:=math.Sin(t) y:=math.Sin(t*freq + phase) img.SetColorIndex(size+int(x*size+0.5), size+int(y*size+0.5), blackIndex) } thevar iable t is cre ate d each timethe for lo opbeg ins, andnew var iables x and y arecre ate d on eachiterat ionofthe loop. Ho w do es thegarb agecol lec tor knowthatavar iable’sstoragecan bereclaimed?The full story is muchmoredet aile d than weneed here, but the basic ideaisthatevery package-le vel var i- able,and every local variableofeachcur rentlyactivefunction, can pot ent ial lybethe start or The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 36 CHAPTER 2. PROGRAM STRUCTURE ro otofapat h to the var iable in question,fol low ing point ers and other kinds ofreferences that ultimate lyleadtothe var iable.Ifnosuchpat hexists, the var iable has becom e unreach able, so it can nolon g eraffec t therestofthe computation. Becaus e thelifet imeofavar iable isdeter mined onlybywhether ornot itisreach able, a local var iable may out liveasingleiterat ionofthe enclosingloop. Itmay cont inuetoexist evenafter itsenclosingfunctionhas retur ned. Acompi ler may cho ose toallocatelocal variables onthe heap oronthe stack but,perhaps sur- pr isingly, thischoice isnot deter mined bywhether var or new was usedtodeclare the var iable. var global *int func f() { func g() { var x int y:=new(int) x=1 *y = 1 global = &x } } Here , x mu stbeheap-al locate d becaus e it isstill reach ablefro m thevar iable global af ter f hasretur ned,despit e beingdeclare d as a localvar iable; wesay x es cap esfro m f.Convers ely, when g returns, the var iable *y becomesunreach ableand can berec ycled.Since *y do es not es cap e from g,it’ssafefor the compi ler toallocate *y on the stack,eventhoug h it was allo- cate d with new.Inany cas e,the notion of escapingisnot som ethingthatyou need towor ry ab out inorder towrite cor rec t co de,thoug h it’sgood tokeepinminddur ingper for mance opt imizat ion, since eachvar iable thatescap es re quires an extra memor y al location. Garb agecol lec tion isatremendou s helpinwriting cor rec t prog rams, but it doesnot relie ve youofthe burden ofthin kingabout memor y.You don’tneed toexplicitlyallocateand fre e memory,but towrite efficientprogramsyou still need tobeawareofthe lifet imeofvar iables. Fo r example, keeping unnecessary point ers to short-live d objec tswit hin long-live d objec ts, especi ally globalvar iables, will pre ventthe garb agecol lec tor fro m re claimingthe short-live d objec ts. 2.4. Assignments Thevalue heldbyavar iable isupdated byanassig nmentstatement,whichinits simplestfor m hasavar iable onthe lef t of the = sig nand an expressiononthe rig ht. x=1 // named variable *p = true // indirect variable person.name = "bob" // struct field count[x] = count[x] * scale // array or slice or map element Each ofthe arithmeticand bit w ise binar y op erator s hasacor responding assig nment operator al lowing , forexample, the laststatement toberewritt enas count[x] *= scale The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 SECTION 2.4. ASSIGNMENTS37 whichsaves usfro m having torep eat (andre-e valuate)the expressionfor the var iable. Numericvar iables can also beincrement edand decrement edby ++ and -- st atements: v:=1 v++ // same as v = v + 1; v becomes 2 v-- // same as v = v - 1; v becomes 1 again 2.4.1. Tuple Assignment Anot her for m of assig nment, known as tupl e assig nment,allowsseveral variables tobe assig ned atonce. All ofthe rig ht-handside expressions are evaluate d before any ofthe var i- ables areupdated,mak ingthisfor m most usefulwhensom e of the var iables appear onbot h sides ofthe assig nment, as happens,for example, whenswapping the values oftwo var iables: x, y = y, x a[i], a[j] = a[j], a[i] or whencomputing the gre atest commondiv isor(GCD) oftwo int egers: func gcd(x, y int) int { for y != 0 { x, y = y, x%y } return x } or whencomputing the n-t hFibonacci numberiterat ive ly: func fib(n int) int { x, y := 0, 1 for i := 0; i < n; i++ { x, y = y, x+y } return x } Tu ple assig nmentcan also makeasequence oftrivialassig nments morecompact, i, j, k = 2, 3, 5 though asamatterofsty le, avoid the tup lefor m if the expressions are complex; a sequence of separatestatementsiseasier toread. Certain expressions,suchasacal l to a functionwit h mu ltipleresults, pro duce several values. Wh ensuchacal l is used inanassig nmentstatement,the lef t-handside musthaveasmany var iables as the functionhas results. f, err = os.Open("foo.txt") // function call returns two values Of ten, functions use these addition alresults toindic atesom e kind oferror,eit her byretur ning an error as in the cal l to os.Open,orabool,usu allycal le d ok.Aswe’ll see inlater chapt ers, The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 38 CHAPTER 2. PROGRAM STRUCTURE thereare three operator s that som etimesbeh ave thisway too.Ifamap lookup (§4.3), typ e assertion(§7.10), orchannel receive (§8.4.2) appearsinanassig nmentinwhichtwo results are exp ected,eachpro duces an addition alboole an resu lt: v, ok = m[key] // map lookup v, ok = x.(T) // type assertion v, ok = <-ch // channel receive As wit h var iable decl arat ions,wecan assig nunwante d values tothe blank identifier : _, err = io.Copy(dst, src) // discard byte count _, ok = x.(T) // check type but discard result 2.4.2. Assignability As sig nmentstatementsare anexplicitfor m of assig nment, but there are manyplaces in a prog ram whereanassig nmentocc urs implicit ly:a functioncal limplicitlyassig nsthe argument values tothe cor respondingparameter variables; a return st atement imp licitlyassig nsthe return op erands tothe cor respondingresultvar iables; andalit eral expressionfor a composite type (§4.2) such as thisslice: medals := []string{"gold", "silver", "bronze"} implicitlyassig nseachelement, as if ithad beenwritt enlikethis: medals[0] = "gold" medals[1] = "silver" medals[2] = "bronze" Theelements ofmaps andchannel s,thoug h notordinar y var iables, areals o su bjec t to simi lar implicitassig nments. An assig nment, explicitorimp licit, isalways legal if the lef t-handside (the var iable) andthe right-handside (the value) havethe sametyp e.Moregeneral ly, the assig nmentislegal onlyif thevalue is assig nab le to the typ e of the var iable. Therulefor assig nab ility hascas es forvar ious typ es, so we’ll explain the relevantcas e as we introduce eachnew typ e.For the typ es we’ve dis cussedsofar,the rules aresimple: the typ es mu stexac tly match,and nil maybeassig ned toany var iable ofint erface orreference typ e. Cons tants (§3.6) havemore flexiblerules for assig nabilit y that avoidthe need for mostexplicit conv ersions. Wh ether two values may becompare d with == and != is rel ate d to assig nabilit y:inany com- parison, the firs t op erandmustbeassig nable tothe typ e of the secon d op erand, orvice versa. As wit h assig nabilit y,we’ll explain the relevantcas es for comp arab ility when wepresent each ne w type. The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 SECTION 2.5. TYPE DECLARATIONS 39 2.5. Type Declarations Thetyp e of a var iable orexpressiondefinesthe charac ter ist ics ofthe values itmay takeon, such astheir size (numberofbitsornumberofelements, perhaps), how the y arerepresent ed internal ly, the int rinsic operat ions thatcan beper for med onthem, andthe methodsass oci- ated wit h them. In any program there are var iables thatshare the samerepresent ation but sig nifyver y dif fer- entcon cepts. For ins tance,an int couldbeusedtorepresent a loopindex, a timestamp,afile des crip tor,oramonth;afloat64 couldrepresent a velocit y in metersper secon d or a temper- atureinone ofseveral scales; andastring couldrepresent a passwordorthe nameofacolor. A type de clarat iondefinesanew name d ty pe that has the same un derly ing type as an exist ing type.The named typ e prov ides a way tosep aratedif ferentand perhaps incomp atibleusesof theunderly ing typ e so thatthe y can’tbemixed unintent ion ally. type name underlying-type Type declarat ions mostoften appear at packagelevel,where the named typ e is visible through- outthe package, and ifthe nameisexp orted (it startswit h an upp er-case letter), it’saccessible from other packages as wel l. To illustratetyp e de clarat ions,let’stur n thedif ferenttemperaturescales into dif ferenttyp es: gopl.io/ch2/tempconv0 // Package tempconv performs Celsius and Fahrenheit temperature computations. package tempconv import "fmt" type Celsius float64 type Fahrenheit float64 const ( AbsoluteZeroC Celsius = -273.15 FreezingC Celsius =0 BoilingC Celsius =100 ) func CToF(c Celsius) Fahrenheit { return Fahrenheit(c*9/5 + 32) } func FToC(f Fahrenheit) Celsius { return Celsius((f - 32) * 5 / 9) } Thispackagedefinestwo typ es, Celsius and Fahrenheit,for the two units oftemperature. Ev enthoug h both havethe sameunderly ing typ e, float64,the y arenot the sametyp e,sothe y cannot becompare d or com bine d in arit hmeticexpressions.Distinguishingthe typ es makesit possible toavoid erro rslikeinadver tentlycom biningtemperatures in the two dif ferentscales; an explicittyp e conv ersion li ke Celsius(t) or Fahrenheit(t) is required toconvert from a float64. Celsius(t) and Fahrenheit(t) areconversions,not functioncal ls. They don’t ch ange the value orrepresent ation inany way,but the y make the change ofmeaningexplicit. On the other hand, the functions CToF and FToC conv ert bet weenthe two scales; the y do return dif ferentvalues. The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 40 CHAPTER 2. PROGRAM STRUCTURE Fo r ever y type T,there isacor respondingconversionoperat ion T(x) that conv ertsthe value x to typ e T.Aconv ersionfro m on e type toanother isallow ed if bot h have the sameunderly ing type,orifbot h areunnamed point ertyp es that point tovar iables ofthe sameunderly ing typ e; thes econv ersions change the typ e butnot the represent ation of the value.If x is assig nable to T,aconversionisper mitt edbut isusu allyredundant, Conv ersions are als o al lowe d betweennumer ic types, andbet weenstr ing and som e slice typ es, as wewill see inthe next chapt er. These conversions may change the represent ation of the value.For ins tance,convertingafloating-p ointnumbertoanint egerdis cards any frac tional part,and convertingastr ing toa[]byte slice allo cates a copy ofthe str ing dat a. In any cas e,a conv ersionnever fails atrun time. Theunderly ing typ e of a named typ edeter mines its str uctureand represent ation,and als o the setofint rinsic operat ions itsup por ts, whichare the sameasifthe underly ing typ e hadbeen us eddirec tly.Thatmeans thatarithmeticoperator s work the samefor Celsius and Fahren- heit as the y do for float64, as you mig htexp ect. fmt.Printf("%g\n", BoilingC-FreezingC) // "100" °C boilingF := CToF(BoilingC) fmt.Printf("%g\n", boilingF-CToF(FreezingC)) // "180" °F fmt.Printf("%g\n", boilingF-FreezingC) // compile error: type mismatch Comp arisonoperator s li ke == and < canals o be usedtocompare a value ofanamed typ e to anot her ofthe sametyp e,ortoavalue ofthe underly ing typ e.But two values ofdif ferent name d typescannot becompare d direc tly : var c Celsius var f Fahrenheit fmt.Println(c == 0) // "true" fmt.Println(f >= 0) // "true" fmt.Println(c == f) // compile error: type mismatch fmt.Println(c == Celsius(f)) // "true"! No tethe lastcas e carefully. Inspit e of itsname, the typ e conv ersion Celsius(f) do es not ch ange the value ofits argument, justits typ e.The testistruebecause c and f arebot h zero. Anamed typ e mayprovide not ation alconvenience if ithelps avoidwriting out complex typ es ov erand overagain. Theadvantage issmall whenthe underly ing typ e is simplelike float64, butbig for complic ated typ es, as wewill see whenwedis cussstr ucts. Name d typesals o make itpossibletodefine newbeh avior s forvalues ofthe typ e.These behavior s areexpress edasaset offunctions ass oci ated wit h thetyp e,cal le d thetyp e’s metho ds. We’ll look at met hods in det ail in Chapt er6but will give a taste ofthe mech anism here. Thedeclarat ionbelow,inwhichthe Celsius parameter c appearsbeforethe functionname, asso ciateswit h the Celsius type a met hod named String that retur ns c’snumer ic value fo llowe d by °C: func (c Celsius) String() string { return fmt.Sprintf("%g°C", c) } The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 SECTION 2.6. PACKAGES AND FILES 41 Many typ es de clare a String method ofthisfor m becaus e it control s howvalues ofthe typ e appear whenprint edasastr ing bythe fmt package, aswewill see inSec tion 7.1. c:=FToC(212.0) fmt.Println(c.String()) // "100°C" fmt.Printf("%v\n", c) // "100°C"; no need to call String explicitly fmt.Printf("%s\n", c) // "100°C" fmt.Println(c) // "100°C" fmt.Printf("%g\n", c) // "100"; does not call String fmt.Println(float64(c)) // "100"; does not call String 2.6. Packages and Files Packages in Goser vethe samepur pos es as librar ies or modules in other langu ages, sup por ting mo dular ity,enc apsulat ion, sep aratecompi lat ion, andreuse.The sourcecodefor a package resides in one ormore .go files, usu allyinadirec tor y whos e name end s with theimp ort pat h; forins tance,the files ofthe gopl.io/ch1/helloworld packageare store d in direc tor y $GOPATH/src/gopl.io/ch1/helloworld. Each packageser ves as a sep arate name space forits decl arat ions.Wit hin the image package, forexample, the identifier Decode refers to a dif ferentfunctionthandoesthe sameidentifier in the unicode/utf16 package. Torefer toafunctionfro m outside its package, wemust qu ali fy theidentifier tomakeexplicitwhether wemean image.Decode or utf16.Decode. Packages also let ushide infor mat ionbycontrol lingwhichnames arevisible outside the pack- age, or expor ted.InGo, a simplerulegov ernswhichidentifiersare exp orted and whichare not: expor ted identifiersstart wit h an upp er-case letter. To illustratethe basics, sup pos e that our temperatureconversionsof twarehas becom e popu lar andwewanttomakeitavai lable tothe Gocommunity asanew package. How dowedothat? Let’scre ate a packagecal le d gopl.io/ch2/tempconv,avar iat iononthe pre vious example. (Herewe’ve made an exception toour usu alruleofnumbering examples in sequence,sothat thepackagepat h canbemorerealist ic.) Thepackageits elf isstore d in two files toshowhow de clarat ions insep arate files ofapackageare accessed; in reallife, a tinypackagelikethis wouldneed onlyone file. We haveput the declarat ions ofthe typ es, their cons tants, andtheir met hodsin tempconv.go: gopl.io/ch2/tempconv // Package tempconv performs Celsius and Fahrenheit conversions. package tempconv import "fmt" type Celsius float64 type Fahrenheit float64 The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 42 CHAPTER 2. PROGRAM STRUCTURE const ( AbsoluteZeroC Celsius = -273.15 FreezingC Celsius =0 BoilingC Celsius =100 ) func (c Celsius) String() string {return fmt.Sprintf("%g°C", c) } func (f Fahrenheit) String() string { return fmt.Sprintf("%g°F", f) } andthe conversionfunctions in conv.go: package tempconv // CToF converts a Celsius temperature to Fahrenheit. func CToF(c Celsius) Fahrenheit { return Fahrenheit(c*9/5 + 32) } // FToC converts a Fahrenheit temperature to Celsius. func FToC(f Fahrenheit) Celsius { return Celsius((f - 32) * 5 / 9) } Each file startswit h a package de clarat ionthatdefinesthe packagename. Whenthe package is imp orted,its members are referred toas tempconv.CToF andsoon. Package-le vel names li kethe typ esandcon stantsdeclare d in one file ofa packageare visible toall the other files of thepackage, asifthe sourcecodewereall inasingle file.Not e that tempconv.go imports fmt, but conv.go do es not, because itdoesnot use anythingfro m fmt. Becaus e thepackage-le vel const namesbeg in with upp er-case letters,the y to o areaccessible with qualified names like tempconv.AbsoluteZeroC: fmt.Printf("Brrrr! %v\n", tempconv.AbsoluteZeroC) // "Brrrr! -273.15°C" To convert a Cel siu s temp eraturetoFahren heitinapackagethatimp orts gopl.io/ch2/temp- conv,wecan write the fol low ing code: fmt.Println(tempconv.CToF(tempconv.BoilingC)) // "212°F" The doc comment (§10.7.4) immediate lypre cedingthe package de clarat iondocuments the packageasawhole.Convent ion ally, itshouldstart wit h asummar y sent enceinthe sty le illustrated.Onlyone file in eachpackageshouldhaveapackagedoc comment.Extensive doc comments areoften place d in a file oftheir own,convent ion allycal le d doc.go. Exercis e2.1: Addtyp es,cons tants, andfunctions to tempconv forpro cessingtemperatures in theKelvinscale,where zeroKelvinis −273.15°C andadif ference of1Khas the samemag ni- tude as 1°C. 2.6.1. Imports Wi thin a Goprogram, every packageisidentified byaunique str ing cal le d its import pat h. Thes e arethe str ingsthatapp ear in an import de clarat ionlike "gopl.io/ch2/tempconv". Thelangu agespecification doesn’tdefine where these str ingscom e from or whatthe y me an; it’suptothe tools toint erpretthem. Whenusingthe go to ol(Chapter10), an import pat h denot esadirec tor y cont ainingone ormoreGosourcefiles thattoget her makeupthe package. The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 SECTION 2.6. PACKAGES AND FILES 43 In addition toits import pat h, each packagehas a pack age nam e,whichisthe short (andnot ne cessarily unique) namethatapp earsinits package de clarat ion. Byconvent ion,apackage’s name match esthe lastseg mentofits import pat h, making iteasy topre dic t that the package name of gopl.io/ch2/tempconv is tempconv. To use gopl.io/ch2/tempconv,wemustimp ort it: gopl.io/ch2/cf // Cf converts its numeric argument to Celsius and Fahrenheit. package main import ( "fmt" "os" "strconv" "gopl.io/ch2/tempconv" ) func main() { for _, arg := range os.Args[1:] { t, err := strconv.ParseFloat(arg, 64) if err != nil { fmt.Fprintf(os.Stderr, "cf: %v\n", err) os.Exit(1) } f:=tempconv.Fahrenheit(t) c:=tempconv.Celsius(t) fmt.Printf("%s = %s, %s = %s\n", f, tempconv.FToC(f), c, tempconv.CToF(c)) } } Theimp ort declarat ionbinds a short nametothe imp orted packagethatmay beusedtorefer to its cont entsthroughoutthe file.The import ab ove lets usrefer tonames wit hin gopl.io/ch2/tempconv by usingaqu alified ident ifier li ke tempconv.CToF.Bydefau lt, the short nameisthe packagename—tempconv in thiscas e—but an imp ort declarat ionmay sp ecif y an alternat ive nametoavoid a conflic t(§10.3). The cf prog ram conv ertsasinglenumer ic command-lineargumenttoits value in bot h Celsiu s andFahren heit: $gobuild gopl.io/ch2/cf $./cf 32 32°F = 0°C, 32°C = 89.6°F $./cf 212 212°F = 100°C, 212°C = 413.6°F $./cf -40 -40°F = -40°C, -40°C = -40°F It isanerror toimp ort a packageand thennot refer toit. Thische ckhelps eliminatedep en- dencies thatbecom e unnecessary asthe codeevo l ves, although itcan beanuis ancedur ing The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 44 CHAPTER 2. PROGRAM STRUCTURE debugging, since commenting out a lineofcodelike log.Print("got here!") mayremov e thesolereference tothe packagename log,causingthe compi ler toemitanerror.Inthissit- uation,you need tocomment out or deletethe unnecessary import. Bett erstill,use the golang.org/x/tools/cmd/goimports to ol, whichaut omat ical lyins erts andremov espackages fro m theimp ort declarat ionasnecessary ; most editors can beconfig- ured torun goimports each timeyou saveafile.Likethe gofmt to ol, itals o pretty-printsGo source files in the canonic al format. Exercis e2.2: Wr ite a general-pur pos e unit-conv ersionprogram analogou s to cf that reads numb ers fro m itscommand-linearguments orfro m thestand ard inp utifthere are noargu- ments, andconvertseachnumberint o units like temperatureinCel siu s andFahren heit, lengt h in feetand meters,weig ht in pound s andkilog rams, andthe like. 2.6.2. PackageInitialization Packageinitializat ionbeg insbyinitializingpackage-le vel var iables in the order in whichthe y aredeclare d,exceptthatdep endencies areres olved firs t: var a = b + c // a initialized third, to 3 var b = f() // b initialized second, to 2, by calling f var c = 1 // c initialized first, to 1 func f() int { return c + 1 } If the packagehas multiple .go files, the y areinitialize d in the order in whichthe files are giventothe compi ler ; the go to olsor ts .go files bynamebeforeinv oking the compi ler. Each var iable decl are d at packagelevel startslifewit h thevalue ofits initializer expression, if any, but for som e var iables, like tables ofdat a, an initializer expressionmay not bethe simplest way toset its initial value.Inthatcas e,the init func tionmechanism may besimpler.Any file may cont ain anynumberoffunctions whose declarat ionisjust func init() { /* ... */ } Such init func tions can’tbecal le d or reference d,but other wis e they are nor mal functions. Wi thin each file, init func tions are aut omat ical lyexe cut edwhenthe program starts, in the order in whichthe y aredeclare d. Onepackageisinitialize d at a time, inthe order ofimp ortsinthe program, dependencies firs t, so a package p importing q canbesurethat q is fullyinitialize d before p’sinitializat ionbeg ins. Init ializat ionpro ceedsfro m thebot tom up;the main packageisthe lasttobeinitialize d.In this manner,all packages arefullyinitialize d before the app lic ation’s main func tionbeg ins. Thepackagebelow definesafunction PopCount that retur nsthe numberofset bits, thatis, bitswhose value is1,inauint64 value,whichiscal le d its popu lat ion count.Itusesan init func tiontopre compute a table ofresults, pc,for eachpossible8-bit value sothatthe PopCount func tionneedn’ttake64steps but can justretur n thesum ofeig httable lookups. (Thisisdefi- nite ly not thefastest algor it hmfor count ing bits, but it’sconvenientfor illustrat ing init The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 SECTION 2.7. SCOPE 45 func tions,and for showing how topre compute a table ofvalues, whichisoften a useful prog rammingtechnique.) gopl.io/ch2/popcount package popcount // pc[i] is the population count of i. var pc [256]byte func init() { for i := range pc { pc[i] = pc[i/2] + byte(i&1) } } // PopCount returns the population count (number of set bits) of x. func PopCount(x uint64) int { return int(pc[byte(x>>(0*8))] + pc[byte(x>>(1*8))] + pc[byte(x>>(2*8))] + pc[byte(x>>(3*8))] + pc[byte(x>>(4*8))] + pc[byte(x>>(5*8))] + pc[byte(x>>(6*8))] + pc[byte(x>>(7*8))]) } No tethatthe range lo opin init us esonlythe index; the value isunnecessary and thu s ne e d notbeinclude d.The loopcou ldals ohave beenwritt enas for i, _ := range pc { We’ll see other usesof init func tions inthe next sec tion and inSec tion 10.5. Exercis e2.3: Re writ e PopCount to use a loopins teadofasingleexpression. Compare the per- formance ofthe two versions.(Section11.4 shows how tocompare the per for mance ofdif fer- entimp lementation s systematically.) Exercis e2.4: Wr ite a versionof PopCount that counts bitsbyshif tingits argumentthrough 64 bit position s,testing the rig htmostbit eachtime. Compare its per for mance tothe table- lo oku p version. Exercis e2.5: Theexpression x&(x-1) clears the rig htmostnon-zerobit of x.Write a version of PopCount that counts bitsbyusingthisfac t,andass ess its per for mance. 2.7. Scope Adeclarat ionass oci ates a namewit h aprogram entity,suchasafunctionoravar iable.The scop e of a declarat ionisthe par t of the sourcecodewhere a use ofthe declare d name refersto that decl arat ion. The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 46 CHAPTER 2. PROGRAM STRUCTURE Don’tconfuse scop e with lifet ime. The scope ofadeclarat ionisareg ionofthe program text; it isacompi le-t imepro per ty. The lifet imeofavar iable isthe range oftimedur ingexe cut ion when the var iable can berefer red tobyother par ts of the program; itisarun-t imepro per ty. Asyntactic bl o ck is a sequence ofstatementsenclos edinbraces like those thatsur round the bodyofafunctionorloop. A name declare d inside a synt actic blo ckisnot visible outside that block. Theblo ckenclos es itsdeclarat ions and deter mines their scope.Wecan generalize this notion of blo cks toinclude other gro upingsofdeclarat ions thatare not explicitlysur rounded by braces in the sourcecode; we’ll cal l them all lexicalblocks.There isalexic al blockfor the entire sourcecode, cal le d the univ ers e bl o ck;for eachpackage; for each file; for each for, if, and switch st atement;for eachcas e in a switch or select st atement;and,ofcours e, foreach explicitsyntactic blo ck. Adeclarat ion’slexic al blockdeter mines its scope,whichmay belarge orsmall.The declara- tion s of bui lt-in typ es, func tions,and con stantslike int, len,and true areinthe univers e blockand can berefer red tothroughoutthe ent ire program. Declarat ions outside anyfunc- tion,thatis, at pack age level,can berefer red tofro m any file in the samepackage. Imp orted packages, suchas fmt in the tempconv example, are declare d at the file level,sothe y canbe referred tofro m thesame file,but not fro m anot her file in the samepackagewit houtanother import.Manydeclarat ions,likethatofthe var iable c in the tempconv.CToF func tion, are local,sothe y canberefer red toonlyfro m within the samefunctionorperhaps justapar t of it. Thescope ofacontrol-flow lab el, asusedby break, continue,and goto st atements, isthe entire enclosingfunction. Aprogram may cont ain multipledeclarat ions ofthe samenamesolon g as eachdeclarat ionis in a different lexic al block. For example, you can decl are a local variablewit h thesamename as a package-le vel var iable.Or, asshown inSec tion 2.3.3, you can decl are a functionparame- tercal le d new,eventhoug h afunctionofthisnameispre declare d in the univers e block. Don’t ov erdoit, thoug h; thelargerthe scope ofthe redeclarat ion, the more likelyyou are tosur prise thereader. Wh enthe compi ler encounters a reference toaname, itlooks for a declarat ion, startingwit h theinner mostenclosinglexic al blockand wor kinguptothe univers e block. Ifthe compi ler find s no declarat ion, itrep ortsan ‘‘unde clare d name’’ er ror.Ifanameisdeclare d in bot h an outerblo ckand aninner blo ck, the inner decl arat ionwill befound firs t.Inthatcas e,the inner decl arat ionissaid to sh a dow or hi d e theout erone,mak ingitinaccessible: func f() {} var g = "g" func main() { f:="f" fmt.Println(f) // "f"; local var f shadows package-level func f fmt.Println(g) // "g"; package-level var fmt.Println(h) // compile error: undefined: h } The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 SECTION 2.7. SCOPE 47 Wi thin a function, lexical blo cks may beneste d to arbit rar ydepth,soone local decl arat ioncan sh adowanother.Mostblo cks arecre ate d by control-flow con str uctslike if st atementsand for lo ops. Theprogram below has three dif ferentvar iables cal le d x becaus e each declarat ion appears in a dif ferentlexic al block. (Thisexampleillustrates scope rules, not good sty le!) func main() { x:="hello!" for i := 0; i < len(x); i++ { x:=x[i] if x != '!' { x:=x+'A' - 'a' fmt.Printf("%c", x) // "HELLO" (one letter per iteration) } } } Theexpressions x[i] and x+'A' - 'a' each refer toadeclarat ionof x from anout erblo ck; we’ll explain thatinamom ent.(No tethatthe latterexpressionis not equivalentto uni- code.ToUpper.) As mention edabove , notall lexic al blocks correspond toexplicitbrace-delimite d sequences of st atements; som e aremerelyimp lie d.The for lo opabove cre atestwo lexic al blocks: the explicitblo ckfor the loopbody, and animp licitblo ckthataddition allyenclos es thevar iables de clare d by the initializat ionclaus e,suchas i.The scope ofavar iable decl are d in the imp licit blockisthe con dit ion,post-statement (i++), andbodyofthe for st atement. Theexamplebelow als o hasthree var iables named x,eachdeclare d in a different blo ck—on e in the functionbody, one inthe for st atement’sblo ck, andone inthe loopbody—butonlytwo of the blo cks areexplicit: func main() { x:="hello" for _, x := range x { x:=x+'A' - 'a' fmt.Printf("%c", x) // "HELLO" (one letter per iteration) } } Like for lo ops, if st atementsand switch st atementsals o create imp licitblo cks in addition to their bodyblo cks. Thecode in the fol low ing if-else ch ain shows the scope of x and y: if x := f(); x == 0 { fmt.Println(x) }else if y := g(x); x == y { fmt.Println(x, y) }else { fmt.Println(x, y) } fmt.Println(x, y) // compile error: x and y are not visible here The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 48 CHAPTER 2. PROGRAM STRUCTURE Thesecon d if st atement isneste d within the firs t,sovar iables decl are d within the firs t st ate- ment’sinitializer arevisible wit hin the secon d.Simi lar rules apply toeachcas e of a switch st atement:there isablo ckfor the con dit ion and a blo ckfor eachcas e body. At the packagelevel,the order in whichdeclarat ions app ear has noeffec t on their scope,soa de clarat ionmay refer toits elf ortoanother thatfol lowsit, letting usdeclare recursiveor mu tuallyrec ursivetyp esandfunctions.The compi ler will rep ort anerror ifacon stant orvar i- able decl arat ionreferstoits elf,how ever. In thisprogram: if f, err := os.Open(fname); err != nil { // compile error: unused: f return err } f.ReadByte() // compile error: undefined f f.Close() // compile error: undefined f thescope of f is justthe if st atement,so f is not accessibletothe statementsthatfol low, resu lting incompi ler erro rs. Dep endingonthe compi ler,you may get an addition alerror reportingthatthe local variable f was never used. Thus itisoften necessary todeclare f before the con dit ion sothatitisaccessibleafter : f, err := os.Open(fname) if err != nil { return err } f.ReadByte() f.Close() Yo u maybetempt edtoavoid decl aring f and err in the out erblo ckbymov ing the cal lsto ReadByte and Close inside an else block: if f, err := os.Open(fname); err != nil { return err }else { // f and err are visible here too f.ReadByte() f.Close() } butnor mal prac tice in Goistodealwit h theerror inthe if blockand thenretur n, so thatthe successf ulexe cut ion pat h is not indente d. Sh ort var iable decl arat ions demandanawarenessofscope.Con sider the program below, whichstartsbyobt ainingits cur rentwor kingdirec tor y andsav ingit in a package-le vel var i- able.Thiscou ldbedon e by cal ling os.Getwd in function main,but it mig htbebettertosep a- ratethiscon cer n from the primary log ic,especi ally iffai lingtoget the direc tor y is a fat aler ror. Thefunction log.Fatalf pr intsamessage and cal ls os.Exit(1). The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 SECTION 2.7. SCOPE 49 var cwd string func init() { cwd, err := os.Getwd() // compile error: unused: cwd if err != nil { log.Fatalf("os.Getwd failed: %v", err) } } Sinceneither cwd nor err is already declare d in the init func tion’sblo ck, the := st atement de claresbot h of themaslocal variables. Theinner decl arat ionof cwd makesthe out erone inaccessible, sothe statement doesnot updatethe package-le vel cwd var iable as intended. CurrentGocompi lersdetec t that the local cwd var iable isnever usedand rep ort thisasan er ror,but the y arenot str ictly required toper for m this che ck. Fur thermore, a minor change , such asthe addition of a log gingstatement thatreferstothe local cwd woulddefeatthe che ck. var cwd string func init() { cwd, err := os.Getwd() // NOTE: wrong! if err != nil { log.Fatalf("os.Getwd failed: %v", err) } log.Printf("Working directory = %s", cwd) } Theglobal cwd var iable remainsuninitialize d,and the app arent lynor mal log out put obfuscates the bug . Thereare a numberofways todealwit h this pot ent ial pro blem. Themostdirec t is toavoid := by declaring err in a sep arate var de clarat ion: var cwd string func init() { var err error cwd, err = os.Getwd() if err != nil { log.Fatalf("os.Getwd failed: %v", err) } } We’ve now seenhow packages, files, decl arat ions,and statementsexpress the str uctureof prog rams. Inthe next two chapt ers,we’ll look at the str uctureofdat a. The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 This page intentionally left blank From the Library of YIGUANG HU ptg16105617 3 Basic Data Types It’sall bits at the bot tom,ofcours e, butcomputers operatefundament allyonfixe d-size num- bers cal le d word s,whichare int erprete d as integers,floating-p ointnumbers,bit sets, ormem- or y addresses, thencom bine d into largeraggregates thatrepresent packets, pixel s,por tfo lios, poetr y,and everythingels e.Gooffersavar ietyofways toorganize dat a, with a spectrumof data typ es that at one end match the featuresofthe hardwareand atthe other endprovide what programmersneed toconvenientlyrepresent complic ated dat a st ruc tures. Go’styp es fal l into fourcategor ies: basi c ty pes, ag gre gat e ty pes, reference types,and interface ty pes.Basic typ es, thetopic ofthischapt er, include numbers,str ings, andboole ans. Aggregate types—ar rays (§4.1) andstr ucts(§4.4)—form morecomplic ated dat a typesbycom biningval- ues ofseveral simpler ones. Reference typ esareadiverse gro upthatincludes point ers (§2.3.2), slices (§4.2), maps (§4.3), functions (Chapter5), andchannel s (C hapter8), but whatthe y have in common isthatthe y al l refertoprogram variables orstate in direc tly,sothatthe effec t of an op erat ionapp lie d to one reference isobs erve d by all copies ofthatreference.Final ly, we’ll tal k ab out int erface typ es in Chapt er7. 3.1. Int egers Go’snumer ic data typ esinclude several sizes ofint egers,floating-p ointnumbers,and complex numb ers.Eachnumer ic type deter mines the size andsig nedness ofits values. Let’sbeg in with integers. Go provides bot h sig ned and unsig ned int egerarithmetic. Thereare fourdistinc t sizes of sig ned int egers—8, 16, 32, and64bits—repres ente d by the typ es int8, int16, int32,and int64,and cor respondingunsig ned versions uint8, uint16, uint32,and uint64. 51 The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 52 CHAPTER 3. BASIC DATATYPES Thereare als o twotyp es called just int and uint that arethe natural ormostefficientsize for sig ned and unsig ned int egers onapar tic ularplatfor m; int is byfar the most widely used numerictyp e.Bot h thes e typeshavethe samesize,eit her 32 or64bits, but onemustnot make assump tions about which; different compi lersmay makedif ferentchoices evenonidentical hard ware. Thetyp e rune is ansynonym for int32 andconvent ion allyindic ates thatavalue isaUnico de co de point. Thetwo names may beusedint erc hange ably.Simi larly,the typ e byte is ansyn- onym for uint8,and emp hasizes thatthe value isapie ce of raw dat a rat her thanasmall numericquant ity. Final ly, there isanunsig ned int egertyp e uintptr,whose width isnot specified but issuffi- cienttoholdall the bitsofapoint ervalue.The uintptr type isusedonlyfor low-le vel prog ramming, suchasatthe bound ary ofaGoprogram wit h aClibrar y or anoperat ingsys- tem. We’ll see examples ofthiswhenwedealwit h the unsafe package in Chapt er13. Regardlessoftheir size, int, uint,and uintptr aredif ferenttyp es from their explicitlysize d siblings. Thus int is not the sametyp eas int32,evenifthe natural size ofint egers is32bits, andanexplicitconversionisrequired touse an int value where an int32 is needed,and vice vers a. Signed numbers are repres ente d in 2’s-comp lementfor m,inwhichthe hig h-order bit is reserved for the sig n of the numberand the range ofvalues ofan n-bit numberisfro m −2n−1 to 2n−1−1. Unsig ned int egers use the full range ofbitsfor non-negat ive values andthu s have therange 0 to2n−1. For ins tance,the range of int8 is −128 to127, where asthe range of uint8 is 0 to255. Go’sbinar y op erator s forarithmetic, logic, andcomparisonare liste d here inorder ofdecre as- ingpre cedence: */%<<>>&&^ +-|^ == != < <= > >= && || Thereare onlyfive level s of precedence for binary operator s.Operator s at the samelevel as- so ciate to the lef t, so parenthes es mayberequired for clarity,ortomakethe operator s evaluate in the int ended order in an expressionlike mask & (1 << 28). Each operator inthe firs t twolines ofthe table abov e,for ins tance +,has a corresponding assig nment operator li ke += that may beusedtoabbre viate anassig nmentstatement. Theint egerarithmeticoperator s +, -, *,and / maybeapp lie d to int eger, floating-p oint, and comp lex numbers,but the remainder operator % applies onlytoint egers.The beh avior of % for negat ive numbers var ies acrossprogramminglangu ages. InGo, the sig n of the remainder is always the sameasthe sig n of the div idend, so -5%3 and -5%-3 arebot h -2.The beh avior of / dep ends onwhether its operands are int egers,so 5.0/4.0 is 1.25,but 5/4 is 1 becaus e integer divisiontrunc atesthe resulttowardzero. The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 SECTION 3.1. INTEGERS 53 If the resultof an arithmeticoperat ion, whether signe d or unsig ned,has morebitsthancan be repres ente d in the resulttyp e,itissaid to ov erflow.The hig h-order bitsthatdonot fitare si lentlydis carde d.Ifthe originalnumberisasig ned typ e,the resultcou ldbenegat ive ifthe lef tmost bit is a 1, as in the int8 examplehere: var u uint8 = 255 fmt.Println(u, u+1, u*u) // "255 0 1" var i int8 = 127 fmt.Println(i, i+1, i*i) // "127 -128 1" Tw o integers ofthe sametyp e maybecompare d usingthe binar y comp arisonoperator s below; the typ e of a comparisonexpressionisaboole an. == equalto != notequ alto < lessthan <= lessthanorequ alto > greaterthan >= greaterthanorequ alto In fac t, al l values ofbasic typ e—boole ans, numbers,and str ings—are comp arab le,meaning that two values ofthe sametyp e maybecompare d usingthe == and != op erator s.Fur ther- more , integers,floating-p ointnumbers,and str ingsare ordere d by the comparisonoperator s. Thevalues ofmanyother typ es arenot comparable,and no other typ es areordered.Aswe encountereachtyp e,we’ll present the rules gov erningthe comp arab ility of itsvalues. Thereare als o unar yaddition and subtrac tionoperator s: + unar y positive (no effec t) - unar y negat ion Fo r integers, +x is a shorthand for 0+x and -x is a shorthand for 0-x;for floating-p ointand comp lex numbers, +x is just x and -x is the negat ionof x. Go als o prov ides the fol low ing bit w ise binar y op erator s,the firs t four ofwhichtre attheir op- erands asbit patternswit h no con ceptofarithmeticcar ryorsig n: & bit w ise AND | bit w ise OR ^ bit w ise XOR &^ bit cle ar (AND NOT) << lef t shif t >> rightshif t Theoperator ^ is bit w ise exc lusiveOR(XO R)whenusedasabinar y op erator,but whenused as a unar y prefixoperator it isbit w ise negat ionorcomplement; thatis, itretur nsavalue wit h each bit inits operandinv erted.The &^ op erator isbit cle ar (AND NOT): in the expression z=x&^y,eachbit of z is 0 ifthe cor respondingbit of y is 1;other wis e it equ als the cor- resp ondingbit of x. The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 54 CHAPTER 3. BASIC DATATYPES Thecodebelow shows how bit w ise operat ions can beusedtoint erpretauint8 value as a comp act and efficientset of8indep endentbits. Ituses Printf’s %b verb toprint a numb er’s binary dig its; 08 mo difies %b (an adverb!) topad the resultwit h zeros toexac tly 8 dig its. var x uint8 = 1<<1 | 1<<5 var y uint8 = 1<<1 | 1<<2 fmt.Printf("%08b\n", x) // "00100010", the set {1, 5} fmt.Printf("%08b\n", y) // "00000110", the set {1, 2} fmt.Printf("%08b\n", x&y) // "00000010", the intersection {1} fmt.Printf("%08b\n", x|y) // "00100110", the union {1, 2, 5} fmt.Printf("%08b\n", x^y) // "00100100", the symmetric difference {2, 5} fmt.Printf("%08b\n", x&^y) // "00100000", the difference {5} for i := uint(0); i < 8; i++ { if x&(1<>1) // "00010001", the set {0, 4} (S ection6.5 shows an implementation of int egersets thatcan bemuchbig ger thanabyte.) In the shif t op erat ions x<>n,the n op eranddeter mines the numberofbit position s to shif tandmustbeunsig ned;the x op erandmay beunsig ned orsig ned.Arithmetically, a lef t shif t x<>n is equivalenttothe floor of div isionby2n. Left shif ts fill the vac ated bitswit h zeros, as do rig htshif ts of unsig ned numbers,but rig ht shif ts of sig ned numbers fill the vac ated bitswit h copies ofthe sig n bit.For thisreason, itis importanttouse unsig ned arithmeticwhenyou’re tre ating anint eger as a bit pattern. Although Goprovides unsig ned numbers and arithmetic, wetendtouse the sig ned int form even for quant ities thatcan’tbenegat ive , such asthe lengt h of anarray,thoug h uint mig ht seem a moreobv iou s ch oice.Indeed,the bui lt-in len func tionretur nsasig ned int,asinthis lo opwhichannounces prize medals in reverse order : medals := []string{"gold", "silver", "bronze"} for i := len(medals) - 1; i >= 0; i-- { fmt.Println(medals[i]) // "bronze", "silver", "gold" } Thealt ernat ive wouldbecal amitous.If len returned anunsig ned number, then i to o would be a uint,and the con dit ion i>=0wouldalways betruebydefinition.After the thirditera- tion,inwhich i==0,the i-- st atement wou ldcause i to becom e not −1, but the maximum uint value (for example, 264−1), andthe evaluation of medals[i] wouldfai l at run time, or pani c (§5.9), byatt emp tingtoaccess an elementoutside the bound s of the slice. Fo r this reason, unsig ned numbers tend tobeusedonlywhentheir bit w ise operator s or peculi ar ar ithmeticoperator s arerequired,aswhenimp lementing bit sets, parsingbinar y file The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 SECTION 3.1. INTEGERS 55 formats, orfor hashingand crypt ography.The y aretypic ally not usedfor merelynon-negat ive qu ant ities. In general,anexplicitconversionisrequired toconvert a value fro m on e type toanother,and binary operator s forarithmeticand log ic(exceptshif ts) mu sthaveoperands ofthe sametyp e. Although thisocc asionallyresults in longerexpressions,itals o eliminates a whole class of problemsand makes programseasier tounderst and. As anexamplefami liar fro m ot her cont exts, consider thissequence: var apples int32 = 1 var oranges int16 = 2 var compote int = apples + oranges // compile error At tempt ing tocompi lethese three declarat ions pro duces an erro r mess age: invalid operation: apples + oranges (mismatched types int32 and int16) Thistyp e mismatch can be fixe d in several ways, mostdirec tly byconvertingeverythingtoa common typ e: var compote = int(apples) + int(oranges) As des crib edinSec tion 2.5, for every typ e T,the conversionoperat ion T(x) conv ertsthe value x to typ e T if the conversionisallow ed. Manyint eger-to-integerconversions donot ent ail any ch ange invalue; the y ju sttel l thecompi ler how toint erpretavalue.But a conversionthatnar- rows a big integerint o asmaller one,oraconversionfro m integertofloating-p ointorvice vers a,may change the value orlos e precision: f:=3.141 // a float64 i:=int(f) fmt.Println(f, i) // "3.141 3" f=1.99 fmt.Println(int(f)) // "1" Flo at to int egerconversiondis cards any frac tionalpar t, tr unc ating towardzero. You should avoidconversions inwhichthe operandisout of range for the targettyp e,because the beh av- iordep ends onthe imp lementation: f:=1e100 // afloat64 i:=int(f) // result is implementation-dependent Integerlit eralsofany size andtyp e canbewritt enasordinar y de cimal numbers,orasoctal numb ers ifthe y beginwit h 0,asin 0666,orashexade cimal if the y beginwit h 0x or 0X,asin 0xdeadbeef.Hex digitsmay beupp erorlow ercas e.Nowad ays octalnumbers seemtobe us edfor exac tly one pur pos e—file per missions onPOSIX systems—buthexade cimal numbers arewidely usedtoemp hasize the bit pattern ofanumberoverits numer icvalue. Wh enprint ing numbers usingthe fmt package, wecan cont rol the radix andfor mat wit h the %d, %o,and %x verbs, as shown inthisexample: The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 56 CHAPTER 3. BASIC DATATYPES o:=0666 fmt.Printf("%d %[1]o %#[1]o\n", o) // "438 666 0666" x:=int64(0xdeadbeef) fmt.Printf("%d %[1]x %#[1]x %#[1]X\n", x) // Output: // 3735928559 deadbeef 0xdeadbeef 0XDEADBEEF No tethe use oftwo fmt tr icks. Usu allyaPrintf format str ing containingmultiple % verbs wouldrequirethe samenumberofext ra op erands,but the [1] ‘‘adverbs’’ af ter % te ll Printf to us e thefirs t op erandoverand overagain. Secon d,the # adverb for %o or %x or %X te lls Printf to emita0 or 0x or 0X prefixrespectively. Rune lit eralsare writt enasacharac ter wit hin singlequotes. ThesimplestexampleisanASCII ch arac ter like 'a',but it’spossibletowrite any Unico de co de pointeit her direc tly orwit h numericescap es, as wewill see shortly. Runesare print edwit h %c,orwit h %q if quoting isdesired: ascii := 'a' unicode := 'D' newline := '\n' fmt.Printf("%d %[1]c %[1]q\n", ascii) // "97 a 'a'" fmt.Printf("%d %[1]c %[1]q\n", unicode) // "22269 D 'D'" fmt.Printf("%d %[1]q\n", newline) // "10 '\n'" 3.2. Floating-PointNumbers Go provides two sizes of floating-p ointnumbers, float32 and float64.Their arit hmetic prop erties aregov erned bythe IEEE 754 stand ard imp lemente d by all moder nCPUs. Values ofthese numer ic typesrange fro m tiny tohuge. The limits of floating-p ointvalues can be found inthe math package. The con stant math.MaxFloat32,the largest float32,isabout 3.4e38,and math.MaxFloat64 is about 1.8e308.The smallestpositive values arenear 1.4e-45 and 4.9e-324,respectively. A float32 prov ides approximatelysix decimal digitsofpre cision, where asafloat64 prov ides about15dig its; float64 shouldbepreferred for mostpur pos es becaus e float32 comp utation s acc umulateerror rapid lyunlessone isquite caref ul, and the smallestpositive integerthatcannot beexac tly represent ed as a float32 is not large: var f float32 = 16777216 // 1 << 24 fmt.Println(f == f+1) // "true"! Flo at ing-p ointnumbers can bewritt enlit eral lyusingdecimals, like this: const e = 2.71828 // (approximately) Dig its may beomitt edbeforethe decimal point (.707)orafter it(1.). Ver y smal l or ver y large numbers are betterwritt eninscientificnot ation,wit h theletter e or E precedingthe dec- imal expon ent: The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 SECTION 3.2. FLOATING-POINT NUMBERS 57 const Avogadro = 6.02214129e23 const Planck =6.62606957e-34 Flo at ing-p ointvalues areconvenientlyprint edwit h Printf’s %g verb,whichcho osesthe most comp act represent ation thathas adequ ate pre cision, but for tables ofdat a, the %e (exp onent) or %f (noexp onent)for msmay bemoreappro priate. All three verbs allow fieldwidth and numericpre cisiontobecontrol led. for x := 0; x < 8; x++ { fmt.Printf("x = %d eA =%8.3f\n", x, math.Exp(float64(x))) } Thecodeabove printsthe pow ers of e with thre e de cimal digitsofpre cision, aligne d in an eig ht-charac ter field: x=0 eA =1.000 x=1 eA =2.718 x=2 eA =7.389 x=3 eA =20.086 x=4 eA =54.598 x=5 eA =148.413 x=6 eA =403.429 x=7 eA =1096.633 In addition toalarge col lec tion of the usu almat hemat ical functions,the math packagehas func tions for cre ating and detec ting the speci al values define d by IEEE 754: the positive and negat ive infinities, whichrepresent numb ers ofexcessive mag nitude andthe resultofdiv ision by zero; andNaN (‘‘notanumber’’), the resultofsuchmat hemat ical lydubious operat ions as 0/0 or Sqrt(-1). var z float64 fmt.Println(z, -z, 1/z, -1/z, z/z) // "0 -0 +Inf -Inf NaN" Thefunction math.IsNaN testswhether its argumentisanot-a-numbervalue,and math.NaN returnssuchavalue.It’stempt ing touse NaN as a sentinel value in a numer ic comp utation, buttesting whether a specificcomputation alresultisequ altoNaN isfraug htwit h peril becaus e anycomparisonwit h NaN always yields false: nan := math.NaN() fmt.Println(nan == nan, nan < nan, nan > nan) // "false false false" If a functionthatretur nsafloating-p ointresultmig htfai l,it’sbettertorep ort the fai luresep a- rately, likethis: func compute() (value float64, ok bool) { // ... if failed { return 0, false } return result, true } The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 58 CHAPTER 3. BASIC DATATYPES Thenext program illustrates floating-p ointgraphics comp utation.Itplots a functionoftwo var iables z=f(x, y) as a wiremesh3-D sur face,usingScalableVec tor Graphics (SVG), a st and ard XML not ation for linedraw ings. Figure3.1 shows an exampleofits out put for the func tion sin(r)/r,where r is sqrt(x*x+y*y). Figure 3.1. Asur face plot ofthe function sin(r)/r. gopl.io/ch3/surface // Surface computes an SVG rendering of a 3-D surface function. package main import ( "fmt" "math" ) const ( width, height = 600, 320 // canvas size in pixels cells = 100 // number of grid cells xyrange = 30.0 // axis ranges (-xyrange..+xyrange) xyscale = width / 2 / xyrange // pixels per x or y unit zscale = height * 0.4 // pixels per z unit angle = math.Pi / 6 // angle of x, y axes (=30°) ) var sin30, cos30 = math.Sin(angle), math.Cos(angle) // sin(30°), cos(30°) The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 SECTION 3.2. FLOATING-POINT NUMBERS 59 func main() { fmt.Printf("", width, height) for i := 0; i < cells; i++ { for j := 0; j < cells; j++ { ax, ay := corner(i+1, j) bx, by := corner(i, j) cx, cy := corner(i, j+1) dx, dy := corner(i+1, j+1) fmt.Printf("\n", ax, ay, bx, by, cx, cy, dx, dy) } } fmt.Println("") } func corner(i, j int) (float64, float64) { // Find point (x,y) at corner of cell (i,j). x:=xyrange * (float64(i)/cells - 0.5) y:=xyrange * (float64(j)/cells - 0.5) // Compute surface height z. z:=f(x, y) // Project (x,y,z) isometrically onto 2-D SVG canvas (sx,sy). sx := width/2 + (x-y)*cos30*xyscale sy := height/2 + (x+y)*sin30*xyscale - z*zscale return sx, sy } func f(x, y float64) float64 { r:=math.Hypot(x, y) // distance from (0,0) return math.Sin(r) / r } No tice thatthe function corner returnstwo values, the coordinates ofthe cor ner ofthe cel l. Theexplanation of how the program wor ksrequires onlybasic geometr y,but it’sfine toskip ov erit, since the point istoillustrate floating-p ointcomputation.The ess enceofthe program is mappingbet weenthree dif ferentcoordinatesystems,shown inFigure3.2. The firs t is a 2-D gr idof100&100 cellsidentified byint egercoordinates (i, j), startingat(0, 0) in the far back corner.Weplotfro m thebacktothe fro ntsothatbackg round polygons may beobs cured by foreground ones. Thesecon d co ordinatesystemisameshof3-D floating-p ointcoordinates (x, y, z), where x and y arelinearfunctions of i and j,transl ate d so thatthe originisinthe center, and scale d by thecon stant xyrange.The heig ht z is the value ofthe sur face func tion f (x, y). Thethirdcoordinatesystemisthe 2-D imagecanvas, wit h (0, 0) in the top lef tcorner.Points in thisplane are denot ed(sx, sy). Weuse anisometr icpro jec tion tomap each3-D point The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 60 CHAPTER 3. BASIC DATATYPES Figure 3.2. Three dif ferentcoordinatesystems. (x, y, z)ont o the2-D canvas. A pointapp earsfar thertothe rig htonthe canvas the gre aterits x value orthe sm all er its y value.And a point app earsfar therdow n thecanvas the gre aterits x value or y value,and the smaller its z value.The ver tic alandhor izont alscale factors for x and y areder ive d from the sineand cosineofa30° angle. The scale factorfor z,0.4, isanarbit rar y parameter. Fo r each cel l in the 2-D grid, the main functioncomputesthe coordinates onthe image canvas of the fourcor nersofthe polygon AB CD,where B correspond s to (i, j)and A, C,and D areits neig hbors,thenprints an SVG ins tructiontodraw it. Exercis e3.1: If the function f returnsanon-finite float64 value,the SVG file will contain invalid elements (although manySVG renderershandlethisgracef ully). Modif y theprogram toskipinvalid polygons. Exercis e3.2: Experiment wit h visu alizat ions ofother functions fro m the math package. Can youpro duce an eggbox,mogu ls, orasadd le? Exercis e3.3: Coloreachpolygonbas edonits heig ht, sothatthe peaks arecolored red (#ff0000)and the val leys blue(#0000ff). Exercis e3.4: Fo llowing the appro ach ofthe Lissajous exampleinSec tion 1.7, cons truct a web server thatcomputessur facesandwritesSVG dat a to the client. Theser ver mustset the Con- tent-Type he ader like this: w.Header().Set("Content-Type", "image/svg+xml") (Thisstepwas not required inthe Lissajous examplebecause the ser ver usesstand ard heur ist ics torecog nizecommon for mats like PNG fro m thefirs t 512 bytes ofthe respons e and generates the pro per header.) Allow the clienttospecif yvalues like heig ht, width,and color as HT TP re questparameters. The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 SECTION 3.3. COMPLEX NUMBERS 61 3.3. ComplexNumbers Go provides two sizes ofcomplex numbers, complex64 and complex128,whose components are float32 and float64 resp ectively. The bui lt-in function complex createsacomplex num- berfro m itsrealand imaginary components, andthe bui lt-in real and imag func tions ext ract thos ecomp onents: var x complex128 = complex(1, 2) // 1+2i var y complex128 = complex(3, 4) // 3+4i fmt.Println(x*y) // "(-5+10i)" fmt.Println(real(x*y)) // "-5" fmt.Println(imag(x*y)) // "10" If a floating-p ointlit eral ordecimal integerlit eral isimmediate lyfol low edby i,suchas 3.141592i or 2i,itbecom esan im aginary lit era l,denot ing a complex numberwit h azeroreal comp onent: fmt.Println(1i * 1i) // "(-1+0i)", i$ =-1 Un der the rules for con stant arithmetic, comp lex cons tants can beadde d to other cons tants (integerorfloating point,realorimaginary), allowing ustowrite complex numbers natural ly, li ke 1+2i,orequivalently, 2i+1.The declarat ions of x and y ab ove can besimplified: x:=1+2i y:=3+4i Comp lex numbers may becompare d forequ ality with == and !=.Two complex numbers are equal if their realpar tsareequ aland their imag inar y partsare equ al. The math/cmplx packageprovides librar y func tions for wor kingwit h comp lex numbers,such as the complex squ are root and exp onent iat ionfunctions. fmt.Println(cmplx.Sqrt(-1)) // "(0+1i)" Thefol low ing program uses complex128 ar ithmetictogenerateaMandelbro t set. gopl.io/ch3/mandelbrot // Mandelbrot emits a PNG image of the Mandelbrot fractal. package main import ( "image" "image/color" "image/png" "math/cmplx" "os" ) The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 62 CHAPTER 3. BASIC DATATYPES func main() { const ( xmin, ymin, xmax, ymax = -2, -2, +2, +2 width, height =1024, 1024 ) img := image.NewRGBA(image.Rect(0, 0, width, height)) for py := 0; py < height; py++ { y:=float64(py)/height*(ymax-ymin) + ymin for px := 0; px < width; px++ { x:=float64(px)/width*(xmax-xmin) + xmin z:=complex(x, y) // Image point (px, py) represents complex value z. img.Set(px, py, mandelbrot(z)) } } png.Encode(os.Stdout, img) // NOTE: ignoring errors } func mandelbrot(z complex128) color.Color { const iterations = 200 const contrast = 15 var v complex128 for n := uint8(0); n < iterations; n++ { v=v*v + z if cmplx.Abs(v) > 2 { return color.Gray{255 - contrast*n} } } return color.Black } Thetwo neste d lo ops iterateovereachpoint ina1024&1024 grays cale rasterimage represent- ingthe −2to+2por tionofthe complex plane.The program tests whether rep eatedlysqu ar- ingand addingthe numberthatpoint representsevent ual ly ‘‘es cap es’’ thecircleofradius 2.If so,the point isshade d by the numberofiterat ions ittooktoescap e.Ifnot,the value belon gs to the Mandelbro t set, andthe point remainsblack.Final ly, the program writestoits stand ard output the PNG-enco dedimage ofthe iconic frac tal,shown inFigure3.3. Exercis e3.5: Implementafull-colorMandelbro t setusingthe function image.NewRGBA and thetyp e color.RGBA or color.YCbCr. Exercis e3.6: Su persamp lingisatechnique toreduce the effec t of pixe lat ionbycomputing the colorvalue at several pointswit hin eachpixel and tak ingthe average. The simplestmet hod is to div ide eachpixel int o four ‘‘su bpixe ls.’’ Implementit. Exercis e3.7: Anot her simplefrac tal usesNewton’smet hod tofind complex solut ion s to a func tionsuchas z4−1=0.Shade eachstartingpoint bythe numberofiterat ions required to getclos e to one ofthe fourroots. Color eachpoint bythe rootitappro ach es. The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 SECTION 3.4. BOOLEANS 63 Figure 3.3. TheMandelbro t set. Exercis e3.8: Render ingfrac talsathig h zo omlevel s demands gre atarithmeticpre cision. Implementthe samefrac tal usingfourdif ferentrepresent ation s of numbers: complex64, com- plex128, big.Float,and big.Rat.(Thelattertwo typ esarefound inthe math/big package. Float us esarbit rar y butbounded-pre cision floating-p oint; Rat us esunb ounde d-pre cision rat ionalnumbers.) How dothe y comp are inper for mance andmemor y us age?Atwhatzoom le vel s do render ingartifac ts become visible? Exercis e3.9: Wr ite a web ser ver thatrendersfrac talsand writesthe image dat a to the client. Al low the clienttospecif y the x, y,and zoomvalues as parameterstothe HTTPrequest. 3.4. Booleans Avalue oftyp e bool,or boolean,has onlytwo possiblevalues, true and false.The con di- tion s in if and for st atementsare boole ans, andcomparisonoperator s li ke == and < produce aboole an resu lt. Theunary operator ! is log ical negat ion, so !true is false,or, one mig ht say, (!true==false)==true,alt hough asamatterofsty le, wealways simplif y re dundant boole anexpressions like x==true to x. Booleanvalues can becom bine d with the && (AND) and || (OR) operator s,whichhave sh ort- circuit behavior : if the answerisalready deter mined bythe value ofthe lef t op erand, the rig ht op erandisnot evaluate d, making itsafetowrite expressions likethis: s!=""&&s[0] == 'x' where s[0] wouldpanic if applie d to anemp tystr ing . Since && hashig her pre cedence than || (mnemonic: && is boole an mu ltiplic ation, || is boole anaddition), noparenthes esarerequired for con dit ion s of thisfor m: The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 64 CHAPTER 3. BASIC DATATYPES if 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || '0' <= c && c <= '9' { // ...ASCII letter or digit... } Thereisnoimp licitconversionfro m aboole an value toa numer ic value like 0 or1,orvice vers a.It’snecessary touse anexplicit if, as in i:=0 if b { i=1 } It mig htbewor thwriting a conversionfunction if thisoperat ionwereneeded often: // btoi returns 1 if b is true and 0 if false. func btoi(b bool) int { if b { return 1 } return 0 } Theinv ers e op erat ionissosimplethatitdoesn’twar rantafunction, but for symmetr y here it is: // itob reports whether i is non-zero. func itob(i int) bool { return i != 0 } 3.5. Strings Astr ing isanimmut ablesequence ofbytes. Str ingsmay cont ain arbit rar y data,including byteswit h value 0, but usu allythe y cont ain human-readabletext. Text str ingsare convent ion- al lyint erprete d as UTF-8-enco dedsequences ofUnico de co de points (runes), whichwe’ll explore indet ailver y so on. Thebui lt-in len func tionretur nsthe numberofbytes (not runes) in a str ing , andthe in dex op erat ion s[i] retr ieves the i-t h byte ofstr ing s,where 0 ≤ i < len(s). s:="hello, world" fmt.Println(len(s)) // "12" fmt.Println(s[0], s[7]) // "104 119" ('h' and 'w') At tempt ing toaccessabyteoutside thisrange results in a panic: c:=s[len(s)] // panic: index out of range The i-t h byte ofastr ing isnot necessarily the i-t h ch ara cter of a str ing , becaus e theUTF-8 enco dingofanon-ASCII code point requires two ormorebytes. Wor kingwit h ch arac tersis discussedshortly. The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 SECTION 3.5. STRINGS 65 The substr ing op erat ion s[i:j] yields a new str ing con sisting ofthe bytes ofthe originalstr ing st artingatindex i andcontinuingupto, but not including, the byte at index j.The result cont ains j-i bytes. fmt.Println(s[0:5]) // "hello" Again, a panic results if either index isout of bound s or if j is lessthan i. Either orbot h of the i and j op erands maybeomitt ed, inwhichcas e thedefau ltvalues of 0 (t hestart ofthe str ing)and len(s) (its end) areassume d,respectively. fmt.Println(s[:5]) // "hello" fmt.Println(s[7:]) // "world" fmt.Println(s[:]) // "hello, world" The + op erator makes a new str ing bycon catenat ingtwo str ings: fmt.Println("goodbye" + s[5:]) // "goodbye, world" St rings may becompare d with comparisonoperator s li ke == and <;the comparisonisdon e byte bybyte, sothe resultisthe natural lexicographic order ing. St ringvalues areimmut able: the bytesequence cont ained inastr ing value can never be ch ange d,thoug h of cours e we can assig n anew value toastr ing variab le.Toapp end one st ringtoanother,for ins tance,wecan write s:="left foot" t:=s s+=",right foot" Thisdoesnot modif y thestr ing that s or iginallyheldbut causes s to holdthe newstr ing formed bythe += st atement;meanw hile, t st i l l cont ainsthe old str ing . fmt.Println(s) // "left foot, right foot" fmt.Println(t) // "left foot" Sincestr ingsare immut able, con str uctions thattry tomodif y astr ing’sdat a in place arenot al lowe d: s[0] = 'L' // compile error: cannot assign to s[0] Immu tabilit y me ans thatitissafefor two copies ofastr ing toshare the sameunderly ing memory,mak ingitche aptocopystr ingsofany lengt h. Simi larly,astr ing s andasubst ring li ke s[7:] maysafelyshare the samedat a, so the subst ringoperat ionisals o ch eap.Nonew memory isallocated ineit her cas e.Figure3.4 illustrates the arrangement ofastr ing and two of itssubst rings sharing the sameunderly ing bytearray. 3.5.1. String Literals Astr ing value can bewritt en as a st ring litera l,asequence ofbytes enclos ed in dou ble quotes: "Hello, BF" The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 66 CHAPTER 3. BASIC DATATYPES Figure 3.4. Thestr ing "hello, world" andtwo subst rings. Becaus e Go source files arealways enco dedinUTF-8 andGotext str ingsare convent ion ally interprete d as UTF-8, wecan include Unico deco de points in str ing lit erals. Wi thin a double-quote d st ringlit eral, es cap e sequ ences that beg in with a backslash \ canbe us edtoins ert arbit rar y byte values into the str ing . Oneset ofescap es hand les ASCII cont rol co des li kenewline, car r iageretur n,andtab: \a ‘‘aler t’’ or bel l \b backsp ace \f form feed \n ne wline \r carriageretur n \t tab \v vertic al tab \' singlequote (on ly in the runelit eral '\'') \" double quote (on lywit hin "..." literals) \\ backsl ash Arbit rar y bytescan also beinclude d in literal str ingsusinghexade cimal oroctal escapes. A hexadecimalescap e is writt en \xhh,wit h exac tly two hexade cimal digits h (in upp erorlow er case). An oc tal escap e is writt en \ooo with exac tly three octal digits o (0 through 7)not exce e ding \377.Bot h denot e asinglebytewit h thespecified value.Later,we’ll see how to enco de Unico deco de points numer ical ly in str ing lit erals. A rawstr ing litera l is writt en `...`,usingbackquotesins teadofdou ble quotes. Wit hin a raw st ringlit eral,noescap e sequences arepro cessed; the contentsare taken literal ly, including backsl ashesand newlines, soaraw str ing lit eral may spreadoverseveral lines in the program source.The onlypro cessingisthatcar r iageretur nsare deleted sothatthe value ofthe str ing is the sameonall platfor ms, includingthose thatconvent ion allyput car r iageretur nsintext files. Rawstr ing lit eralsare a convenientway towrite regu lar expressions,whichtendtohavelotsof backsl ashes. They are als o us efulfor HTMLtempl ates, JSONlit erals, commandusage mes- sages, andthe like, whichoften extendovermultiplelines. The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 SECTION 3.5. STRINGS 67 const GoUsage = `Go is a tool for managing Go source code. Usage: go command [arguments] ...` 3.5.2. Unicode Long ago,lifewas simpleand there was, at leastinaparochi al view,onlyone charac ter set to de al with:ASCII, the AmericanStand ard Codefor Infor mat ionInt erc hange . ASCII, ormore precis ely US-ASCII, uses7bitstorepresent 128 ‘‘ch arac ters’’:the upp er- and low er-case letters of Eng lish, digits, andavar ietyofpunctuation and device-cont rol charac ters. For muchofthe earlydays ofcomputing , this was adequ ate, but it lef t aver y large frac tionofthe wor ld’s popu lat ionunabletouse their own writ ing systems incomputers.Wit h thegrowt h of the Internet, dat a in myr iadlangu ages has becom e much morecommon. How can thisrichvar i- et y be dealt wit h at alland, if possible, efficiently? TheanswerisUnico de(unicode.org), whichcol lec tsall ofthe charac tersinall ofthe wor ld’s wr iting systems,plu s accents andother diacr iticalmarks, cont rol codes like tab andcar r iage return,and plenty ofesoterica,and assig nseachone a stand ard numbercal le da Un ico d eco d e point or, in Go ter minolog y,arune. Unico de version8definescodepointsfor over120,000 charac tersinwel l ov er100 langu ages andscr ipts. How are these represent edincomputerprogramsand dat a? Thenatural dat a type toholdasingleruneis int32,and that’swhatGouses; ithas the synonym rune for precis ely thispur pos e. We cou ldrepresent a sequence ofrunes as a sequence of int32 values. Inthisrepresent ation, whichiscal le dUTF-32 orUCS-4, the encodingofeachUnico deco de pointhas the samesize, 32 bits. Thisissimpleand unifor m,but it usesmuchmorespace thannecessary since most comp uter-re adabletext isinASCII, whichrequires only8bitsor1byteper charac ter.All the ch arac tersinwidespreaduse still numberfewer than65,536, whichwou ldfitin16bits. Can we dobetter? 3.5.3. UTF-8 UTF-8 isavar iable-lengt henco dingofUnico deco de points as bytes. UTF-8 was invent edby KenThompsonand Rob Pike, two ofthe cre ators ofGo, and isnow a Unico de st and ard . It us esbet ween1and 4 bytes torepresent eachrune, but only 1 bytefor ASCII charac ters, and on ly2or3bytes for mostrunes in common use.The hig h-order bitsofthe firs t byte ofthe enco dingfor a runeindic atehow manybytes fol low.Ahig h-order 0 indic ates 7-bit ASCII, whereeachrunetakes only1byte, soitisidenticaltoconvent ion alASCII. A hig h-order 110 indic ates thatthe runetakes 2 bytes; the secon d byte beg inswit h 10.Largerrunes haveanalo- gous encodings. The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 68 CHAPTER 3. BASIC DATATYPES 0xxxxxx runes0−127 (ASCII) 11xxxxx 10xxxxxx 128−2047 (values <128 unus ed) 110xxxx 10xxxxxx 10xxxxxx 2048−65535 (values <2048 unus ed) 1110xxx 10xxxxxx 10xxxxxx 10xxxxxx 65536−0x10f f f f (other values unus ed) Avar iable-lengt h enco dingpre cludes direc t indexingtoaccessthe n-t h ch arac ter ofastr ing , butUTF-8 has manydesirable pro per ties tocompens ate. The encodingiscompact,compati- blewit h ASCII, andself-sy nchro nizing: it’spossibletofind the beg inningofacharac ter by back ing upnomorethanthree bytes. It’sals o aprefixcode, soitcan bedecoded fro m lef t to rightwit houtany ambiguity orlookahead. Norune’sencodingisasubst ringofany other,or even ofa sequence ofothers, soyou can searc h forarunebyjustsearc hingfor itsbytes, withoutwor rying about the pre cedingcontext. Thelexicog raphic byteorder equ als the Uni- co deco de pointorder,sosor tingUTF-8 wor ksnatural ly. There are noemb edde d NUL (zero) bytes, whichisconvenientfor prog ramminglangu ages thatuse NUL toter minatestr ings. Go source files arealways enco dedinUTF-8, andUTF-8 isthe preferred encodingfor text st rings manipu lated byGoprograms. The unicode packageprovides functions for wor king with indiv idu alrunes (suchasdistinguishingletters fro m numb ers,orconvertinganupp er- case lettertoalow er-case one), andthe unicode/utf8 packageprovides functions for encod- ingand decodingrunes as bytes usingUTF-8. Many Unico de ch arac tersare hardtotyp e on a key board ortodistinguish visuallyfro m sim- ilar-lo oking ones; som e areeveninv isible. Unico de es cap es in Gostr ing lit eralsallow usto sp ecif y them bytheir numer ic co de pointvalue.There are two for ms, \uhhhh fora16-bit value and \Uhhhhhhhh fora32-bit value,where each h is a hexade cimal digit;the need for the 32-bit for m ar isesver y inf requently. Eachdenot esthe UTF-8 enco dingofthe specified code point. Thus,for example, the fol low ing str ing lit eralsall represent the samesix-bytestr ing: "BF" "\xe4\xb8\x96\xe7\x95\x8c" "\u4e16\u754c" "\U00004e16\U0000754c" Thethree escap e sequences abov e prov ide alternat ive not ation s forthe firs t st ring, but the val- ues the y denot e areidentical. Unico de es cap es mayals o be used in runelit erals. Thes e thre e literalsare equivalent: 'B''\u4e16''\U00004e16' Arunewhose value islessthan256 may bewritt enwit h asinglehexade cimal escape,suchas '\x41' for 'A',but for hig her values, a \u or \U es cap e mu stbeused. Con sequently, '\xe4\xb8\x96' is not a legal runelit eral,eventhoug h thos e thre e bytesare a valid UTF-8 enco dingofasinglecodepoint. Than ks to the nice pro per ties ofUTF-8, manystr ing operat ions don’trequiredecoding. We cantestwhether one str ing containsanother as a prefix: The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 SECTION 3.5. STRINGS 69 func HasPrefix(s, prefix string) bool { return len(s) >= len(prefix) && s[:len(prefix)] == prefix } or asasuffix: func HasSuffix(s, suffix string) bool { return len(s) >= len(suffix) && s[len(s)-len(suffix):] == suffix } or asasubst ring: func Contains(s, substr string) bool { for i := 0; i < len(s); i++ { if HasPrefix(s[i:], substr) { return true } } return false } usingthe samelog ic forUTF-8-enco dedtext as for raw bytes. Thisisnot truefor other enco dings. (Thefunctions above are draw n from the strings package, thoug h itsimp lemen- tation of Contains us esahashingtechnique tosearc h more efficiently.) On the other hand, ifwereallycareabout the indiv idu alUnico de ch arac ters, wehavetouse ot her mechanisms. Con sider the str ing fro m ourver y firs t example, whichincludes two East Asiancharac ters. Figure3.5 illustrates its represent ation inmemor y.The str ing contains13 bytes, but int erprete d as UTF-8, itencodes onlyninecodepointsorrunes: import "unicode/utf8" s:="Hello, BF" fmt.Println(len(s)) // "13" fmt.Println(utf8.RuneCountInString(s)) // "9" To pro cessthose charac ters, weneed a UTF-8 deco der.The unicode/utf8 packageprovides on e that wecan use likethis: for i := 0; i < len(s); { r, size := utf8.DecodeRuneInString(s[i:]) fmt.Printf("%d\t%c\n", i, r) i+=size } Each cal l to DecodeRuneInString returns r,the runeits elf,and size,the numberofbytes occupied bythe UTF-8 enco dingof r.The size isusedtoupdatethe byteindex i of the next rune inthe str ing . Butthisisclumsy, and weneed loops ofthiskindall the time. For tunately, Go’s range lo op, whenapp lie d to a str ing , perfor msUTF-8 deco dingimp licitly. The out put of theloopbelow isals o shown inFigure3.5; not ice how the index jumps bymorethan1for each non-ASCII rune. The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 70 CHAPTER 3. BASIC DATATYPES Figure 3.5. A range lo opdecodes a UTF-8-enco dedstr ing . for i, r := range "Hello, BF"{ fmt.Printf("%d\t%q\t%d\n", i, r, r) } We cou lduse a simple range lo optocount the numberofrunes in a str ing , li kethis: n:=0 for _, _ = range s { n++ } As wit h theother for msof range lo op, wecan omitthe var iables wedon’tneed: n:=0 for range s { n++ } Or wecan justcal l utf8.RuneCountInString(s). We mention edearlier thatitismostlyamatterofconvent ion inGothattext str ingsare int er- preted asUTF-8-enco dedsequences ofUnico de co de points, but for cor rec t us e of range lo ops onstr ings, it’smorethanaconvent ion,it’sanecessity.Whathappens ifwerange overa st ringcontainingarbit rar y binary dat a or,for thatmatter, UTF-8 dat acont ainingerror s? Each timeaUTF-8 deco der,whether explicitinacal l to utf8.DecodeRuneInString or implicitinarange lo op, con sumes an unexp ected inp utbyte, itgenerates a speci al Unico de re placement chara cter, '\uFFFD',whichisusu allyprint edasawhite question markinside a bl ack hexagon alordiamond-li keshape (.Whenaprogram encounters thisrunevalue,it’s of ten a signthatsom e upst reampar t of the systemthatgenerated the str ing dat a hasbeen The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 SECTION 3.5. STRINGS 71 care lessinits tre atmentoftext enco dings. UTF-8 isexception allyconvenient as an int erc hange for mat but wit hin a program runes may be moreconvenientbecause the y areofunifor m size andare thu s easi lyindexed inarrays and slices. A []rune conv ersionapp lie d to a UTF-8-enco dedstr ing retur nsthe sequence ofUnico de co de points thatthe str ing encodes: // "program" in Japanese katakana s:=">+=@?" fmt.Printf("% x\n", s) // "e3 83 97 e3 83 ad e3 82 b0 e3 83 a9 e3 83 a0" r:=[]rune(s) fmt.Printf("%x\n", r) // "[30d7 30ed 30b0 30e9 30e0]" (Theverb %xin the firs t Printf insertsaspace bet weeneachpair ofhex digits.) If a slice ofrunes isconverted toastr ing , it produces the con catenat ionofthe UTF-8 enco d- ings ofeachrune: fmt.Println(string(r)) // ">+=@?" Conv ertinganint egervalue toastr ing int erprets the int egerasarunevalue,and yieldsthe UTF-8 represent ation of thatrune: fmt.Println(string(65)) // "A", not "65" fmt.Println(string(0x4eac)) // "C" If the runeisinvalid,the replacementcharac ter issubst itute d: fmt.Println(string(1234567)) // "(" 3.5.4. Strings and ByteSlices Fo urstand ard packages arepar tic ularlyimp ortantfor manipu lat ingstr ings: bytes, strings, strconv,and unicode.The strings packageprovides manyfunctions for searc hing, replac- ing, comparing , tr imming, split ting, and joiningstr ings. The bytes packagehas similarfunctions for manipu lat ingslices ofbytes, oftyp e []byte, whichshare som e prop erties wit h st rings. Because str ingsare immut able, bui ldingupstr ings incrementallycan invo l ve alot ofallocat ionand copying . In suchcas es, it’smoreefficientto us e the bytes.Buffer type,whichwe’ll show in a mom ent. The strconv packageprovides functions for convertingboole an, integer, and floating-p oint values toand fro m their str ing represent ation s,and functions for quoting and unquoting st rings. The unicode packageprovides functions like IsDigit, IsLetter, IsUpper,and IsLower for cl assif yingrunes. Eachfunctiontakes a singleruneargumentand retur nsaboole an. Conv er- sionfunctions like ToUpper and ToLower conv ert a rune int o thegiven cas e if itisaletter. All thes e func tions use the Unico de st and ard categor ies for letters,dig its, andsoon. The strings The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 72 CHAPTER 3. BASIC DATATYPES packagehas similarfunctions,als o called ToUpper and ToLower,thatretur n anew str ing wit h thespecified transfor mat ionapp lie d to eachcharac ter ofthe originalstr ing . The basename func tionbelow was inspired bythe Unix shel l ut i lit y of the samename. Inour version, basename(s) removesany prefixof s that lookslikeafile systempat h with com- ponentssep arated byslashes, anditremov esany suffixthatlooks like a file typ e: fmt.Println(basename("a/b/c.go")) // "c" fmt.Println(basename("c.d.go")) // "c.d" fmt.Println(basename("abc")) // "abc" The firs t versionof basename do es al l thewor k withoutthe helpoflibrar ies: gopl.io/ch3/basename1 // basename removes directory components and a .suffix. // e.g., a => a, a.go => a, a/b/c.go => c, a/b.c.go => b.c func basename(s string) string { // Discard last '/' and everything before. for i := len(s) - 1; i >= 0; i-- { if s[i] == '/' { s=s[i+1:] break } } // Preserve everything before last '.'. for i := len(s) - 1; i >= 0; i-- { if s[i] == '.' { s=s[:i] break } } return s } Asimpler versionusesthe strings.LastIndex librar y func tion: gopl.io/ch3/basename2 func basename(s string) string { slash := strings.LastIndex(s, "/") // -1 if "/" not found s=s[slash+1:] if dot := strings.LastIndex(s, "."); dot >= 0 { s=s[:dot] } return s } The path and path/filepath packages provide a moregeneral set offunctions for manip- ulat inghierarchic al names. The path packagewor kswit h sl ash-delimite d pathsonany plat- form.Itshouldn’tbeusedfor file names, but it isappro priatefor other domains, like the pat h comp onent ofaURL. Bycontrast, path/filepath manipu lates file names usingthe rules for thehostplatfor m,suchas /foo/bar forPOSIX or c:\foo\bar on Micros oft Windows. The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 SECTION 3.5. STRINGS 73 Let’scontinuewit h anot her subst ringexample. The taskistotakeastr ing represent ation of an integer, suchas "12345",and ins ert commasevery three places, as in "12,345".Thisversion on lywor ksfor int egers;handling floating-p ointnumbers islef t as a exercise. gopl.io/ch3/comma // comma inserts commas in a non-negative decimal integer string. func comma(s string) string { n:=len(s) if n <= 3 { return s } return comma(s[:n-3]) + "," + s[n-3:] } Theargumentto comma is a str ing . If its lengt h is lessthanorequ alto3,nocomma is neces- sary.Other wis e, comma callsits elf rec ursivelywit h asubst ringcon sisting ofall but the last thre e ch arac ters, andapp end s acomma and the lastthree charac terstothe resultofthe rec ur- sive cal l. Astr ing containsanarray ofbytes that, oncecre ate d, is immut able. Bycontrast, the elements of a byteslice can befre ely modified. St rings can beconverted tobyteslices andbackagain: s:="abc" b:=[]byte(s) s2 := string(b) Conceptu ally, the []byte(s) conv ersionallocates a new bytearray holdingacopyofthe bytes of s,and yieldsaslice thatreferences the ent irety ofthatarray.Anopt imizingcompi ler may be abletoavoid the allocat ionand copying insom e cases, but ingeneral copy ing isrequired to ensure thatthe bytes of s remain unch ange d even if those of b aresubsequentlymodified.The conv ersionfro m byte slice backtostr ing wit h string(b) also makes a copy,toens ure immut abi lit y of the resulting str ing s2. To avoid conv ersions and unnecessary memor y al location,manyofthe utilit y func tions inthe bytes packagedirec tly paral leltheir counterpar ts in the strings package. For example, here arehalf a dozen functions fro m strings: func Contains(s, substr string) bool func Count(s, sep string) int func Fields(s string) []string func HasPrefix(s, prefix string) bool func Index(s, sep string) int func Join(a []string, sep string) string andthe cor respondingonesfro m bytes: The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 74 CHAPTER 3. BASIC DATATYPES func Contains(b, subslice []byte) bool func Count(s, sep []byte) int func Fields(s []byte) [][]byte func HasPrefix(s, prefix []byte) bool func Index(s, sep []byte) int func Join(s [][]byte, sep []byte) []byte Theonlydif ference isthatstr ingshavebeenreplace d by byte slices. The bytes packageprovides the Buffer type for efficientmanipu lat ionofbyteslices. A Buffer st artsout emp tybut grows as dat a of typ es li ke string, byte,and []byte arewritt en to it. Asthe examplebelow shows, a bytes.Buffer var iable requires noinitializat ionbecause itszerovalue isusable: gopl.io/ch3/printints // intsToString is like fmt.Sprintf(values) but adds commas. func intsToString(values []int) string { var buf bytes.Buffer buf.WriteByte('[') for i, v := range values { if i > 0 { buf.WriteString(", ") } fmt.Fprintf(&buf, "%d", v) } buf.WriteByte(']') return buf.String() } func main() { fmt.Println(intsToString([]int{1, 2, 3})) // "[1, 2, 3]" } Wh enapp endingthe UTF-8 enco dingofanarbit rar y rune toabytes.Buffer,it’sbesttouse bytes.Buffer’s WriteRune method,but WriteByte is fine for ASCII charac terssuchas '[' and ']'. The bytes.Buffer type isext remelyversatile, and whenwedis cussint erfaces in Chapt er7, we’ll see how itmay beusedasareplacementfor a file whene ver an I/O functionrequires a sin k forbytes (io.Writer)as Fprintf do esab ove , or a sourceofbytes (io.Reader). Exercis e3.10: Wr ite a non-rec ursiveversionof comma,using bytes.Buffer insteadofstr ing conc atenation. Exercis e3.11: En hance comma so thatitdeals cor rec tly wit h floating-p ointnumbers and an opt ion alsig n. Exercis e3.12: Wr ite a functionthatrep ortswhether two str ingsare anagramsofeachother, that is, the y cont ain the sameletters inadif ferentorder. The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 SECTION 3.6. CONSTANTS75 3.5.5. Conversions between Strings and Numbers In addition toconversions bet weenstr ings, runes, andbytes, it’soften necessary toconvert betweennumer icvalues andtheir str ing represent ation s.Thisisdon e with func tions fro m the strconv package. To convert anint egertoastr ing , on e opt ion istouse fmt.Sprintf;another istouse the func- tion strconv.Itoa (‘‘integertoASCII’’): x:=123 y:=fmt.Sprintf("%d", x) fmt.Println(y, strconv.Itoa(x)) // "123 123" FormatInt and FormatUint canbeusedtofor mat numbers inadif ferentbas e: fmt.Println(strconv.FormatInt(int64(x), 2)) // "1111011" The fmt.Printf verbs %b, %d, %u,and %x areoften moreconvenientthan Format func tions, especi ally ifwewanttoinclude addition alinfor mat ionbesides the number: s:=fmt.Sprintf("x=%b", x) // "x=1111011" To parse a str ing represent ing anint eger, use the strconv func tions Atoi or ParseInt,or ParseUint forunsig ned int egers: x, err := strconv.Atoi("123") // x is an int y, err := strconv.ParseInt("123", 10, 64) // base 10, up to 64 bits Thethirdargumentof ParseInt givesthe size ofthe int egertyp e that the resultmustfitint o; forexample, 16imp lies int16,and the speci alvalue of0imp lies int.Inany cas e,the typ e of theresult y is always int64,whichyou can thenconvert toasmaller typ e. Sometimes fmt.Scanf is usef ulfor parsinginp utthatcon sists oforderly mixtures ofstr ings andnumbers all onasingleline, but it can beinflexible, esp eci ally whenhandlingincomplete or irregu lar input. 3.6. Constants Cons tants areexpressions whose value isknown tothe compi ler andwhose evaluation isguar- ante e d to occ ur at comp ile time, not atrun time. The underly ing typ e of every con stant isa basic typ e: boole an, st ring, ornumber. A const de clarat iondefinesnamed values thatlooksyntactic ally likevar iables but whose value iscon stant,whichpre vents accidental(or nefar ious)changesdur ingprogram exec ution. Fo r inst ance, a con stant ismoreappro priatethanavar iable for a mat hemat ical cons tantlike pi,since its value won’tchange: const pi = 3.14159 // approximately; math.Pi is a better approximation As wit h var iables, a sequence ofcon stantscan appear in one declarat ion; thiswou ldbe appropriatefor a gro upofrel ate d values: The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 76 CHAPTER 3. BASIC DATATYPES const ( e=2.71828182845904523536028747135266249775724709369995957496696763 pi = 3.14159265358979323846264338327950288419716939937510582097494459 ) Many computation s on con stantscan becompletelyevaluate d at comp ile time, reducingthe work necessary atrun timeand enablingother comp iler opt imizat ions.Error s ordinar ily detec ted atrun timecan berep orted atcompi letimewhentheir operands are con stants, such as integerdiv isionbyzero, str ing indexingout of bound s,and any floating-p ointoperat ion that wou ldresult in a non-finite value. Theresults ofall arithmetic, logic al,and comparisonoperat ions app lie d to con stant operands arethems elves cons tants, as arethe results ofconversions and cal lstocer tain bui lt-in func- tion s such as len, cap, real, imag, complex,and unsafe.Sizeof (§13.1). Sincetheir values areknown tothe compi ler,con stant expressions may appear in typ es, sp ecif- ic ally asthe lengt h of anarray typ e: const IPv4Len = 4 // parseIPv4 parses an IPv4 address (d.d.d.d). func parseIPv4(s string) IP { var p [IPv4Len]byte // ... } Acon stant declarat ionmay specif y atyp e as wel l as a value,but inthe abs ence ofanexplicit type,the typ e is infer red fro m theexpressiononthe rig ht-handside.Inthe fol low ing , time.Duration is a name d type whose underly ing typ e is int64,and time.Minute is a con- st ant ofthattyp e.Bot h of the con stantsdeclare d belowthu s have the typ e time.Duration as we ll, asreveale d by %T: const noDelay time.Duration = 0 const timeout = 5 * time.Minute fmt.Printf("%T %[1]v\n", noDelay) // "time.Duration 0" fmt.Printf("%T %[1]v\n", timeout) // "time.Duration 5m0s fmt.Printf("%T %[1]v\n", time.Minute) // "time.Duration 1m0s" Wh enasequence ofcon stantsisdeclare d as a gro up, the rig ht-handside expressionmay be omit ted for all but the firs t of the gro up, imp l yingthatthe pre vious expressionand its typ e shouldbeusedagain. For example: const ( a=1 b c=2 d ) fmt.Println(a, b, c, d) // "1 1 2 2" The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 SECTION 3.6. CONSTANTS77 Thisisnot ver y us efulifthe imp licitlycopie d right-handside expressionalways evaluatesto thesamething. But what if it cou ldvar y? Thisbringsusto iota. 3.6.1. The ConstantGenerator iota A const de clarat ionmay use the constant generat o r iota,whichisusedtocre ate a sequence of rel ate d values wit houtspellingout eachone explicitly. Inaconst de clarat ion, the value of iota begins atzeroand incrementsbyone for eachitem in the sequence. Here’sanexamplefro m the time package, whichdefinesnamed con stantsoftyp e Weekday for thedays ofthe week, startingwit h zerofor Sunday.Typ es of thiskindare often cal le d enu- merati ons,or enums forshort. type Weekday int const ( Sunday Weekday = iota Monday Tuesday Wednesday Thursday Friday Saturday ) Thisdeclares Sunday to be0, Monday to be 1, and soon. We can use iota in morecomplex expressions too,asinthisexamplefro m the net package whereeachofthe low est 5 bitsofanunsig ned int egerisgiven a dist inc t name and boole an interpretation: type Flags uint const ( FlagUp Flags = 1 << iota // is up FlagBroadcast // supports broadcast access capability FlagLoopback // is a loopback interface FlagPointToPoint // belongs to a point-to-point link FlagMulticast // supports multicast access capability ) As iota increments, eachcon stant isassig ned the value of 1< float64 f=2 // untyped integer -> float64 f=1e123 // untyped floating-point -> float64 f='a' // untyped rune -> float64 Thestatementsabove are thu s equivalenttothese: var f float64 = float64(3 + 0i) f=float64(2) f=float64(1e123) f=float64('a') Wh ether implicitorexplicit, conv ertingacon stant fro m on e type toanother requires thatthe targettyp e canrepresent the originalvalue.Roundingisallow edfor realand complex float- ing-p ointnumbers: The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 80 CHAPTER 3. BASIC DATATYPES const ( deadbeef = 0xdeadbeef // untyped int with value 3735928559 a=uint32(deadbeef) // uint32 with value 3735928559 b=float32(deadbeef) // float32 with value 3735928576 (rounded up) c=float64(deadbeef) // float64 with value 3735928559 (exact) d=int32(deadbeef) // compile error: constant overflows int32 e=float64(1e309) // compile error: constant overflows float64 f=uint(-1) // compile error: constant underflows uint ) In a var iable decl arat ionwit hout an explicittyp e (includingshort var iable decl arat ions), the flavor of the unt ypedcon stant imp licitlydeter mines the defau lttyp e of the var iable,asinthese examples: i:=0 //untyped integer; implicit int(0) r:='\000'// untyped rune; implicit rune('\000') f:=0.0 // untyped floating-point; implicit float64(0.0) c:=0i//untyped complex; implicit complex128(0i) No tethe asy mmet ry: unt ypedint egers are converted to int,whose size isnot guarante e d, but untypedfloating-p ointand complex numbers are converted tothe explicitlysize d types float64 and complex128.The langu agehas nounsize d float and complex typesanalogou s to unsize d int,because itisver y difficult towrite cor rec t numericalalgor it hms wit hout know ing the size ofone’sfloating-p ointdat a types. To givethe var iable a different typ e,wemustexplicitlyconvert the unt ypedcon stant tothe desired typ e or state the desired typ e in the var iable decl arat ion, as in these examples: var i = int8(0) var i int8 = 0 Thes e defau lts arepar tic ularlyimp ortantwhenconvertinganunt ypedcon stant toanint erface value (see Chapter 7) since the y deter mineits dynamic typ e. fmt.Printf("%T\n", 0) // "int" fmt.Printf("%T\n", 0.0) // "float64" fmt.Printf("%T\n", 0i) // "complex128" fmt.Printf("%T\n", '\000')//"int32" (rune) We’ve now cov ere d thebasic dat a typesofGo. The next stepistoshowhow the y canbecom- bine d into largergro upingslikearrays andstr ucts, andthenint o data str uctures for solv ing re alprogrammingpro blems; thatisthe topic ofChapt er4. The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 4 CompositeTypes In Chapt er3 wedis cussedthe basic typ es that ser veasbui ldingblo cks for dat a st ruc tures in a Go program; the y arethe atoms ofour univers e. In thischapt er, we’ll takealookat comp osite types, the mole cules create d by com biningthe basic typ es in various ways. We’ll tal k ab out four suchtyp es—ar rays, slices, maps, andstr ucts—andatthe end ofthe chapt er, we’ll show howstr uctured dat a usingthese typ es canbeencoded asand parsedfro m JSONdat aandused to generateHTMLfro m temp lates. Ar rays andstr uctsare ag gre gat e types; their values arecon catenat ions ofother values in mem- or y.Arrays arehom ogene ous—their elements allhavethe sametyp e—whereasstr uctsare heterogene ous.Bot h ar rays andstr uctsare fixe d size.Incontrast, slices andmaps are dy namic dat a st ruc tures thatgrow as values areadde d. 4.1. Arrays An array isafixe d-lengt h sequence ofzeroormoreelements ofapar tic ulartyp e.Because of their fixe d lengt h,ar raysarerarelyuseddirec tly inGo. Slices, whichcan growand shrink,are much moreversatile, but tounderst and slices wemustunderst and arrays firs t. In div idu alarray elements areaccessedwit h theconvent ion alsubscript not ation,where su bscriptsrun fro m zerotoone lessthanthe array lengt h. Thebui lt-in function len returns thenumberofelements in the array. var a [3]int // array of 3 integers fmt.Println(a[0]) // print the first element fmt.Println(a[len(a)-1]) // print the last element, a[2] 81 The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 82 CHAPTER 4. COMPOSITE TYPES // Print the indices and elements. for i, v := range a { fmt.Printf("%d %d\n", i, v) } // Print the elements only. for _, v := range a { fmt.Printf("%d\n", v) } By defau lt, the elements ofanew array variableare initial lyset tothe zerovalue for the ele- ment typ e,whichis 0 fornumbers.Wecan use an ar ray lit era l to initialize an array wit h alist of values: var q [3]int = [3]int{1, 2, 3} var r [3]int = [3]int{1, 2} fmt.Println(r[2]) // "0" In anarray literal,ifanellipsis ‘‘...’’ appearsinplace ofthe lengt h, thearray lengt h is deter- mined bythe numberofinitializers. Thedefinition of q canbesimplified to q:=[...]int{1, 2, 3} fmt.Printf("%T\n", q) // "[3]int" Thesize of an array ispar t of itstyp e,so [3]int and [4]int aredif ferenttyp es. Thesize mu stbeacon stant expression, thatis, an expressionwhose value can becompute d as the prog ram is beingcompi led. q:=[3]int{1, 2, 3} q=[4]int{1, 2, 3, 4} // compile error: cannot assign [4]int to [3]int As we’ll see,the lit eral synt axissimi lar for arrays, slices, maps, andstr ucts. Thespecificfor m ab ove isalistofvalues in order,but it isals o possible tospecif y alistofindex andvalue pairs, li kethis: type Currency int const ( USD Currency = iota EUR GBP RMB ) symbol := [...]string{USD: "$", EUR: "9", GBP: "!", RMB: """} fmt.Println(RMB, symbol[RMB]) // "3 "" In thisfor m,indices can appear in anyorder andsom e maybeomitt ed; as before, uns pecified values takeonthe zerovalue for the elementtyp e.For ins tance, r:=[...]int{99: -1} defines an array r with 100 elements, allzeroexceptfor the last, whichhas value −1. The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 SECTION 4.1. ARRAYS83 If anarray’selementtyp e is comp arab le then the array typ e is comparable too,sowemay direc tly compare two arrays ofthattyp e usingthe == op erator,whichrep ortswhether allcor- resp ondingelements areequ al. The != op erator isits negat ion. a:=[2]int{1, 2} b:=[...]int{1, 2} c:=[2]int{1, 3} fmt.Println(a == b, a == c, b == c) // "true false false" d:=[3]int{1, 2} fmt.Println(a == d) // compile error: cannot compare [2]int == [3]int As a moreplausible example, the function Sum256 in the crypto/sha256 packagepro duces theSHA256 cryptographic hashor di gest of a message store d in an arbit rar y byte slice.The digesthas 256 bits, soits typ e is [32]byte.Iftwo digests arethe same, itisext remelylikely that the two messagesare the same; if the digests differ, the two messagesare dif ferent. This prog ram pr intsand comparesthe SHA256 digests of "x" and "X": gopl.io/ch4/sha256 import "crypto/sha256" func main() { c1 := sha256.Sum256([]byte("x")) c2 := sha256.Sum256([]byte("X")) fmt.Printf("%x\n%x\n%t\n%T\n", c1, c2, c1 == c2, c1) // Output: // 2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881 // 4b68ab3847feda7d6c62c1fbcbeebfa35eab7351ed5e78f4ddadea5df64b8015 // false // [32]uint8 } Thetwo inp uts differbyonlyasinglebit,but approximatelyhalf the bitsare dif ferentinthe digests. Not ice the Printf verbs: %x to print all the elements ofanarray orslice ofbytes in hexade cimal, %t to showaboole an,and %T to displ aythe typ e of a value. Wh enafunctioniscal le d,acopyofeachargumentvalue isassig ned tothe cor responding parameter variable, sothe functionreceivesacopy, not the original. Passinglarge arrays in this way can beinefficient, andany changesthatthe functionmakes toarray elements affe ct on lythe copy, not the original. Inthisregard, Gotre ats arrays like any other typ e,but this behavior isdif ferentfro m languagesthatimp licitlypassarrays by reference. Of course,wecan explicitlypassapoint ertoanarray sothatany modification s thefunction makestoarray elements will bevisible tothe cal ler.Thisfunctionzeroesthe contentsofa [32]byte ar ray: func zero(ptr *[32]byte) { for i := range ptr { ptr[i] = 0 } } The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 84 CHAPTER 4. COMPOSITE TYPES Thearray literal [32]byte{} yields anarray of32bytes. Eachelementofthe array has the zerovalue for byte,whichiszero. Wecan use thatfac t to write a dif ferentversionof zero: func zero(ptr *[32]byte) { *ptr = [32]byte{} } Usingapoint ertoanarray isefficientand allowsthe cal le d func tiontomut ate the cal ler’s var iable,but arrays arestill inherentlyinflexiblebecause oftheir fixe d size.The zero func tion wi l l notacceptapoint ertoa[16]byte var iable,for example, nor isthere any way toadd or remove array elements. For these reasons,other thanspeci al caseslikeSHA256’sfixe d-size hash,arrays areseldomused as functionparameters; instead, weuse slices. Exercis e4.1: Wr ite a functionthatcountsthe numberofbitsthatare dif ferent in two SHA256 hashes. (See PopCount from Sec tion 2.6.2.) Exercis e4.2: Wr ite a program thatprintsthe SHA256 hashofits stand ard inp utbydefau ltbut supp ortsacommand-line flag toprint the SHA384 orSHA512 hashins tead. 4.2. Slices Slices represent var iable-lengt h sequences whose elements allhavethe sametyp e.Aslice typ e is writt en []T,where the elements havetyp e T;itlooks like anarray typ e withoutasize. Ar rays andslices areint imate lyconne cte d. Aslice isalig htweig htdat a st ruc turethatgives accesstoasubsequence (orperhaps all) ofthe elements ofanarray,whichisknown asthe slice’s un derly ing array.Aslice has three components: a point er, a lengt h,andacap acity.The pointerpointstothe firs t elementofthe array thatisreach ablethrough the slice,whichisnot ne cessarily the array’sfirs t element. Thelengt h is the numberofslice elements; itcan’texceed thecap acity,whichisusu allythe numberofelements bet weenthe start ofthe slice andthe end of the underly ing array.The bui lt-in functions len and cap return thos evalues. Mu ltipleslices can share the sameunderly ing array andmay refer tooverl appingpar ts of that ar ray.Figure4.1 shows an array ofstr ingsfor the mont hsofthe year, and two overl apping slices ofit. Thearray isdeclare d as months := [...]string{1: "January", /* ... */, 12: "December"} so January is months[1] andDecemberis months[12].Ordinar ily,the array elementatindex 0wou ldcontain the firs t value,but because monthsare always numbere d from 1,wecan leave it out of the declarat ionand itwill beinitialize d to anemp tystr ing . The sli ceoperator s[i:j],where 0 ≤ i ≤ j ≤ cap(s),cre atesanew slice thatreferstoelements i thro ugh j-1 of the sequence s,whichmay beanarray variable, a point erto an array,or anot her slice.The resulting slice has j-i elements. If i is omitt ed, it’s0,and if j is omitt ed, it’s len(s).Thu s theslice months[1:13] refers to the whole range ofvalid months, as does the slice months[1:];the slice months[:] refers to the whole array.Let’sdefine overl appingslices forthe secon d qu arter andthe northern summer : The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 SECTION 4.2. SLICES 85 Figure 4.1. Tw o ov erl appingslices ofanarray ofmonths. Q2 := months[4:7] summer := months[6:9] fmt.Println(Q2) // ["April" "May" "June"] fmt.Println(summer) // ["June" "July" "August"] June isinclude d in eachand isthe soleout put of this(inefficient) testfor commonelements: for _, s := range summer { for _, q := range Q2 { if s == q { fmt.Printf("%s appears in both\n", s) } } } The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 86 CHAPTER 4. COMPOSITE TYPES Slicingbeyon d cap(s) caus esapanic, but slicingbeyon d len(s) extends the slice,sothe resu ltmay belon g erthanthe original: fmt.Println(summer[:20]) // panic: out of range endlessSummer := summer[:5] // extend a slice (within capacity) fmt.Println(endlessSummer) // "[June July August September October]" As anaside,not e thesimi lar ity ofthe subst ringoperat iononstr ingstothe slice operator on []byte slices. Bot h arewritt en x[m:n],and bot h return a subsequence ofthe originalbytes, sh aring the underly ing represent ation sothatbot h op erat ions takecon stant time. The expres- sion x[m:n] yields a str ing if x is a str ing , or a []byte if x is a []byte. Sinceaslice cont ainsapoint ertoanelementofanarray,passingaslice toafunctionper mits thefunctiontomodif y theunderly ing array elements. Inother words,copying a slice creates an alias (§2.3.2) for the underly ing array.The function reverse re versesthe elements ofan []int slice in place,and itmay beapp lie d to slices ofany lengt h. gopl.io/ch4/rev // reverse reverses a slice of ints in place. func reverse(s []int) { for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 { s[i], s[j] = s[j], s[i] } } Here wereverse the whole array a: a:=[...]int{0, 1, 2, 3, 4, 5} reverse(a[:]) fmt.Println(a) // "[5 4 3 2 1 0]" Asimpleway to ro tat e aslice leftby n elements istoapp l y the reverse func tionthree times, firs t to the leading n elements, thentothe remainingelements, and finallytothe whole slice. (Torot ate to the rig ht, makethe thirdcal lfirs t.) s:=[]int{0, 1, 2, 3, 4, 5} // Rotate s left by two positions. reverse(s[:2]) reverse(s[2:]) reverse(s) fmt.Println(s) // "[2 3 4 5 0 1]" No tice how the expressionthatinitializes the slice s dif fersfro m that for the array a.Asli ce litera l lo oks like anarray literal,asequence ofvalues sep arated bycommasand sur rounded by braces, but the size isnot given. Thisimp licitlycre atesanarray variableofthe rig htsize and yields a slice thatpointstoit. Aswit h ar ray literals, slice literalsmay specif y thevalues in order,orgivetheir indices explicitly, oruse a mix ofthe two sty les. Un likearrays, slices arenot comparable,sowecannot use == to test whether two slices cont ain thesameelements. Thestand ard librar y prov ides the hig hly opt imize d bytes.Equal func tion forcomparing two slices ofbytes ([]byte), but for other typ es of slice,wemustdothe The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 SECTION 4.2. SLICES 87 comp arisonourselves: func equal(x, y []string) bool { if len(x) != len(y) { return false } for i := range x { if x[i] != y[i] { return false } } return true } Gi venhow natural this ‘‘de ep’’ equality testis, andthatitisnomorecostlyatrun timethanthe == op erator for arrays ofstr ings, itmay bepuzzlingthatslice comp arisons donot als o work this way.There are two reasons why deepequivalence ispro blemat ic. First,unlikearray ele- ments, the elements ofaslice areindirec t,mak ingitpossiblefor a slice tocontain its elf. Although there are ways todealwit h such cas es, none issimple, efficient, andmost importantly, obv iou s. Second,because slice elements areindirec t,afixe d slice value may cont ain different elements at different times as the contentsofthe underly ing array aremodified.Because a hashtable such asGo’smap typ e makesonlyshallow copies ofits keys, itrequires thatequ ality for each ke y remain the samethroughoutthe lifet imeofthe hashtable.Deepequivalence wou ldthu s make slices unsuit ablefor use asmap keys. For reference typ es li kepoint ers and channel s,the == op erator tests reference ident ity,thatis, whether the two ent ities refer tothe samething. An analogou s ‘‘sh allow’’ equality testfor slices couldbeuseful, and itwou ldsolvethe pro blem with maps, but the incon sistent tre atmentofslices andarrays bythe == op erator wou ldbe conf using. The safestchoice istodis allow slice comp arisons alt ogether. Theonlylegal slice comp arisonisagainst nil, as in if summer == nil { /* ... */ } Thezerovalue ofaslice typ e is nil.Ani l slice has nounderly ing array.The nil slice has lengt handcap acity zero, but there are als o non-ni l slices oflengt handcap acity zero, suchas []int{} or make([]int, 3)[3:].Aswit h anytyp e that can havenil values, the nil value ofa partic ularslice typ e canbewritt enusingaconversionexpressionsuchas []int(nil). var s []int // len(s) == 0, s == nil s=nil // len(s) == 0, s == nil s=[]int(nil) // len(s) == 0, s == nil s=[]int{} // len(s) == 0, s != nil So,ifyou need totestwhether a slice isemp ty, use len(s) == 0,not s==nil.Other than comp aring equ alto nil,anil slice beh aveslikeany other zero-lengt h slice; reverse(nil) is perfec tly safe, for example. Unlesscle arly documente d to the contrar y,Gofunctions should treatall zero-lengt h slices the sameway,whether nilornon-ni l. The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 88 CHAPTER 4. COMPOSITE TYPES Thebui lt-in function make createsaslice ofaspecified elementtyp e,lengt h,andcap acity.The capacity argumentmay beomitt ed, inwhichcas e thecap acity equ als the lengt h. make([]T, len) make([]T, len, cap) // same as make([]T, cap)[:len] Un der the hood, make createsanunnamed array variableand retur nsaslice ofit; the array is accessibleonlythrough the retur ned slice.Inthe firs t form,the slice isavie w of the ent ire ar ray.Inthe secon d,the slice isavie w of only the array’sfirs t len elements, but itscap acity includes the ent ire array.The addition alelements areset aside for fut ure growt h. 4.2.1. The append Function Thebui lt-in append func tionapp end s it ems toslices: var runes []rune for _, r := range "Hello, BF"{ runes = append(runes, r) } fmt.Printf("%q\n", runes) // "['H''e''l''l''o'',''''B''F']" Theloopuses append to bui ld theslice ofninerunes enco dedbythe str ing lit eral,alt hough this specificpro blem ismoreconvenientlysolved byusingthe bui lt-in conv ersion []rune("Hello, BF"). The append func tioniscruci al to underst andinghow slices wor k,solet’stakealookatwhatis goingon. Here’saversioncal le d appendInt that isspeci alizedfor []int slices: gopl.io/ch4/append func appendInt(x []int, y int) []int { var z []int zlen := len(x) + 1 if zlen <= cap(x) { // There is room to grow. Extend the slice. z=x[:zlen] }else { // There is insufficient space. Allocate a new array. // Grow by doubling, for amortized linear complexity. zcap := zlen if zcap < 2*len(x) { zcap = 2 * len(x) } z=make([]int, zlen, zcap) copy(z, x) // a built-in function; see text } z[len(x)] = y return z } The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 SECTION 4.2. SLICES 89 Each cal l to appendInt mu stche ckwhether the slice has sufficientcap acity toholdthe new elements in the exist ing array.Ifso, itextends the slice bydefiningalargerslice (still wit hin theoriginalarray), copies the element y into the newspace,and retur nsthe slice.The inp ut x andthe result z sh are the sameunderly ing array. If there isins ufficientspace for growt h, appendInt mu stallocateanew array big enough to hold the result, copy the values fro m x into it, thenapp end the newelement y.The result z nowreferstoadif ferentunderly ing array thanthe array that x refers to. It wou ldbestraig htfor wardtocopythe elements wit h explicitloops, but it’seasier touse the built-in function copy,whichcopies elements fro m on e slice toanother ofthe sametyp e.Its firs t argumentisthe destination and its secon d is the source, res emblingthe order ofoperands in an assig nmentlike dst = src.The slices may refer tothe sameunderly ing array ; they may even overl ap. Alt hough wedon’tuse ithere, copy returnsthe numberofelements actu ally copied,whichisthe smaller ofthe two slice lengt hs, sothere isnodangerofrunningoff the endoroverwriting som ethingout of range . Fo r efficiency,the newarray isusu allysom ewhat largerthanthe minimum needed tohold x and y.Exp andingthe array bydou blingits size at eachexp ansionavoidsanexcessive number of allocat ions and ens uresthatapp endingasingleelementtakes cons tanttimeonaverage. Thisprogram demon strates the effec t: func main() { var x, y []int for i := 0; i < 10; i++ { y=appendInt(x, i) fmt.Printf("%d cap=%d\t%v\n", i, cap(y), y) x=y } } Each change incap acity indic ates an allo cat ionand a copy: 0cap=1 [0] 1cap=2 [0 1] 2cap=4 [0 12] 3cap=4 [0 123] 4cap=8 [0 1234] 5cap=8 [0 12345] 6cap=8 [0 123456] 7cap=8 [0 1234567] 8cap=16 [0 12345678] 9cap=16 [0 123456789] Let’stakeaclos er lo okatthe i=3 it erat ion. Theslice x cont ainsthe three elements [0 1 2] but hascap acity 4,sothere isasingleelementofslack atthe end,and appendInt of the element 3 maypro ceed wit houtreallocat ing. The resulting slice y haslengt handcap acity 4,and has the same underly ing array as the originalslice x, as Figure4.2 shows. The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 90 CHAPTER 4. COMPOSITE TYPES Figure 4.2. Ap pendingwit h ro omtogrow. On the next iterat ion, i=4,there isnoslack atall,so appendInt al locatesanew array ofsize 8, copies the fourelements [0 1 2 3] of x,and app end s 4,the value of i.The resulting slice y hasalengt h of 5 but a cap acity of8;the slackof3will savethe next three iterat ions fro m the ne e d to reallocate. The slices y and x arevie ws of dif ferentarrays. Thisoperat ionisdepic ted in Figure4.3. Figure 4.3. Ap pendingwit houtroomtogrow. Thebui lt-in append func tionmay use a moresop histicate d growth strateg y than appendInt’s simplisticone.Usu allywedon’tknowwhether a given cal l to append wi l lcaus e areallocat ion, so wecan’tassume thatthe originalslice referstothe samearray as the resulting slice,nor that it referstoadif ferentone.Simi larly,wemustnot assume thatoperat ions onelements ofthe oldslice will (or will not)bereflec ted inthe newslice.Asaresult, it’susu altoassig n theresult of a cal l to append to the sameslice variablewhose value wepassedto append: runes = append(runes, r) The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 SECTION 4.2. SLICES 91 Up dat ingthe slice variableisrequired not justwhencal ling append,but for any functionthat maychange the lengt h or cap acity ofaslice ormakeitrefer toadif ferentunderly ing array.To us e slices correc tly,it’simp ortanttobearinmindthatalt hough the elements ofthe underly ing ar rayareindirec t,the slice’spoint er, lengt h,andcap acity are not.Toupdatethemrequires an assig nmentlikethe one above . In thisrespect,slices arenot ‘‘pure’’ referencetyp es butres em- ble an aggregatetyp e such asthisstr uct: type IntSlice struct { ptr *int len, cap int } Our appendInt func tionaddsasingleelementtoaslice,but the bui lt-in append lets usadd more thanone newelement, orevenawhole slice ofthem. var x []int x=append(x, 1) x=append(x, 2, 3) x=append(x, 4, 5, 6) x=append(x, x...) // append the slice x fmt.Println(x) // "[1 2 3 4 5 6 1 2 3 4 5 6]" Wi ththe small modification shown below,wecan match the beh avior of the bui lt-in append. Theellipsis ‘‘...’’ in the declarat ionof appendInt makesthe function variadic:itaccepts any numb eroffinalarguments. Thecor respondingellipsisinthe cal l ab ove to append shows how to sup ply a listofarguments fro m aslice.We’ll explain thismechanism in detai l in Section5.7. func appendInt(x []int, y ...int) []int { var z []int zlen := len(x) + len(y) // ...expand z to at least zlen... copy(z[len(x):], y) return z } Thelog ic to exp and z’sunderly ing array remainsunchange d andisnot shown. 4.2.2. In-PlaceSliceTechniques Let’ssee moreexamples offunctions that, like rotate and reverse,modif y theelements ofa slice in place.Given a list ofstr ings, the nonempty func tionretur nsthe non-empt y on es: gopl.io/ch4/nonempty // Nonempty is an example of an in-place slice algorithm. package main import "fmt" The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 92 CHAPTER 4. COMPOSITE TYPES // nonempty returns a slice holding only the non-empty strings. // The underlying array is modified during the call. func nonempty(strings []string) []string { i:=0 for _, s := range strings { if s != "" { strings[i] = s i++ } } return strings[:i] } Thesubtlepar t is thatthe inp utslice andthe out put slice share the sameunderly ing array. Thisavoidsthe need toallocateanother array,thoug h of cours e thecontentsof data arepar tly ov erwritt en, as evidence d by the secon d pr int statement: data := []string{"one", "", "three"} fmt.Printf("%q\n", nonempty(data)) // `["one" "three"]` fmt.Printf("%q\n", data) // `["one" "three" "three"]` Thus wewou ldusu allywrite: data = nonempty(data). The nonempty func tioncan also bewritt enusing append: func nonempty2(strings []string) []string { out := strings[:0] // zero-length slice of original for _, s := range strings { if s != "" { out = append(out, s) } } return out } Whiche ver variant weuse,reusinganarray in thisway requires thatatmostone out put value is pro duce d foreachinp utvalue,whichistrueofmanyalgor it hms thatfilt erout elements ofa sequence orcom bine adj acentones. Suchint ric ateslice usage isthe exception,not the rule, butitcan becle ar,efficient, andusefulonocc asion. Aslice can beusedtoimp lementastack.Given an initial lyemp tyslice stack,wecan pusha ne w value ont o theend ofthe slice wit h append: stack = append(stack, v) // push v Thetop ofthe stack isthe lastelement: top := stack[len(stack)-1] // top of stack andshr inking the stack bypoppingthatelementis stack = stack[:len(stack)-1] // pop The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 SECTION 4.3. MAPS 93 To remov e an elementfro m themidd le of a slice,preservingthe order ofthe remainingele- ments, use copy to slide the hig her-numbere d elements down byone tofill the gap: func remove(slice []int, i int) []int { copy(slice[i:], slice[i+1:]) return slice[:len(slice)-1] } func main() { s:=[]int{5, 6, 7, 8, 9} fmt.Println(remove(s, 2)) // "[5 6 8 9]" } And if we don’tneed topreservethe order,wecan justmov e thelastelementint o thegap: func remove(slice []int, i int) []int { slice[i] = slice[len(slice)-1] return slice[:len(slice)-1] } func main() { s:=[]int{5, 6, 7, 8, 9} fmt.Println(remove(s, 2)) // "[5 6 9 8] } Exercis e4.3: Re writ e reverse to use anarray point erins teadofaslice. Exercis e4.4: Wr ite a versionof rotate that operates in a singlepass. Exercis e4.5: Wr ite anin-place functiontoeliminateadj acentdup lic ates in a []string slice. Exercis e4.6: Wr ite anin-place functionthatsqu asheseachrun ofadj acentUnico de sp aces (s ee unicode.IsSpace) in a UTF-8-enco ded []byte slice into a singleASCII space. Exercis e4.7: Mo dif y reverse to reverse the charac tersofa[]byte slice thatrepresentsa UTF-8-enco dedstr ing , in place.Can you doitwit houtallocat ingnew memor y? 4.3. Maps Thehashtable isone ofthe most ingenious and versatileofall dat a st ruc tures. Itisan unordered col lec tion of key/value pairsinwhichall the keysare distinc t,and the value asso ci- ated wit h agiven key can beret rie ved,updated,orremov edusingacon stant numb erofkey comp arisons onthe average, nomatterhow large the hashtable. In Go, a map is a reference toahashtable,and a map typ e is writt en map[K]V,where K and V arethe typ es of itskeysand values. All ofthe keys in a given map areofthe sametyp e,and all of the values areofthe sametyp e,but the keysneed not beofthe sametyp e as the values. The ke y type K mu stbecomparable using ==,sothatthe map can testwhether a given key isequ al to one already wit hin it. Though floating-p ointnumbers are comparable,it’sabad ideato comp are floats for equ ality and,aswemention edinChapt er3,esp eci ally bad if NaN isapos- siblevalue.There are norestr ictions onthe value typ e V. The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 94 CHAPTER 4. COMPOSITE TYPES Thebui lt-in function make canbeusedtocre ate a map: ages := make(map[string]int) // mapping from strings to ints We can also use a maplit era l to cre ate a new map popu lated wit h some initial key/value pairs: ages := map[string]int{ "alice": 31, "charlie": 34, } Thisisequivalentto ages := make(map[string]int) ages["alice"] = 31 ages["charlie"] = 34 so analt ernat ive expressionfor a new emp tymap is map[string]int{}. Mapelements areaccessedthrough the usu alsubscript not ation: ages["alice"] = 32 fmt.Println(ages["alice"]) // "32" andremov edwit h thebui lt-in function delete: delete(ages, "alice") // remove element ages["alice"] Al l of these operat ions are safeevenifthe elementisn’tinthe map; a map lookup usingakey that isn’tpresent retur nsthe zerovalue for itstyp e,so, for ins tance,the fol low ing workseven when "bob" is not yet a key inthe map because the value of ages["bob"] wi l l be 0. ages["bob"] = ages["bob"] + 1 // happy birthday! Theshorthand assig nmentfor ms x+=yand x++ also wor k formap elements, sowecan re- wr ite the statement above as ages["bob"] += 1 or evenmorecon cis ely as ages["bob"]++ Butamap elementisnot a var iable,and wecannot takeits address: _=&ages["bob"] // compile error: cannot take address of map element Onereasonthatwecan’ttakethe addressofamap elementisthatgrowing a map might cause re hashingofexist ing elements into new storagelocat ions,thu s potent ial lyinvalid atingthe address. To enumerateall the key/value pairsinthe map,weuse a range-b ased for lo opsimi lar to thos e we saw for slices. Successive iterat ions ofthe loopcause the name and age var iables to be set tothe next key/value pair : The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 SECTION 4.3. MAPS 95 for name, age := range ages { fmt.Printf("%s\t%d\n", name, age) } Theorder ofmap iterat ionisuns pecified,and dif ferentimp lementation s mig htuse a dif ferent hash function, leadingtoadif ferentorder ing. Inprac tice,the order israndom, varying fro m on e exec ution tothe next. Thisisint ent ion al; mak ingthe sequence varyhelps force programs to berobustacrossimp lementation s.Toenumeratethe key/value pairsinorder,wemustsor t thekeysexplicitly, for ins tance,usingthe Strings func tionfro m the sort package if the keys arestr ings. Thisisacommonpattern: import "sort" var names []string for name := range ages { names = append(names, name) } sort.Strings(names) for _, name := range names { fmt.Printf("%s\t%d\n", name, ages[name]) } Sinceweknowthe finalsize of names from the outset, itismoreefficienttoallocateanarray of therequired size upfro nt. Thestatement below cre atesaslice thatisinitial lyemp tybut has sufficientcap acity toholdall the keysofthe ages map: names := make([]string, 0, len(ages)) In the firs t range lo opabove , we requireonlythe keysofthe ages map, soweomitthe secon d lo opvar iable.Inthe secon d lo op, werequireonlythe elements ofthe names slice,soweuse theblank identifier _ to ignorethe firs t var iable,the index. Thezerovalue for a map typ e is nil,thatis, a reference tonohashtable at all. var ages map[string]int fmt.Println(ages == nil) // "true" fmt.Println(len(ages) == 0) // "true" Most operat ions onmaps, includinglooku p, delete, len,and range lo ops, aresafetoper- form onanil map reference,since itbeh aveslikeanemp tymap.But storing toanil map caus esapanic: ages["carol"] = 21 // panic: assignment to entry in nil map Yo u mu stallocatethe map beforeyou can store int o it. Accessingamap elementbysubscript ing always yieldsavalue.Ifthe key ispresent inthe map, you get the cor respondingvalue; if not,you get the zerovalue for the elementtyp e,aswe sawwit h ages["bob"].For manypur pos es that’sfine,but som etimesyou need toknow whet her the elementwas reallythere ornot.For example, ifthe elementtyp e is numer ic, you mig hthavetodistinguish bet weenanon existentelementand anelementthathappens tohave thevalue zero, usingatestlikethis: The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 96 CHAPTER 4. COMPOSITE TYPES age, ok := ages["bob"] if !ok { /* "bob" is not a key in this map; age == 0. */ } Yo u’ll often see these two statementscom bine d,likethis: if age, ok := ages["bob"]; !ok { /* ... */ } Su bscript ing a map in thiscontext yieldstwo values; the secon d is a boole an that rep orts whet her the elementwas present.The boole an var iable isoften cal le d ok,esp eci ally ifitis immediate lyused in an if condit ion. As wit h slices, maps cannot becompare d to eachother ; theonlylegal comp arisoniswit h nil. To testwhether two maps cont ain the samekeysand the sameass oci ated values, wemust wr ite a loop: func equal(x, y map[string]int) bool { if len(x) != len(y) { return false } for k, xv := range x { if yv, ok := y[k]; !ok || yv != xv { return false } } return true } Observehow weuse !ok to distinguish the ‘‘missing’’ and ‘‘pres entbut zero’’ cases. Had we naïvelywritt en xv != y[k],the cal l belowwou ldincor rec tly rep ort its arguments as equ al: // True if equal is written incorrectly. equal(map[string]int{"A": 0}, map[string]int{"B": 42}) Go doesnot provide a set type,but since the keysofamap aredistinc t,amap can ser vethis purpos e.Toillustrate, the program dedup re ads a sequence oflines andprintsonlythe firs t occurrence ofeachdistinc t line. (It’savar iantofthe dup prog ram that weshowe d in Section1.3.) The dedup prog ram us esamap whose keysrepresent the set oflines thathave already app eared toens ure thatsubsequentocc urrences arenot print ed. gopl.io/ch4/dedup func main() { seen := make(map[string]bool) // a set of strings input := bufio.NewScanner(os.Stdin) for input.Scan() { line := input.Text() if !seen[line] { seen[line] = true fmt.Println(line) } } The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 SECTION 4.3. MAPS 97 if err := input.Err(); err != nil { fmt.Fprintf(os.Stderr, "dedup: %v\n", err) os.Exit(1) } } Go programmersoften descr ibe a map usedinthisfashionasa‘‘setofstr ings’’ withoutfur ther ado,but beware, not all map[string]bool values aresimplesets; som e maycontain bot h true and false values. Sometimesweneed a map orset whose keysare slices, but because a map’skeysmustbecom- parable,thiscannot beexpress eddirec tly.How ever, itcan bedon e in two steps. First we define a helperfunction k that maps eachkey toastr ing , with thepro per tythat k(x) == k(y) if andonlyifwecon sider x and y equivalent. Then wecre ate a map whose keysare str ings, apply ing the helperfunctiontoeachkey beforeweaccessthe map. Theexamplebelow usesamap torecordthe numberoftimes Add hasbeencal le d with a given list ofstr ings. Ituses fmt.Sprintf to convert a slice ofstr ingsint o asinglestr ing thatisa suit ablemap key,quoting eachslice elementwit h %q to recordstr ing bound aries faithfully: var m = make(map[string]int) func k(list []string) string { return fmt.Sprintf("%q", list) } func Add(list []string) {m[k(list)]++ } func Count(list []string) int { return m[k(list)] } Thesameappro ach can beusedfor any non-comp arable key typ e,not justslices. It’seven us efulfor comparable key typ es when you wantadefinition of equ ality other than ==,suchas case-insensit ive comparisons for str ings. And the typ e of k(x) ne e dn’tbeastr ing;any com- parable typ e with thedesired equivalence pro per tywill do, such as int egers,arrays, orstr ucts. Here’sanother exampleofmaps in action,aprogram thatcountsthe occ urrences ofeachdis- tinc t Unico de co de point in its input. Since there are a large numberofpossiblecharac ters, on lyasmall frac tionofwhichwou ldapp ear in anypar tic ulardocument, a map isanatural way tokeeptrackofjustthe onesthathavebeenseenand their correspondingcounts. gopl.io/ch4/charcount // Charcount computes counts of Unicode characters. package main import ( "bufio" "fmt" "io" "os" "unicode" "unicode/utf8" ) The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 98 CHAPTER 4. COMPOSITE TYPES func main() { counts := make(map[rune]int) // counts of Unicode characters var utflen [utf8.UTFMax + 1]int // count of lengths of UTF-8 encodings invalid := 0 // count of invalid UTF-8 characters in := bufio.NewReader(os.Stdin) for { r, n, err := in.ReadRune() // returns rune, nbytes, error if err == io.EOF { break } if err != nil { fmt.Fprintf(os.Stderr, "charcount: %v\n", err) os.Exit(1) } if r == unicode.ReplacementChar && n == 1 { invalid++ continue } counts[r]++ utflen[n]++ } fmt.Printf("rune\tcount\n") for c, n := range counts { fmt.Printf("%q\t%d\n", c, n) } fmt.Print("\nlen\tcount\n") for i, n := range utflen { if i > 0 { fmt.Printf("%d\t%d\n", i, n) } } if invalid > 0 { fmt.Printf("\n%d invalid UTF-8 characters\n", invalid) } } The ReadRune method perfor msUTF-8 deco dingand retur nsthree values: the decoded rune, thelengt h in bytes ofits UTF-8 enco ding, and anerror value.The onlyerror weexp ect isend- of-file.Ifthe inp utwas not a legal UTF-8 enco dingofarune, the retur ned runeis uni- code.ReplacementChar andthe lengt h is 1. The charcount prog ram also printsacount ofthe lengt hsofthe UTF-8 enco dings ofthe runesthatapp eared inthe inp ut. A mapisnot the bestdat a st ruc turefor that; since enco ding lengt hsrange onlyfro m 1to utf8.UTFMax (w hichhas the value 4), an array ismorecompact. As anexp eriment, weran charcount on thisbookits elf at one point.Alt hough it’smostlyin English, ofcours e, it doeshaveafair numberofnon-ASCII charac ters. Hereare the top ten: °27 B 15 F 14 é 13 A 10 < 5 & 5 D 4 ( 4 + 3 The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 SECTION 4.4. STRUCTS99 andhereisthe distr ibution of the lengt hsofall the UTF-8 enco dings: len count 1765391 260 370 40 Thevalue typ e of a map can its elf beacomposite typ e,suchasamap orslice.Inthe fol low ing co de,the key typ e of graph is string andthe value typ e is map[string]bool,represent ing a setofstr ings. Con ceptu ally, graph maps a str ing toaset ofrel ate d st rings, its successors ina direc ted graph. gopl.io/ch4/graph var graph = make(map[string]map[string]bool) func addEdge(from, to string) { edges := graph[from] if edges == nil { edges = make(map[string]bool) graph[from] = edges } edges[to] = true } func hasEdge(from, to string) bool { return graph[from][to] } The addEdge func tionshows the idiomaticway topopu lateamap lazi ly, thatis, toinitialize each value as its key app earsfor the firs t time.The hasEdge func tionshows how the zero value ofamissingmap entr y is often put towor k:evenifneither from nor to is present, graph[from][to] wi l l always giveameaningf ul resu lt. Exercis e4.8: Mo dif y charcount to count letters,dig its, andsoonintheir Unico de categories, usingfunctions like unicode.IsLetter. Exercis e4.9: Wr ite a program wordfreq to rep ort the fre quency ofeachword in an inp uttext file.Cal l input.Split(bufio.ScanWords) before the firs t call to Scan to bre akthe inp utint o word s insteadoflines. 4.4. Structs A st ruc t is anaggregatedat a type thatgro ups toget her zeroormorenamed values ofarbit rar y typesasa singleent ity.Eachvalue iscal le da fiel d.The classic exampleofastr uct fro m data processingisthe emp loy eerecord, whose fields are a unique ID,the emp loy ee’sname, address, date ofbir th, position,sal ary, manager,and the like. All ofthese fields are col lec ted int o asin- gleent ity thatcan becopie d as a unit, passedtofunctions and retur ned bythem, store d in ar rays,andsoon. The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 100 CHAPTER 4. COMPOSITE TYPES Thes e twostatementsdeclare a str uct typ e called Employee andavar iable cal le d dilbert that is anins tance ofan Employee: type Employee struct { ID int Name string Address string DoB time.Time Position string Salary int ManagerID int } var dilbert Employee Theindiv idu alfields of dilbert areaccessedusingdot not ation like dilbert.Name and dilbert.DoB.Because dilbert is a var iable,its fields are var iables too,sowemay assig n to a field: dilbert.Salary -= 5000 // demoted, for writing too few lines of code or takeits addressand accessitthrough a point er: position := &dilbert.Position *position = "Senior " + *position // promoted, for outsourcing to Elbonia Thedot not ation als o workswit h apoint ertoastr uct: var employeeOfTheMonth *Employee = &dilbert employeeOfTheMonth.Position += " (proactive team player)" Thelaststatement isequivalentto (*employeeOfTheMonth).Position += " (proactive team player)" Gi venanemp loy ee’sunique ID,the function EmployeeByID returnsapoint ertoan Employee st ruc t. We can use the dot not ation toaccessits fields: func EmployeeByID(id int) *Employee { /* ... */ } fmt.Println(EmployeeByID(dilbert.ManagerID).Position) // "Pointy-haired boss" id := dilbert.ID EmployeeByID(id).Salary = 0 // fired for... no real reason Thelaststatement updates the Employee st ruc t that ispoint edtobythe resultofthe cal l to EmployeeByID.Ifthe resulttyp e of EmployeeByID were change d to Employee insteadof *Employee,the assig nmentstatement wou ldnot compi lesince its left-handside wou ldnot identify a var iable. Fieldsare usu allywritt enone per line, wit h thefield’snamepre cedingits typ e,but con sec utive fields ofthe sametyp e maybecom bine d, as wit h Name and Address here: The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 SECTION 4.4. STRUCTS101 type Employee struct { ID int Name, Address string DoB time.Time Position string Salary int ManagerID int } Field order issig nificant totyp eidentity.Had weals o combined the declarat ionofthe Posi- tion field(also a str ing), orint erc hange d Name and Address,wewou ldbedefiningadif ferent st ruc t type.Typic ally weonlycom bine the declarat ions ofrel ate d fields. Thenameofastr uct fieldisexp orted ifitbeg inswit h acapit alletter; thisisGo’smain access cont rol mechanism. A st ruc t type may cont ain a mixtureofexp orted and unexp orted fields. St ruc t typestendtobeverb osebecause the y of ten invo l ve alinefor each field. Alt hough we couldwrite out the whole typ e each timeitisneeded,the rep etit ion wou ldget tires ome. In ste ad, str uct typ es usuallyapp ear wit hin the declarat ionofanamed typ e li ke Employee. Anamed str uct typ e S can’tdeclare a fieldofthe sametyp e S:anaggregatevalue cannot con- tain its elf.(An analogou s rest ric tionapp lies toarrays.) But S maydeclare a fieldofthe pointertyp e *S,whichlets uscre ate rec ursivedat a st ruc tures like lin ked lists andtre es. Thisis illustrated inthe codebelow,whichusesabinar y tree toimp lement an ins ertionsor t: gopl.io/ch4/treesort type tree struct { value int left, right *tree } // Sort sorts values in place. func Sort(values []int) { var root *tree for _, v := range values { root = add(root, v) } appendValues(values[:0], root) } // appendValues appends the elements of t to values in order // and returns the resulting slice. func appendValues(values []int, t *tree) []int { if t != nil { values = appendValues(values, t.left) values = append(values, t.value) values = appendValues(values, t.right) } return values } The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 102 CHAPTER 4. COMPOSITE TYPES func add(t *tree, value int) *tree { if t == nil { // Equivalent to return &tree{value: value}. t=new(tree) t.value = value return t } if value < t.value { t.left = add(t.left, value) }else { t.right = add(t.right, value) } return t } Thezerovalue for a str uct iscomposedofthe zerovalues ofeachofits fields.Itisusu ally desirable thatthe zerovalue beanatural orsensibledefau lt. For example, in bytes.Buffer, theinitial value ofthe str uct isaready-to-use emp tybuf fer,and the zerovalue of sync.Mutex, whichwe’ll see inChapt er9,isaready-to-use unlocke d mu tex. Som etimesthissensibleinitial behavior happens for fre e,but som etimesthe typ e desig ner has towor k at it. Thestr uct typ e with nofields is cal le d the emptystr uct,writt en struct{}.Ithas size zeroand carries noinfor mat ionbut may beusefulnon etheless. Som e Go programmersuse itins tead of bool as the value typ e of a map thatrepresentsaset, toemp hasize thatonlythe keysare sig- nificant,but the space sav ingismarginaland the syntaxmorecumbers ome,sowegeneral ly avoidit. seen := make(map[string]struct{}) // set of strings // ... if _, ok := seen[s]; !ok { seen[s] = struct{}{} // ...first time seeing s... } 4.4.1. Struct Literals Avalue ofastr uct typ e canbewritt enusingast ruc t litera l that specifies values for itsfields. type Point struct{ X, Y int } p:=Point{1, 2} Thereare two for msofstr uct lit eral.The firs t form,shown above , re quires thatavalue be sp ecified for ever y field, inthe rig htorder.Itburdensthe writer(andreader) wit h rememb er- ingexac tly whatthe fields are , anditmakes the codefrag i le shouldthe set of fields later grow or bereordered.Accordingly, thisfor m tend s to beusedonlywit hin the packagethatdefines thestr uct typ e,orwit h smal ler st ruc t typesfor whichthere is an obv iou s fieldorder ingcon- vent ion,like image.Point{x, y} or color.RGBA{red, green, blue, alpha}. The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 SECTION 4.4. STRUCTS103 Mo reoften, the secon d form isused, inwhichastr uct value isinitialize d by listing som e or all of the fieldnames andtheir correspondingvalues, as in thisstatement fro m theLissajous prog ram of Sec tion 1.4: anim := gif.GIF{LoopCount: nframes} If a fieldisomitt edinthiskindoflit eral,itisset tothe zerovalue for itstyp e.Because names areprovide d,the order of fields doesn’tmatter. Thetwo for mscannot bemixed inthe samelit eral.Nor can you use the (order-b ased)firs t form oflit eral tosne akaro und the rulethatunexp orted identifiersmay not berefer red to from another package. package p type T struct{ a, b int } // a and b are not exported package q import "p" var _ = p.T{a: 1, b: 2} // compile error: can'treference a, b var _ = p.T{1, 2} // compile error: can'treference a, b Although the lastlineabove doesn’tmention the unexp orted fieldidentifiers, it’sreallyusing them implicitly, soit’snot allow ed. St ruc tvalues can bepassedasarguments tofunctions and retur ned fro m them. For ins tance, this functionscales a Point by a specified fac tor : func Scale(p Point, factor int) Point { return Point{p.X * factor, p.Y * factor} } fmt.Println(Scale(Point{1, 2}, 5)) // "{5 10}" Fo r efficiency,largerstr uct typ es areusu allypassedtoorretur ned fro m func tions indirec tly usingapoint er, func Bonus(e *Employee, percent int) int { return e.Salary * percent / 100 } andthisisrequired ifthe functionmustmodif y itsargument, since in a cal l-by-value langu age li keGo, the cal le d func tionreceivesonlyacopyofanargument, not a reference tothe original argument. func AwardAnnualRaise(e *Employee) { e.Salary = e.Salary * 105 / 100 } Becaus e st ruc ts aresocommonlydealt wit h thro ugh point ers,it’spossibletouse this shorthand notation tocre ate and initialize a struct var iable andobt ain its address: pp := &Point{1, 2} It isexac tly equivalentto The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 104 CHAPTER 4. COMPOSITE TYPES pp := new(Point) *pp = Point{1, 2} but &Point{1, 2} canbeuseddirec tly wit hin an expression, such as a functioncal l. 4.4.2. Comparing Structs If all the fields ofa str uct are comparable,the str uct its elf iscomparable,sotwo expressions of that typ e maybecompare d using == or !=.The == op erat ioncomparesthe cor responding fields ofthe two str ucts in order,sothe two print edexpressions below are equivalent: type Point struct{ X, Y int } p:=Point{1, 2} q:=Point{2, 1} fmt.Println(p.X == q.X && p.Y == q.Y) // "false" fmt.Println(p == q) // "false" Comp arable str uct typ es, li keother comp arable typ es, maybeused as the key typ e of a map. type address struct { hostname string port int } hits := make(map[address]int) hits[address{"golang.org", 443}]++ 4.4.3. Struct Embedding and Anonymous Fields In thissec tion,we’ll see how Go’sunu sual st ruc t embedding me chanism lets ususe one named st ruc t type asan an ony mou s fiel d of another str uct typ e,providingaconvenientsyntactic shortcutsothatasimpledot expressionlike x.f canstand for a chain of fields like x.d.e.f. Consider a 2-D drawingprogram thatprovides a librar y of shapes, suchasrec tangles, ellipses, st ars,and whe els. Hereare two ofthe typ es it mig htdefine: type Circle struct { X, Y, Radius int } type Wheel struct { X, Y, Radius, Spokes int } A Circle hasfields for the X and Y co ordinates ofits center, and a Radius.AWheel hasall the fe aturesofaCircle,plu s Spokes,the numberofins cribedradi al sp okes. Let’scre ate a whe el: The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 SECTION 4.4. STRUCTS105 var w Wheel w.X = 8 w.Y = 8 w.Radius = 5 w.Spokes = 20 As the set ofshapesgrows, we’re bound tonot ice similarities andrep etit ion among them, soit maybeconvenienttofac tor out their common par ts: type Point struct { X, Y int } type Circle struct { Center Point Radius int } type Wheel struct { Circle Circle Spokes int } Theapp lic ationmay becle arer for it,but thischange makes accessingthe fields ofaWheel more verb ose: var w Wheel w.Circle.Center.X = 8 w.Circle.Center.Y = 8 w.Circle.Radius = 5 w.Spokes = 20 Go lets usdeclare a fieldwit h atyp e butnoname; such fields are cal le d an ony mou s fiel ds.The type ofthe fieldmustbeanamed typ e or a point ertoanamed typ e.Below, Circle and Wheel have one anony mou s fieldeach. Wesay thataPoint is embedded within Circle,and a Circle is emb edde d within Wheel. type Circle struct { Point Radius int } type Wheel struct { Circle Spokes int } Than ks to emb edding, wecan refer tothe names at the leavesofthe imp licittre e without giving the int erveningnames: The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 106 CHAPTER 4. COMPOSITE TYPES var w Wheel w.X = 8 // equivalent to w.Circle.Point.X = 8 w.Y = 8 // equivalent to w.Circle.Point.Y = 8 w.Radius = 5 // equivalent to w.Circle.Radius = 5 w.Spokes = 20 Theexplicitfor msshown inthe commentsabove are still valid,how ever, showing that ‘‘anonymou s field’’ is som ethingofamisnomer. The fields Circle and Point do have names—that ofthe named typ e—butthose names areopt ion alindot expressions.Wemay omit any orall ofthe anony mou s fields whenselec ting their subfields. Unfortunately, there’snocor respondingshorthand for the str uct lit eral synt ax, soneither of thes e wi l l comp ile: w=Wheel{8, 8, 5, 20} // compile error: unknown fields w=Wheel{X: 8, Y: 8, Radius: 5, Spokes: 20} // compile error: unknown fields Thestr uct lit eral mustfol low the shap e of the typ e de clarat ion, sowemustuse one ofthe two formsbelow,whichare equivalenttoeachother : gopl.io/ch4/embed w=Wheel{Circle{Point{8, 8}, 5}, 20} w=Wheel{ Circle: Circle{ Point: Point{X: 8, Y: 8}, Radius: 5, }, Spokes: 20, // NOTE: trailing comma necessary here (and at Radius) } fmt.Printf("%#v\n", w) // Output: // Wheel{Circle:Circle{Point:Point{X:8, Y:8}, Radius:5}, Spokes:20} w.X = 42 fmt.Printf("%#v\n", w) // Output: // Wheel{Circle:Circle{Point:Point{X:42, Y:8}, Radius:5}, Spokes:20} No tice how the # adverb causes Printf’s %v verb todispl ayvalues in a for m simi lar toGosyn- tax. For str uct values, thisfor m includes the nameofeach field. Becaus e ‘‘anonymou s’’ fields dohaveimp licitnames, you can’thavetwo anony mou s fields of thesametyp esince their names wou ldconflic t. Andbecause the nameofthe fieldisimp lic- it lydeter mined byits typ e,sotoo isthe visibilit y of the field. Inthe examples abov e,the Point and Circle anonymou s fields are exp orted.Had the y been unexp orted (point and circle), we cou ldstill use the shorthand for m w.X = 8 // equivalent to w.circle.point.X = 8 butthe explicitlon g form shown inthe comment wou ldbeforbidden outside the declaring packagebecause circle and point wouldbeinaccessible. The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 SECTION 4.5. JSON 107 Wh atwe’ve seensofar ofstr uct emb eddingisjustaspr ink lingofsyntactic sugar onthe dot notation usedtoselec t st ruc t fields.Later,we’ll see thatanony mou s fields need not bestr uct types; anynamed typ e or point ertoanamed typ e wi l l do.But why wou ldyou wanttoemb ed atyp e that has nosubfields? Theanswerhas to do wit h methods. Theshorthand notation usedfor selec ting the fields ofan embedde d type wor ksfor selec ting its met hodsaswel l.Ineffec t,the out erstr uct typ e gains notjustthe fields ofthe emb edde d type but itsmet hodstoo.Thismechanism isthe main way that comp lex obj e ctbeh avior s arecomposedfro m simpler ones. Comp ositi on is central to objec t-oriente d prog ramming in Go, and we’ll explore itfur ther in Sec tion 6.3. 4.5. JSON JavaS crip t Objec t No tat ion(JSON) isastand ard not ation for sendingand receiving str uctured infor mat ion. JSONisnot the onlysuchnot ation.XML (§7.14), ASN.1, andGoogle’sPro tocol Buffersser vesimi lar pur pos esandeachhas its niche,but because ofits simplicity,readabi lit y, andunivers alsup por t,JSONisthe most widely used. Go has excellentsup por t forencodingand decodingthese for mats, provide d by the stand ard librar y packages encoding/json, encoding/xml, encoding/asn1,and soon, andthese pack- ages allhavesimi lar APIs.Thissec tion gives a brief overvie w of the most imp ortantpar ts of the encoding/json package. JSONisanencodingofJavaS crip t values—st rings, numbers,boole ans, arrays, andobj e cts—as Unico de text. It’sanefficientyet readablerepresent ation for the basic dat a typesofChapt er3 andthe composite typ es of thischapt er—ar rays, slices, str ucts, andmaps. Thebasic JSONtyp es arenumbers (in decimal orscientificnot ation), boole ans(true or false), andstr ings, whichare sequences ofUnico de co de points enclos edindou ble quotes, with backslash escap es usingasimi lar not ation toGo, thoug hJSON’s \Uhhhh numericescap es denot e UTF-16 codes, not runes. Thes e basic typ es maybecom bine d re cursive lyusingJSONarrays andobj e cts. A JSONarray is anordered sequence ofvalues, writt enasa comma-s eparated listenclos edinsqu are brack- ets; JSONarrays areusedtoencodeGoarrays andslices. A JSONobj e ctisamapping fro m st rings tovalues, writt enasasequence of name:value pairssep arated bycommasand sur- ro unded bybraces; JSONobj e cts areusedtoencodeGomaps (wit h st ringkeys) andstr ucts. Fo r example: boolean true number -273.15 string "She said \"Hello, BF\"" array ["gold", "silver", "bronze"] object {"year": 1980, "event": "archery", "medals": ["gold", "silver", "bronze"]} The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 108 CHAPTER 4. COMPOSITE TYPES Consider an applic ationthatgat hersmov ierevie ws andoffersrecommend ation s.Its Movie data typ eandatypic allist ofvalues aredeclare d below. (Thestr ing lit eralsafter the Year and Color fielddeclarat ions are fiel d tags;we’ll explain them in a mom ent.) gopl.io/ch4/movie type Movie struct { Title string Year int `json:"released"` Color bool `json:"color,omitempty"` Actors []string } var movies = []Movie{ {Title: "Casablanca", Year: 1942, Color: false, Actors: []string{"Humphrey Bogart", "Ingrid Bergman"}}, {Title: "Cool Hand Luke", Year: 1967, Color: true, Actors: []string{"Paul Newman"}}, {Title: "Bullitt", Year: 1968, Color: true, Actors: []string{"Steve McQueen", "Jacqueline Bisset"}}, // ... } Data str uctures like thisare anexcel lent fitfor JSON, andit’seasy toconvert inbot h direc tion s.ConvertingaGodat a st ruc turelike movies to JSONiscal le d marshaling.Mar- sh alingisdon e by json.Marshal: data, err := json.Marshal(movies) if err != nil { log.Fatalf("JSON marshaling failed: %s", err) } fmt.Printf("%s\n", data) Marshal produces a byteslice cont ainingaver y long str ing wit h no ext raneous white space; we’ve folde d thelines soit fits: [{"Title":"Casablanca","released":1942,"Actors":["Humphrey Bogart","Ingr id Bergman"]},{"Title":"Cool Hand Luke","released":1967,"color":true,"Ac tors":["Paul Newman"]},{"Title":"Bullitt","released":1968,"color":true," Actors":["Steve McQueen","Jacqueline Bisset"]}] Thiscompact represent ation containsall the infor mat ionbut it’shardtoread. For human cons ump tion, a variant cal le d json.MarshalIndent produces neatlyindente d output.Two addition alarguments define a prefixfor eachlineofout put and a str ing for eachlevel of indentation: data, err := json.MarshalIndent(movies, "", " ") if err != nil { log.Fatalf("JSON marshaling failed: %s", err) } fmt.Printf("%s\n", data) The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 SECTION 4.5. JSON 109 Thecodeabove prints [ { "Title": "Casablanca", "released": 1942, "Actors": [ "Humphrey Bogart", "Ingrid Bergman" ] }, { "Title": "Cool Hand Luke", "released": 1967, "color": true, "Actors": [ "Paul Newman" ] }, { "Title": "Bullitt", "released": 1968, "color": true, "Actors": [ "Steve McQueen", "Jacqueline Bisset" ] } ] Mars halingusesthe Gostr uct fieldnames as the fieldnames for the JSONobj e cts (through reflec tion,aswe’ll see inSec tion 12.6). Only exp orted fields are marsh ale d,whichiswhy we ch ose capit alize d namesfor all the Gofieldnames. Yo u mayhavenot ice d that the nameofthe Year fieldchange d to released in the out put,and Color ch ange d to color.That’sbecause ofthe fiel d tags.Afieldtag isastr ing ofmet adat a asso ciate d at comp ile timewit h thefieldofastr uct: Year int `json:"released"` Color bool `json:"color,omitempty"` Afieldtag may beany lit eral str ing , butitisconvent ion allyint erprete d as a space-s eparated list of key:"value" pairs; since the y cont ain double quotation marks, fieldtags areusu ally wr itt enwit h raw str ing lit erals. The json ke y cont rol s thebeh avior of the encoding/json package, and other encoding/... packages fol low thisconvent ion.The firs t part ofthe json fieldtag specifies an alternat ive JSONnamefor the Gofield. Field tags areoften usedto sp ecif y an idiomaticJSONnamelike total_count foraGofieldnamed TotalCount.The tag for Color has an addition alopt ion, omitempty,whichindic ates thatnoJSONout put should be pro duce d if the fieldhas the zerovalue for itstyp e (false,here) orisother wis e empt y. Sure enoug h, theJSONout put for Casabl anca,ablack-and-w hite mov ie, has no color field. The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 110 CHAPTER 4. COMPOSITE TYPES Theinv ers e op erat iontomarsh aling, decodingJSONand popu lat ingaGodat a st ruc ture, is called unmarshaling,and itisdon e by json.Unmarshal.The codebelow unmarsh als the JSONmov iedat ainto a slice ofstr uctswhose onlyfieldis Title.BydefiningsuitableGodat a st ruc tures in thisway,wecan selec t whichpar ts of the JSONinp uttodecodeand whichtodis- card . Wh en Unmarshal returns, ithas filled inthe slice wit h the Title infor mat ion; other names in the JSONare ignored. var titles []struct{ Title string } if err := json.Unmarshal(data, &titles); err != nil { log.Fatalf("JSON unmarshaling failed: %s", err) } fmt.Println(titles) // "[{Casablanca} {Cool Hand Luke} {Bullitt}]" Many web ser vices provide a JSONint erface—make a requestwit h HT TPandbackcom esthe desired infor mat ioninJSONfor mat. Toillustrate, let’squer y theGitHu b issuetrackerusing itsweb-s ervice interface.First we’ll define the necessary typ esandcon stants: gopl.io/ch4/github // Package github provides a Go API for the GitHub issue tracker. // See https://developer.github.com/v3/search/#search-issues. package github import "time" const IssuesURL = "https://api.github.com/search/issues" type IssuesSearchResult struct { TotalCount int `json:"total_count"` Items []*Issue } type Issue struct { Number int HTMLURL string `json:"html_url"` Title string State string User *User CreatedAt time.Time `json:"created_at"` Body string // in Markdown format } type User struct { Login string HTMLURL string `json:"html_url"` } As before, the names ofall the str uct fields mustbecapit alize d even if their JSONnames are not. How ever, the matchingpro cessthatass oci ates JSONnames wit h Go str uct names dur ing unmarsh alingiscas e-insensit ive , so it’sonlynecessary touse a fieldtag whenthere’sanunder- scoreinthe JSONnamebut not inthe Goname. Again, weare beingselec tive about which fields todecode; the GitHu b search respons e cont ainscon siderably moreinfor mat ionthanwe showhere. The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 SECTION 4.5. JSON 111 The SearchIssues func tionmakes an HTTP requestand decodes the resultasJSON. Since thequer y termspresent edbyausercou ldcontain charac terslike ? and & that havespeci al me aning in a URL, weuse url.QueryEscape to ens ure thatthe y aretaken literal ly. gopl.io/ch4/github package github import ( "encoding/json" "fmt" "net/http" "net/url" "strings" ) // SearchIssues queries the GitHub issue tracker. func SearchIssues(terms []string) (*IssuesSearchResult, error) { q:=url.QueryEscape(strings.Join(terms, " ")) resp, err := http.Get(IssuesURL + "?q=" + q) if err != nil { return nil, err } // We must close resp.Body on all execution paths. // (Chapter 5 presents 'defer',which makes this simpler.) if resp.StatusCode != http.StatusOK { resp.Body.Close() return nil, fmt.Errorf("search query failed: %s", resp.Status) } var result IssuesSearchResult if err := json.NewDecoder(resp.Body).Decode(&result); err != nil { resp.Body.Close() return nil, err } resp.Body.Close() return &result, nil } Theearlier examples used json.Unmarshal to decodethe ent ire contentsofabyteslice as a singleJSONent ity.For var iety, thisexampleusesthe st reami n g de coder, json.Decoder, whichallowsseveral JSONent ities tobedecoded insequence fro m thesamestream, although we don’tneed thatfeature here. Asyou mig htexp ect,there isacor respondingstreaming enco der called json.Encoder. Thecal l to Decode popu lates the var iable result.There are var ious ways wecan for mat its value nicely.The simplest, demon strated bythe issues commandbelow,isasatext table with fixe d-w idth columns, but inthe next sec tion we’ll see a moresop histicate d approach basedontempl ates. The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 112 CHAPTER 4. COMPOSITE TYPES gopl.io/ch4/issues // Issues prints a table of GitHub issues matching the search terms. package main import ( "fmt" "log" "os" "gopl.io/ch4/github" ) func main() { result, err := github.SearchIssues(os.Args[1:]) if err != nil { log.Fatal(err) } fmt.Printf("%d issues:\n", result.TotalCount) for _, item := range result.Items { fmt.Printf("#%-5d %9.9s %.55s\n", item.Number, item.User.Login, item.Title) } } Thecommand-linearguments specif y thesearc h terms. Thecommand below quer ies theGo proj e ct’sissuetrackerfor the listofopenbugs rel ate d to JSONdecoding: $gobuild gopl.io/ch4/issues $./issues repo:golang/go is:open json decoder 13 issues: #5680 eaigner encoding/json: set key converter on en/decoder #6050 gopherbot encoding/json: provide tokenizer #8658 gopherbot encoding/json: use bufio #8462 kortschak encoding/json: UnmarshalText confuses json.Unmarshal #5901 rsc encoding/json: allow override type marshaling #9812 klauspost encoding/json: string tag not symmetric #7872 extempora encoding/json: Encoder internally buffers full output #9650 cespare encoding/json: Decoding gives errPhase when unmarshalin #6716 gopherbot encoding/json: include field name in unmarshal error me #6901 lukescott encoding/json, encoding/xml: option to treat unknown fi #6384 joeshaw encoding/json: encode precise floating point integers u #6647 btracey x/tools/cmd/godoc: display type kind of each named type #4237 gjemiller encoding/base64: URLEncoding padding is optional TheGitHu b we b-s ervice interface at https://developer.github.com/v3/ hasmanymore fe aturesthanwehavespace for here. Exercis e4.10: Mo dif y issues to rep ort the results in agecategor ies, say lessthanamonth old, lessthanayearold,and more thanayearold. Exercis e4.11: Buildatoolthatlets users cre ate, read, update, and deleteGitHu b issues fro m thecommand line, inv oking their preferred text editorwhensubst ant ial text inputisrequired. The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 SECTION 4.6. TEXT AND HTML TEMPLATES 113 Exercis e4.12: Thepopu lar web comic xkcd hasaJSONint erface.For example, a requestto https://xkcd.com/571/info.0.json produces a detai le d des crip tionofcomic 571, one of many favor ites. Dow nlo ad each URL (once!) andbui ld an offlineindex. Write a tool xkcd that, usingthisindex, printsthe URL andtranscript ofeachcomic thatmatch esasearc h term prov ide d on the command line. Exercis e4.13: TheJSON-b ased web ser vice ofthe OpenMov ieDat abas e lets you searc h https://omdbapi.com/ foramov iebynameand dow nlo ad itsposterimage . Wr ite a tool poster that down loads the posterimage for the movienamed onthe command line. 4.6. Textand HTML Templates Thepre vious exampledoesonlythe simplestpossiblefor matting , forwhich Printf is ent ire ly ade quate. But som etimesfor matting mustbemoreelaborate, and it’sdesirable tosep aratethe format fro m thecodemorecompletely. Thiscan bedon e with the text/template and html/template packages, whichprovide a mechanism for subst ituting the values ofvar iables into a text orHTMLtempl ate. Atempl ate isastr ing orfile cont ainingone ormorepor tions enclos edindou ble braces, {{...}},cal le d ac tions.Mostofthe str ing isprint edlit eral ly, but the actions trigger other behavior s.Eachactioncontainsanexpressioninthe templ ate langu age, a simplebut pow erful notation for printing values, selec ting str uct fields,cal lingfunctions and methods, expressing cont rol flow suchas if-else st atementsand range lo ops, andins tantiat ingother templ ates. Asimpletempl ate str ing isshown below : gopl.io/ch4/issuesreport const templ = `{{.TotalCount}} issues: {{range .Items}}---------------------------------------- Number: {{.Number}} User: {{.User.Login}} Title: {{.Title |printf "%.64s"}} Age: {{.CreatedAt |daysAgo}} days {{end}}` Thistempl ate firs t pr intsthe numberofmatchingissues, thenprintsthe number, user, tit le, andage indays ofeachone.Wit hin an action,there isanot ion of the cur rentvalue,refer red to as ‘‘dot’’ andwritt enas ‘‘.’’,aper iod. The dot initial lyreferstothe templ ate’sparameter, whichwill beagithub.IssuesSearchResult in thisexample. The {{.TotalCount}} ac tion exp ands tothe value ofthe TotalCount field, print edinthe usu alway.The {{range .Items}} and {{end}} ac tions cre ate a loop, sothe text bet weenthemisexp ande d mu ltipletimes, wit h dotbound tosuccessive elements of Items. Wi thin an action,the | notation makes the resultofone operat ionthe argumentofanother, analogou s to a Unix shel l pip eline. Inthe cas e of Title,the secon d op erat ionisthe printf func tion, whichisabui lt-in synony m for fmt.Sprintf in alltempl ates. For Age,the secon d op erat ionisthe fol low ing function, daysAgo,whichconvertsthe CreatedAt fieldint o an The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 114 CHAPTER 4. COMPOSITE TYPES el aps edtime, using time.Since: func daysAgo(t time.Time) int { return int(time.Since(t).Hours() / 24) } No tice thatthe typ e of CreatedAt is time.Time,not string.Inthe sameway thatatyp e may cont rol its str ing for matting (§2.5) bydefiningcer tain met hods, a typ e mayals o define meth- odstocontrol its JSONmarsh alingand unmarsh alingbeh avior.The JSON-marsh ale d value of a time.Time is a str ing inastand ard for mat. Producingout put wit h atempl ate isatwo-steppro cess. First wemustparse the templ ate int o asuitableint ernal represent ation,and thenexe cut e it on specificinp uts. Parsingneed bedon e on lyonce. The codebelow cre atesand parsesthe templ ate templ define d ab ove . No tethe ch ainingofmet hod cal ls: template.New createsand retur nsatempl ate; Funcs adds daysAgo to the set offunctions accessiblewit hin thistempl ate, thenretur nsthattempl ate;finally, Parse is cal le d on the result. report, err := template.New("report"). Funcs(template.FuncMap{"daysAgo": daysAgo}). Parse(templ) if err != nil { log.Fatal(err) } Becaus e temp lates areusu allyfixe d at comp ile time, fai luretoparse a templ ate indic ates a fatal buginthe program. The template.Must helperfunctionmakes erro r hand lingmorecon- venient: itaccepts a templ ate and anerror,che cks thatthe error isnil (andpanics other wis e), andthenretur nsthe templ ate. We’ll com e back to thiside a in Sec tion 5.9. Once the templ ate has beencre ate d, aug mente d with daysAgo,parsed, and che cke d,wecan exec ute itusingagithub.IssuesSearchResult as the dat a source and os.Stdout as the des- tination: var report = template.Must(template.New("issuelist"). Funcs(template.FuncMap{"daysAgo": daysAgo}). Parse(templ)) func main() { result, err := github.SearchIssues(os.Args[1:]) if err != nil { log.Fatal(err) } if err := report.Execute(os.Stdout, result); err != nil { log.Fatal(err) } } Theprogram printsaplain text rep ort likethis: The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 SECTION 4.6. TEXT AND HTML TEMPLATES 115 $gobuild gopl.io/ch4/issuesreport $./issuesreport repo:golang/go is:open json decoder 13 issues: ---------------------------------------- Number: 5680 User: eaigner Title: encoding/json: set key converter on en/decoder Age: 750 days ---------------------------------------- Number: 6050 User: gopherbot Title: encoding/json: provide tokenizer Age: 695 days ---------------------------------------- ... No w let’stur n to the html/template package. Itusesthe sameAPI and expressionlangu age as text/template butaddsfeaturesfor aut omat icandcontext-appropriateescapingofstr ings appear ingwit hin HTML, JavaS crip t,CSS, orURLs. Thes e fe aturescan helpavoid a perenni al security pro blem ofHTMLgenerat ion, an injectionattack, in which an adversary craf ts a st ringvalue like the tit leofanissuetoinclude malicious codethat, whenimp rop erlyescap ed by a templ ate, gives themcontrol overthe page. Thetempl ate below printsthe listofissues as an HTML table.Not e thedif ferentimp ort: gopl.io/ch4/issueshtml import "html/template" var issueList = template.Must(template.New("issuelist").Parse(`

{{.TotalCount}} issues

{{range .Items}} {{end}}
# State User Title
{{.Number}} {{.State}} {{.User.Login}} {{.Title}}
`)) Thecommand below exe cut esthe newtempl ate onthe results ofaslig htlydif ferentquer y: The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 116 CHAPTER 4. COMPOSITE TYPES $gobuild gopl.io/ch4/issueshtml $./issueshtml repo:golang/go commenter:gopherbot json encoder >issues.html Figure4.4 shows the app earance ofthe table in a web brows er.The lin ks connec t to the appropriateweb pages at GitHu b. Figure 4.4. An HTMLtable ofGopro jec t issues rel ating toJSONencoding. No neofthe issues in Figure4.4 pos e achallenge for HTML, but wecan see the effec t more clearlywit h issues whose tit les cont ain HTML met acharac terslike & and <.We’ve selec ted two such issues for thisexample: $./issueshtml repo:golang/go 3133 10535 >issues2.html Figure4.5 shows the resultofthisquer y.Not ice thatthe html/template packageaut omat i- callyHTML-es cap edthe tit les sothatthe y appear literal ly. Had weusedthe text/template packagebymistake , thefour-ch arac ter str ing "<" wouldhavebeenrendered asaless-t han ch arac ter '<',and the str ing "" wouldhavebecom e a link element, chang ing the st ruc tureofthe HTMLdocumentand perhaps comp romisingits sec urity. We can sup pressthisaut o-es capingbeh avior for fields thatcontain trusted HTMLdat a by usingthe named str ing typ e template.HTML insteadof string.Simi lar named typ esexist for tr usted JavaS crip t,CSS, andURLs. Theprogram below demon strates the princip lebyusing twofields wit h thesamevalue but dif ferenttyp es: A is a str ing and B is a template.HTML. The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 SECTION 4.6. TEXT AND HTML TEMPLATES 117 Figure 4.5. HTML met acharac ters in issuetit les arecor rec tly displ aye d. gopl.io/ch4/autoescape func main() { const templ = `

A: {{.A}}

B: {{.B}}

` t:=template.Must(template.New("escape").Parse(templ)) var data struct { Astring // untrusted plain text Btemplate.HTML // trusted HTML } data.A = "Hello!" data.B = "Hello!" if err := t.Execute(os.Stdout, data); err != nil { log.Fatal(err) } } Figure4.6 shows the templ ate’sout put asitapp earsinabrows er.Wecan see that A was su bjec t to escapingbut B was not. Figure 4.6. St ringvalues areHTML-es cap edbut template.HTML values arenot. We havespace heretoshowonlythe most basic featuresofthe templ ate system. Asalways, for more infor mat ion, cons ult the packagedocumentation: $godoc text/template $godoc html/template Exercis e4.14: Create a web ser ver thatquer ies GitHub onceand thenallowsnav igationofthe list ofbug rep orts, milestones, andusers. The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 This page intentionally left blank From the Library of YIGUANG HU ptg16105617 5 Functions Afunctionlets uswrap upasequence ofstatementsasaunitthatcan becal le d from els e where in a program, perhaps multipletimes. Functions makeitpossibletobre akabig job int o smal ler pieces thatmig htwel l be writt enbydif ferentpeoplesep arated bybot h time and space. Afunctionhides its implementation det ails fro m itsusers.For all ofthese reasons,functions areacriticalpar t of any programminglangu age. We’ve seenmanyfunctions already.Now let’staketimefor a morethoro ugh dis cussion. The runningexampleofthischapt erisaweb craw ler,thatis, the component ofaweb searc h engine responsible for fetchingweb pages, discov ering the lin ks within them, fetchingthe pagesidentified bythose lin ks, andsoon. A we b craw ler givesusamp leopp ortunity to explore recursion, anonymou s func tions,error handling, and asp ectsoffunctions thatare unique toGo. 5.1. Function Declarations Afunctiondeclarat ionhas a name, a listofparameters, an opt ion allistofresults, andabody: func name(parameter-list)(result-list){ body } Theparameter list specifies the names andtyp es of the function’s para meters,whichare the lo cal variables whose values or ar gum ents aresup plie d by the cal ler.The resultlistspecifies thetyp es of the values thatthe functionretur ns. Ifthe functionretur nsone unnamed result or noresults at all, parenthes es areopt ion aland usu allyomitt ed. Leaving off the resultlist entire lydeclaresafunctionthatdoesnot retur nanyvalue andiscal le d on lyfor itseffec ts. In the hypot func tion, 119 The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 120 CHAPTER 5. FUNCTIONS func hypot(x, y float64) float64 { return math.Sqrt(x*x + y*y) } fmt.Println(hypot(3, 4)) // "5" x and y areparametersinthe declarat ion, 3 and 4 arearguments ofthe cal l,and the function returnsafloat64 value. Like parameters, results may benamed.Inthatcas e,eachnamedeclaresalocal variableini- tialize d to the zerovalue for itstyp e. Afunctionthathas a resultlistmustend wit h a return st atement unlessexe cut ion cle arly cannot reach the end ofthe function, perhaps because the functionend s with a cal l to panic or aninfinite for lo opwit h no break. As wesaw wit h hypot,asequence ofparametersorresults ofthe sametyp e canbefac tored so that the typ e itself iswritt enonlyonce. These two declarat ions are equivalent: func f(i, j, k int, s, t string) {/*... */ } func f(i int, j int, k int, s string, t string) { /* ... */ } Here are fourways todeclare a functionwit h twoparametersand one result, alloftyp e int. Theblank identifier can beusedtoemp hasize thataparameter isunu sed. func add(x int, y int) int {return x + y } func sub(x, y int) (z int) {z=x-y;return } func first(x int, _ int) int { return x } func zero(int, int) int {return 0 } fmt.Printf("%T\n", add) // "func(int, int) int" fmt.Printf("%T\n", sub) // "func(int, int) int" fmt.Printf("%T\n", first) // "func(int, int) int" fmt.Printf("%T\n", zero) // "func(int, int) int" Thetyp e of a functionissom etimescal le d its sig nat ure.Two functions havethe sametyp e or sig nature if the y have the samesequence ofparameter typ es andthe samesequence ofresult types. Thenames ofparametersand results don’taffec t thetyp e,nor doeswhether ornot the y were declare d usingthe fac tored for m. Ev ery functioncal l mu stprovide an argumentfor eachparameter,inthe order in whichthe parametersweredeclare d.Gohas nocon ceptofdefau ltparameter values, nor any way to sp ecif y arguments byname, sothe names ofparametersand results don’tmattertothe cal ler except as documentation. Parametersare local variables wit hin the bodyofthe function, wit h their initial values set to thearguments sup plie d by the cal ler.Functionparametersand named results arevar iables in thesamelexic al block as the function’sout ermostlocal variables. Arguments arepassed by value,sothe functionreceivesacopyofeachargument; modifica- tion s to the copy do not affec t thecal ler.How ever, ifthe argumentcontainssom e kind ofref- erence,likea point er, slice,map,function, orchannel,thenthe cal ler maybeaffec ted byany mo dification s thefunctionmakes tovar iables in direc tly referred tobythe argument. The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 SECTION 5.2. RECURSION 121 Yo u mayocc asionallyencount erafunctiondeclarat ionwit houtabody, indic atingthatthe func tionisimp lemente d in a langu ageother thanGo. Suchadeclarat iondefinesthe function sig nature. package math func Sin(x float64) float64 // implemented in assembly language 5.2. Recursion Func tions may be re cur siv e,thatis, the y maycal l themselves, either direc tly orindirec tly. Re cursionisapow erfultechnique for manypro blems, andofcours e it’sess ent ial for process- ingrec ursivedat a st ruc tures. InSec tion 4.4, weusedrec ursionoveratree toimp lementa simpleins ertionsor t.Inthissec tion,we’ll use itagain for processingHTMLdocuments. Theexampleprogram below usesanon-stand ard package, golang.org/x/net/html,which prov ides an HTML parser. The golang.org/x/... repositories holdpackages designe d and maintained bythe Goteamfor app lic ations suchasnet wor king, int ernat ionalize d text processing, mobileplatfor ms, imagemanipu lat ion, cryptography,and develop ertools.These packages arenot inthe stand ard librar y becaus e they’re still under deve lopment orbecause they’re rarelyneeded bythe maj ority ofGoprogrammers. Thepar ts of the golang.org/x/net/html APIthatwe’ll need are shown below.The function html.Parse re ads a sequence ofbytes, parsesthem, andretur nsthe rootofthe HTMLdoc- umenttre e,whichisan html.Node.HTMLhas several kinds ofnodes—text, comments, and so on—buthereweare con cer ned onlywit h el ement no des ofthe for m . golang.org/x/net/html package html type Node struct { Type NodeType Data string Attr []Attribute FirstChild, NextSibling *Node } type NodeType int32 const ( ErrorNode NodeType = iota TextNode DocumentNode ElementNode CommentNode DoctypeNode ) The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 122 CHAPTER 5. FUNCTIONS type Attribute struct { Key, Val string } func Parse(r io.Reader) (*Node, error) The main func tionparsesthe stand ard inp utasHTML, extrac ts thelin ks usingarec ursive visit func tion, andprintseachdis cov ere d lin k: gopl.io/ch5/findlinks1 // Findlinks1 prints the links in an HTML document read from standard input. package main import ( "fmt" "os" "golang.org/x/net/html" ) func main() { doc, err := html.Parse(os.Stdin) if err != nil { fmt.Fprintf(os.Stderr, "findlinks1: %v\n", err) os.Exit(1) } for _, link := range visit(nil, doc) { fmt.Println(link) } } The visit func tiontraversesanHTMLnodetre e,ext racts the lin k from the href attr ibute of each an chor element ,app end s thelin ks to a slice ofstr ings, andretur nsthe resu lting slice: // visit appends to links each link found in n and returns the result. func visit(links []string, n *html.Node) []string { if n.Type == html.ElementNode && n.Data == "a" { for _, a := range n.Attr { if a.Key == "href" { links = append(links, a.Val) } } } for c := n.FirstChild; c != nil; c = c.NextSibling { links = visit(links, c) } return links } To des cendthe tre e fora node n, visit re cursive lycal lsits elf for eachof n’schi ldren, which areheld in the FirstChild lin ked list. The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 SECTION 5.2. RECURSION 123 Let’srun findlinks on the Gohom e page , piping the out put of fetch (§1.5) tothe inp utof findlinks.We’ve edite d theout put slig htlyfor brevit y. $gobuild gopl.io/ch1/fetch $gobuild gopl.io/ch5/findlinks1 $./fetch https://golang.org | ./findlinks1 # /doc/ /pkg/ /help/ /blog/ http://play.golang.org/ //tour.golang.org/ https://golang.org/dl/ //blog.golang.org/ /LICENSE /doc/tos.html http://www.google.com/intl/en/policies/privacy/ No tice the var ietyoffor msoflin ks that appear in the page. Later we’ll see how tores olve them rel ative tothe bas eURL, https://golang.org,tomakeabs olut e URLs. Thenext program usesrec ursionoverthe HTMLnodetre e to print the str uctureofthe tre e in outline. Asitencount ers eachelement, itpushesthe element’stag ont o astack,thenprintsthe st ack. gopl.io/ch5/outline func main() { doc, err := html.Parse(os.Stdin) if err != nil { fmt.Fprintf(os.Stderr, "outline: %v\n", err) os.Exit(1) } outline(nil, doc) } func outline(stack []string, n *html.Node) { if n.Type == html.ElementNode { stack = append(stack, n.Data) // push tag fmt.Println(stack) } for c := n.FirstChild; c != nil; c = c.NextSibling { outline(stack, c) } } No teone subtlet y:alt hough outline ‘‘pu shes’’ an elementon stack,there isnocor responding pop. When outline callsits elf rec ursively, the cal le e re ceivesacopyof stack.Alt hough the callee may append elements tothisslice,modif yingits underly ing array andperhaps even al locating a new array,itdoesn’tmodif y theinitial elements thatare visible tothe cal ler,so when the functionretur ns, the cal ler’s stack is asitwas beforethe cal l. The Go Programming Language © 2016 Alan A. A. Donovan & Brian W. Kernighan revision 3b600c, date 29 Sep 2015 From the Library of YIGUANG HU ptg16105617 124 CHAPTER 5. FUNCTIONS Here’sthe out lineof https://golang.org,again edite d forbre vit y: $gobuild gopl.io/ch5/outline $./fetch https://golang.org | ./outline [html] [html head] [html head meta] [html head title] [html head link] [html body] [html body div] [html body div] [html body div div] [html body div div form] [html body div div form div] [html body div div form div a] ... As you can see byexp erimenting wit h outline,mostHTMLdocuments can bepro cessed with onlyafew level s of rec ursion, but it’snot hardtocon str uct pat holog ical web pages that re quireext remelydeeprec ursion. Many programminglangu ageimp lementation s us e afixe d-size functioncal l st ack;sizes fro m 64KB to2MB aretypic al.Fixed-size stacksimp ose a limitonthe depth ofrec ursion, soone mu stbecaref ultoavoid a sta ckoverflow when traversinglarge dat a st ruc tures rec ursively; fixe d-size stacksmay evenpos e asec urity risk. Incontrast, typic al Go imp lementation s us e var iable-size stacksthatstart small and grow as needed uptoalimitonthe order ofagigabyte. Thislets ususe rec ursionsafelyand wit houtwor rying about overflow. Exercis e5.1: Change the findlinks prog ram to traverse the n.FirstChild lin ked listusing re cursive cal lsto visit insteadofaloop. Exercis e5.2: Wr ite a functiontopopu lateamapping fro m elementnames—p, div, span,and so on—to the numberofelements wit h that name in an HTMLdocumenttre e. Exercis e5.3: Wr ite a functiontoprint the contentsofall text nodes in an HTML document tree.Donot des cendint o