Compare commits
3 Commits
weekly
...
release.r5
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5d9765785d | ||
|
|
6b0d25d8ee | ||
|
|
9c3eb13a14 |
37
.hgignore
@@ -3,7 +3,7 @@ syntax:glob
|
||||
.git
|
||||
.gitignore
|
||||
*.[568ao]
|
||||
*.a[568o]
|
||||
*.ao
|
||||
*.so
|
||||
*.pyc
|
||||
._*
|
||||
@@ -23,31 +23,34 @@ _test
|
||||
_testmain.go
|
||||
build.out
|
||||
test.out
|
||||
doc/tmpltohtml
|
||||
doc/articles/wiki/*.bin
|
||||
y.tab.[ch]
|
||||
doc/htmlgen
|
||||
doc/codelab/wiki/*.bin
|
||||
misc/cgo/life/run.out
|
||||
misc/cgo/stdio/run.out
|
||||
misc/cgo/testso/main
|
||||
misc/dashboard/builder/builder
|
||||
misc/dashboard/builder/gobuilder
|
||||
misc/goplay/goplay
|
||||
misc/osx/*.pkg
|
||||
misc/osx/*.dmg
|
||||
src/Make.inc
|
||||
src/cmd/6a/6a
|
||||
src/cmd/?a/y.output
|
||||
src/cmd/?l/enam.c
|
||||
src/cmd/cc/y.output
|
||||
src/cmd/dist/dist.dSYM
|
||||
src/cmd/gc/builtin.c
|
||||
src/cmd/gc/mkbuiltin1
|
||||
src/cmd/gc/opnames.h
|
||||
src/cmd/gc/y.output
|
||||
src/pkg/exp/norm/maketables
|
||||
src/pkg/exp/norm/maketesttables
|
||||
src/pkg/exp/norm/normregtest
|
||||
src/pkg/exp/ebnflint/ebnflint
|
||||
src/pkg/go/doc/headscan
|
||||
src/cmd/gc/y1.tab.c
|
||||
src/cmd/gc/yerr.h
|
||||
src/cmd/goinstall/syslist.go
|
||||
src/pkg/Make.deps
|
||||
src/pkg/exp/ogle/ogle
|
||||
src/pkg/go/build/syslist.go
|
||||
src/pkg/os/signal/unix.go
|
||||
src/pkg/runtime/*/asm.h
|
||||
src/pkg/runtime/goc2c
|
||||
src/pkg/runtime/mkversion
|
||||
src/pkg/runtime/z*
|
||||
src/pkg/runtime/runtime.acid.*
|
||||
src/pkg/runtime/runtime_defs.go
|
||||
src/pkg/runtime/version.go
|
||||
src/pkg/runtime/version_*.go
|
||||
src/pkg/unicode/maketables
|
||||
src/pkg/*.*/
|
||||
test/pass.out
|
||||
@@ -55,8 +58,6 @@ test/run.out
|
||||
test/times.out
|
||||
test/garbage/*.out
|
||||
goinstall.log
|
||||
last-change
|
||||
VERSION.cache
|
||||
|
||||
syntax:regexp
|
||||
^bin/
|
||||
|
||||
40
.hgtags
@@ -69,42 +69,4 @@ c81944152e973a917797679055b8fcdc70fbc802 weekly.2011-06-09
|
||||
dac76f0b1a18a5de5b54a1dc0b231aceaf1c8583 weekly.2011-06-16
|
||||
541c445d6c1353fbfa39df7dc4b0eb27558d1fc1 weekly.2011-06-23
|
||||
1b38d90eebcddefabb3901c5bb63c7e2b04a6ec5 release.r58
|
||||
16bfa562ba767aefd82e598da8b15ee4729e23b0 weekly.2011-07-07
|
||||
d292bc7886682d35bb391bf572be28656baee12d release.r58.1
|
||||
3c21f37b25a3f7a1726265c5339c8a7b0b329336 weekly.2011-07-19
|
||||
bb28251f6da4aca85658582c370c7df89d34efd4 weekly.2011-07-29
|
||||
d5785050f61d973fc36775f7bd2e26689529cb3e release.r59
|
||||
c17ce5ec06b4bd5cf6e7ff2ceb0a60c2e40e0b17 weekly.2011-08-10
|
||||
6eb2b9dbe489acb57a2bfc1de31ec2239ed94326 weekly.2011-08-17
|
||||
c934f6f5fe8b30b4b3210ee3f13669e6e4670c32 weekly.2011-09-01
|
||||
c77997547d546c36c7b969586a36de7ceda74e33 weekly.2011-09-07
|
||||
b0819469a6df6029a27192fe7b19a73d97404c63 release.r60
|
||||
8a09ce0cefc64deab4e6d1ed59a08a53e879bbee weekly.2011-09-16
|
||||
fd30c132d1bdeb79f8f111cb721fb1c78b767b27 release.r60.1
|
||||
d7322ae4d055a4cf3efaf842d0717a41acd85bac weekly.2011-09-21
|
||||
32a5db19629897641b2d488de4d1b998942ef80e release.r60.2
|
||||
3bdabf483805fbf0c7ef013fd09bfd6062b9d3f2 weekly.2011-10-06
|
||||
c1702f36df0397c19fc333571a771666029aa37e release.r60.3
|
||||
acaddf1cea75c059d19b20dbef35b20fb3f38954 release.r58.2
|
||||
6d7136d74b656ba6e1194853a9486375005227ef weekly.2011-10-18
|
||||
941b8015061a0f6480954821dd589c60dfe35ed1 weekly.2011-10-25
|
||||
7c1f789e6efd153951e85e3f28722fc69efc2af2 weekly.2011-10-26
|
||||
e69e528f2afc25a8334cfb9359fa4fcdf2a934b6 weekly.2011-11-01
|
||||
780c85032b174c9d4b42adf75d82bc85af7d78d1 weekly.2011-11-02
|
||||
f4397ad6e87c7ce5feac9b01686f1ebd6cbaac4e weekly.2011-11-08
|
||||
2f4482b89a6b5956828872137b6b96636cd904d3 weekly.2011-11-09
|
||||
b4a91b6933748db1a7150c06a1b55ad506e52906 weekly.2011-11-18
|
||||
80db2da6495a20ddff8305c236825811db8c8665 weekly.2011-12-01
|
||||
0beb796b4ef8747af601ed5ea6766d5b1340086b weekly.2011-12-02
|
||||
0c39eee85b0d1606b79c8ebcdeb3b67ed5849e39 weekly.2011-12-06
|
||||
82fdc445f2ff2c85043446eb84a19cc999dfcb95 weekly.2011-12-14
|
||||
4a82689277582a2a60f006e3f158985f2f8d1da3 weekly.2011-12-22
|
||||
354b17404643c0f1a710bdc48927dff02f203ae3 weekly.2012-01-15
|
||||
9f2be4fbbf690b9562c6e98b91daa0003f0913c7 weekly.2012-01-20
|
||||
1107a7d3cb075836387adfab5ce56d1b3e56637d weekly.2012-01-27
|
||||
52ba9506bd993663a0a033c2bd68699e25d061ab weekly.2012-02-07
|
||||
43cf9b39b6477d3144b0353ee91096e55db6107f weekly.2012-02-14
|
||||
96bd78e7d35e892113bdfa1bdc392d3a5f2e644b weekly.2012-02-22
|
||||
f4470a54e6dbcdd52d8d404e12e4754adcd2c948 weekly.2012-03-04
|
||||
3cdba7b0650c6c906ef3e782654f61701abd7dd2 weekly.2012-03-13
|
||||
bce220d0377405146527ab9478867cbc572a6886 weekly.2012-03-22
|
||||
1b38d90eebcddefabb3901c5bb63c7e2b04a6ec5 release
|
||||
|
||||
56
AUTHORS
@@ -11,15 +11,12 @@
|
||||
Abhinav Gupta <abhinav.g90@gmail.com>
|
||||
Adrian O'Grady <elpollouk@gmail.com>
|
||||
Albert Strasheim <fullung@gmail.com>
|
||||
Aleksandar Dezelin <dezelin@gmail.com>
|
||||
Alex Brainman <alex.brainman@gmail.com>
|
||||
Alexander Orlov <alexander.orlov@loxal.net>
|
||||
Alexander Reece <awreece@gmail.com>
|
||||
Alexey Borzenkov <snaury@gmail.com>
|
||||
Amrut Joshi <amrut.joshi@gmail.com>
|
||||
Andrei Vieru <euvieru@gmail.com>
|
||||
Andrew Balholm <andybalholm@gmail.com>
|
||||
Andrew Pritchard <awpritchard@gmail.com>
|
||||
Andrew Skiba <skibaa@gmail.com>
|
||||
Andrey Mirtchovski <mirtchovski@gmail.com>
|
||||
Andy Davis <andy@bigandian.com>
|
||||
@@ -31,32 +28,21 @@ Aron Nopanen <aron.nopanen@gmail.com>
|
||||
Arvindh Rajesh Tamilmani <art@a-30.net>
|
||||
Ben Olive <sionide21@gmail.com>
|
||||
Benny Siegert <bsiegert@gmail.com>
|
||||
Berengar Lehr <berengar.lehr@gmx.de>
|
||||
Bjorn Tipling <bjorn.tipling@gmail.com>
|
||||
Blake Mizerany <blake.mizerany@gmail.com>
|
||||
Bobby Powers <bobbypowers@gmail.com>
|
||||
Caine Tighe <arctanofyourface@gmail.com>
|
||||
Charles L. Dorian <cldorian@gmail.com>
|
||||
Chris Dollin <ehog.hedge@gmail.com>
|
||||
Chris Farmiloe <chrisfarms@gmail.com>
|
||||
Chris Jones <chris@cjones.org>
|
||||
Chris Lennert <calennert@gmail.com>
|
||||
Christian Himpel <chressie@googlemail.com>
|
||||
Christoph Hack <christoph@tux21b.org>
|
||||
Christopher Nielsen <m4dh4tt3r@gmail.com>
|
||||
Christopher Redden <christopher.redden@gmail.com>
|
||||
Christopher Wedgwood <cw@f00f.org>
|
||||
Clement Skau <clementskau@gmail.com>
|
||||
Conrad Meyer <cemeyer@cs.washington.edu>
|
||||
Corey Thomasson <cthom.lists@gmail.com>
|
||||
Damian Gryski <dgryski@gmail.com>
|
||||
Dan Sinclair <dan.sinclair@gmail.com>
|
||||
Daniel Fleischman <danielfleischman@gmail.com>
|
||||
Daniel Krech <eikeon@eikeon.com>
|
||||
Daniel Theophanes <kardianos@gmail.com>
|
||||
Darren Elwood <darren@textnode.com>
|
||||
Dave Cheney <dave@cheney.net>
|
||||
David du Colombier <0intro@gmail.com>
|
||||
David Forsythe <dforsythe@gmail.com>
|
||||
David G. Andersen <dave.andersen@gmail.com>
|
||||
David Jakob Fritz <david.jakob.fritz@gmail.com>
|
||||
@@ -66,51 +52,36 @@ Devon H. O'Dell <devon.odell@gmail.com>
|
||||
Dmitry Chestnykh <dchest@gmail.com>
|
||||
Eden Li <eden.li@gmail.com>
|
||||
Eivind Uggedal <eivind@uggedal.com>
|
||||
Emil Hessman <c.emil.hessman@gmail.com>
|
||||
Eoghan Sherry <ejsherry@gmail.com>
|
||||
Eric Clark <zerohp@gmail.com>
|
||||
Eric Eisner <eric.d.eisner@gmail.com>
|
||||
Esko Luontola <esko.luontola@gmail.com>
|
||||
Evan Shaw <chickencha@gmail.com>
|
||||
Fan Hongjian <fan.howard@gmail.com>
|
||||
Fazlul Shahriar <fshahriar@gmail.com>
|
||||
Firmansyah Adiputra <frm.adiputra@gmail.com>
|
||||
Florian Uekermann <florian@uekermann-online.de>
|
||||
Florian Weimer <fw@deneb.enyo.de>
|
||||
Francisco Souza <franciscossouza@gmail.com>
|
||||
Gary Burd <gary@beagledreams.com>
|
||||
Gideon Jan-Wessel Redelinghuys <gjredelinghuys@gmail.com>
|
||||
Giles Lean <giles.lean@pobox.com>
|
||||
Google Inc.
|
||||
Graham Miller <graham.miller@gmail.com>
|
||||
Gustav Paul <gustav.paul@gmail.com>
|
||||
Gustavo Niemeyer <gustavo@niemeyer.net>
|
||||
Gwenael Treguier <gwenn.kahz@gmail.com>
|
||||
Harley Laue <losinggeneration@gmail.com>
|
||||
Hector Chu <hectorchu@gmail.com>
|
||||
Hong Ruiqi <hongruiqi@gmail.com>
|
||||
Icarus Sparry <golang@icarus.freeuk.com>
|
||||
Ingo Oeser <nightlyone@googlemail.com>
|
||||
Isaac Wagner <ibw@isaacwagner.me>
|
||||
James Fysh <james.fysh@gmail.com>
|
||||
James Meneghello <rawrz0r@gmail.com>
|
||||
James P. Cooper <jamespcooper@gmail.com>
|
||||
James Toy <nil@opensesame.st>
|
||||
James Whitehead <jnwhiteh@gmail.com>
|
||||
Jan H. Hosang <jan.hosang@gmail.com>
|
||||
Jan Mercl <befelemepeseveze@gmail.com>
|
||||
Jan Newmarch <jan.newmarch@gmail.com>
|
||||
Jani Monoses <jani.monoses@ubuntu.com>
|
||||
Jaroslavas Počepko <jp@webmaster.ms>
|
||||
Jeff Hodges <jeff@somethingsimilar.com>
|
||||
Jeff R. Allen <jra@nella.org>
|
||||
Jeremy Jackins <jeremyjackins@gmail.com>
|
||||
Jim McGrath <jimmc2@gmail.com>
|
||||
Joe Poirier <jdpoirier@gmail.com>
|
||||
John Asmuth <jasmuth@gmail.com>
|
||||
Jonathan Mark <jhmark@xenops.com>
|
||||
Jonathan Wills <runningwild@gmail.com>
|
||||
Jongmin Kim <atomaths@gmail.com>
|
||||
Jose Luis Vázquez González <josvazg@gmail.com>
|
||||
Josh Goebel <dreamer3@gmail.com>
|
||||
Jukka-Pekka Kekkonen <karatepekka@gmail.com>
|
||||
@@ -123,40 +94,28 @@ Ken Rockot <ken@oz.gs>
|
||||
Kevin Ballard <kevin@sb.org>
|
||||
Kyle Consalus <consalus@gmail.com>
|
||||
Kyle Lemons <kyle@kylelemons.net>
|
||||
Lai Jiangshan <eag0628@gmail.com>
|
||||
Lorenzo Stoakes <lstoakes@gmail.com>
|
||||
Luca Greco <luca.greco@alcacoop.it>
|
||||
Lucio De Re <lucio.dere@gmail.com>
|
||||
Luit van Drongelen <luitvd@gmail.com>
|
||||
Markus Duft <markus.duft@salomon.at>
|
||||
Martin Neubauer <m.ne@gmx.net>
|
||||
Mateusz Czapliński <czapkofan@gmail.com>
|
||||
Mathieu Lonjaret <mathieu.lonjaret@gmail.com>
|
||||
Matthew Horsnell <matthew.horsnell@gmail.com>
|
||||
Micah Stetson <micah.stetson@gmail.com>
|
||||
Michael Elkins <michael.elkins@gmail.com>
|
||||
Michael Hoisie <hoisie@gmail.com>
|
||||
Michał Derkacz <ziutek@lnet.pl>
|
||||
Miek Gieben <miek@miek.nl>
|
||||
Mikael Tillenius <mikti42@gmail.com>
|
||||
Mike Rosset <mike.rosset@gmail.com>
|
||||
Miki Tebeka <miki.tebeka@gmail.com>
|
||||
Mikio Hara <mikioh.mikioh@gmail.com>
|
||||
Mikkel Krautz <mikkel@krautz.dk>
|
||||
Moriyoshi Koizumi <mozo@mozo.jp>
|
||||
Môshe van der Sterre <moshevds@gmail.com>
|
||||
ngmoco, LLC
|
||||
Nicholas Waples <nwaples@gmail.com>
|
||||
Nigel Kerr <nigel.kerr@gmail.com>
|
||||
Olivier Antoine <olivier.antoine@gmail.com>
|
||||
Olivier Duperray <duperray.olivier@gmail.com>
|
||||
Padraig Kitterick <padraigkitterick@gmail.com>
|
||||
Paolo Giarrusso <p.giarrusso@gmail.com>
|
||||
Pascal S. de Kloe <pascal@quies.net>
|
||||
Patrick Gavlin <pgavlin@gmail.com>
|
||||
Patrick Mylund Nielsen <patrick@patrickmn.com>
|
||||
Paul Lalonde <paul.a.lalonde@gmail.com>
|
||||
Paul Sbarra <Sbarra.Paul@gmail.com>
|
||||
Petar Maymounkov <petarm@gmail.com>
|
||||
Peter Froehlich <peter.hans.froehlich@gmail.com>
|
||||
Peter Mundy <go.peter.90@gmail.com>
|
||||
@@ -164,34 +123,24 @@ Peter Williams <pwil3058@gmail.com>
|
||||
Pieter Droogendijk <pieter@binky.org.uk>
|
||||
Quan Yong Zhai <qyzhai@gmail.com>
|
||||
Raif S. Naffah <go@naffah-raif.name>
|
||||
Rémy Oudompheng <oudomphe@phare.normalesup.org>
|
||||
Risto Jaakko Saarelma <rsaarelm@gmail.com>
|
||||
Robert Figueiredo <robfig@gmail.com>
|
||||
Robert Hencke <robert.hencke@gmail.com>
|
||||
Roger Pau Monné <royger@gmail.com>
|
||||
Roger Peppe <rogpeppe@gmail.com>
|
||||
Ron Minnich <rminnich@gmail.com>
|
||||
Ross Light <rlight2@gmail.com>
|
||||
Ryan Hitchman <hitchmanr@gmail.com>
|
||||
Sanjay Menakuru <balasanjay@gmail.com>
|
||||
Scott Lawrence <bytbox@gmail.com>
|
||||
Sebastien Binet <seb.binet@gmail.com>
|
||||
Sébastien Paolacci <sebastien.paolacci@gmail.com>
|
||||
Sergei Skorobogatov <skorobo@rambler.ru>
|
||||
Sergey 'SnakE' Gromov <snake.scaly@gmail.com>
|
||||
Sergio Luis O. B. Correia <sergio@larces.uece.br>
|
||||
Shenghou Ma <minux.ma@gmail.com>
|
||||
Spring Mc <heresy.mc@gmail.com>
|
||||
Stefan Nilsson <snilsson@nada.kth.se> <trolleriprofessorn@gmail.com>
|
||||
Stefan Nilsson <snilsson@nada.kth.se>
|
||||
Stephen Weinberg <stephen@q5comm.com>
|
||||
Sven Almgren <sven@tras.se>
|
||||
Szabolcs Nagy <nsz@port70.net>
|
||||
Tarmigan Casebolt <tarmigan@gmail.com>
|
||||
Taru Karttunen <taruti@taruti.net>
|
||||
Timo Savola <timo.savola@gmail.com>
|
||||
Tor Andersson <tor.andersson@gmail.com>
|
||||
Ugorji Nwoke <ugorji@gmail.com>
|
||||
Vadim Vygonets <unixdj@gmail.com>
|
||||
Vincent Ambo <tazjin@googlemail.com>
|
||||
Vincent Vanackere <vincent.vanackere@gmail.com>
|
||||
Vinu Rajashekhar <vinutheraj@gmail.com>
|
||||
@@ -199,9 +148,6 @@ Volker Dobler <dr.volker.dobler@gmail.com>
|
||||
Wei Guangjing <vcc.163@gmail.com>
|
||||
William Josephson <wjosephson@gmail.com>
|
||||
Yasuhiro Matsumoto <mattn.jp@gmail.com>
|
||||
Yissakhar Z. Beck <yissakhar.beck@gmail.com>
|
||||
Yongjian Xu <i3dmaster@gmail.com>
|
||||
Yoshiyuki Kanno <nekotaroh@gmail.com> <yoshiyuki.kanno@stoic.co.jp>
|
||||
Yuusei Kuwana <kuwana@kumama.org>
|
||||
Yuval Pavel Zholkover <paulzhol@gmail.com>
|
||||
Ziad Hatahet <hatahet@gmail.com>
|
||||
|
||||
75
CONTRIBUTORS
@@ -35,18 +35,13 @@ Abhinav Gupta <abhinav.g90@gmail.com>
|
||||
Adam Langley <agl@golang.org>
|
||||
Adrian O'Grady <elpollouk@gmail.com>
|
||||
Albert Strasheim <fullung@gmail.com>
|
||||
Aleksandar Dezelin <dezelin@gmail.com>
|
||||
Alex Brainman <alex.brainman@gmail.com>
|
||||
Alexander Orlov <alexander.orlov@loxal.net>
|
||||
Alexander Reece <awreece@gmail.com>
|
||||
Alexandru Moșoi <brtzsnr@gmail.com>
|
||||
Alexey Borzenkov <snaury@gmail.com>
|
||||
Amrut Joshi <amrut.joshi@gmail.com>
|
||||
Andrea Spadaccini <spadaccio@google.com>
|
||||
Andrei Vieru <euvieru@gmail.com>
|
||||
Andrew Balholm <andybalholm@gmail.com>
|
||||
Andrew Gerrand <adg@golang.org>
|
||||
Andrew Pritchard <awpritchard@gmail.com>
|
||||
Andrew Skiba <skibaa@gmail.com>
|
||||
Andrey Mirtchovski <mirtchovski@gmail.com>
|
||||
Andy Davis <andy@bigandian.com>
|
||||
@@ -59,45 +54,32 @@ Arvindh Rajesh Tamilmani <art@a-30.net>
|
||||
Austin Clements <aclements@csail.mit.edu>
|
||||
Balazs Lecz <leczb@google.com>
|
||||
Ben Eitzen <eitzenb@golang.org>
|
||||
Ben Fried <ben.fried@gmail.com>
|
||||
Ben Lynn <benlynn@gmail.com>
|
||||
Ben Olive <sionide21@gmail.com>
|
||||
Benny Siegert <bsiegert@gmail.com>
|
||||
Berengar Lehr <Berengar.Lehr@gmx.de>
|
||||
Bill Neubauer <wcn@golang.org> <wcn@google.com>
|
||||
Bjorn Tipling <bjorn.tipling@gmail.com>
|
||||
Blake Mizerany <blake.mizerany@gmail.com>
|
||||
Bobby Powers <bobbypowers@gmail.com>
|
||||
Brad Fitzpatrick <bradfitz@golang.org> <bradfitz@gmail.com>
|
||||
Brendan O'Dea <bod@golang.org>
|
||||
Caine Tighe <arctanofyourface@gmail.com>
|
||||
Cary Hull <chull@google.com>
|
||||
Charles L. Dorian <cldorian@gmail.com>
|
||||
Chris Dollin <ehog.hedge@gmail.com>
|
||||
Chris Farmiloe <chrisfarms@gmail.com>
|
||||
Chris Hundt <hundt@google.com>
|
||||
Chris Jones <chris@cjones.org> <chris.jones.yar@gmail.com>
|
||||
Chris Lennert <calennert@gmail.com>
|
||||
Christian Himpel <chressie@googlemail.com> <chressie@gmail.com>
|
||||
Christoph Hack <christoph@tux21b.org>
|
||||
Christopher Nielsen <m4dh4tt3r@gmail.com>
|
||||
Christopher Redden <christopher.redden@gmail.com>
|
||||
Christopher Wedgwood <cw@f00f.org>
|
||||
Clement Skau <clementskau@gmail.com>
|
||||
Conrad Meyer <cemeyer@cs.washington.edu>
|
||||
Corey Thomasson <cthom.lists@gmail.com>
|
||||
Damian Gryski <dgryski@gmail.com>
|
||||
Dan Sinclair <dan.sinclair@gmail.com>
|
||||
Daniel Fleischman <danielfleischman@gmail.com>
|
||||
Daniel Krech <eikeon@eikeon.com>
|
||||
Daniel Nadasi <dnadasi@google.com>
|
||||
Daniel Theophanes <kardianos@gmail.com>
|
||||
Darren Elwood <darren@textnode.com>
|
||||
Dave Cheney <dave@cheney.net>
|
||||
Dave Grijalva <dgrijalva@ngmoco.com>
|
||||
David Anderson <danderson@google.com>
|
||||
David Crawshaw <david.crawshaw@zentus.com> <crawshaw@google.com>
|
||||
David du Colombier <0intro@gmail.com>
|
||||
David Crawshaw <david.crawshaw@zentus.com>
|
||||
David Forsythe <dforsythe@gmail.com>
|
||||
David G. Andersen <dave.andersen@gmail.com>
|
||||
David Jakob Fritz <david.jakob.fritz@gmail.com>
|
||||
@@ -109,63 +91,44 @@ Dmitriy Vyukov <dvyukov@google.com>
|
||||
Dmitry Chestnykh <dchest@gmail.com>
|
||||
Eden Li <eden.li@gmail.com>
|
||||
Eivind Uggedal <eivind@uggedal.com>
|
||||
Emil Hessman <c.emil.hessman@gmail.com>
|
||||
Eoghan Sherry <ejsherry@gmail.com>
|
||||
Eric Clark <zerohp@gmail.com>
|
||||
Eric Eisner <eric.d.eisner@gmail.com>
|
||||
Esko Luontola <esko.luontola@gmail.com>
|
||||
Evan Martin <evan.martin@gmail.com>
|
||||
Evan Shaw <chickencha@gmail.com>
|
||||
Fan Hongjian <fan.howard@gmail.com>
|
||||
Fazlul Shahriar <fshahriar@gmail.com>
|
||||
Firmansyah Adiputra <frm.adiputra@gmail.com>
|
||||
Florian Uekermann <florian@uekermann-online.de> <f1@uekermann-online.de>
|
||||
Florian Weimer <fw@deneb.enyo.de>
|
||||
Francisco Souza <franciscossouza@gmail.com>
|
||||
Fumitoshi Ukai <ukai@google.com>
|
||||
Gary Burd <gary@beagledreams.com> <gary.burd@gmail.com>
|
||||
Gideon Jan-Wessel Redelinghuys <gjredelinghuys@gmail.com>
|
||||
Giles Lean <giles.lean@pobox.com>
|
||||
Graham Miller <graham.miller@gmail.com>
|
||||
Gustav Paul <gustav.paul@gmail.com>
|
||||
Gustavo Niemeyer <gustavo@niemeyer.net> <n13m3y3r@gmail.com>
|
||||
Gwenael Treguier <gwenn.kahz@gmail.com>
|
||||
Harley Laue <losinggeneration@gmail.com>
|
||||
Hector Chu <hectorchu@gmail.com>
|
||||
Hong Ruiqi <hongruiqi@gmail.com>
|
||||
Ian Lance Taylor <iant@golang.org>
|
||||
Icarus Sparry <golang@icarus.freeuk.com>
|
||||
Ingo Oeser <nightlyone@googlemail.com> <nightlyone@gmail.com>
|
||||
Isaac Wagner <ibw@isaacwagner.me>
|
||||
Ivan Krasin <krasin@golang.org>
|
||||
Jacob Baskin <jbaskin@google.com>
|
||||
James Aguilar <jaguilar@google.com>
|
||||
James Fysh <james.fysh@gmail.com>
|
||||
James Meneghello <rawrz0r@gmail.com>
|
||||
James P. Cooper <jamespcooper@gmail.com>
|
||||
James Toy <nil@opensesame.st>
|
||||
James Whitehead <jnwhiteh@gmail.com>
|
||||
Jamie Gennis <jgennis@google.com> <jgennis@gmail.com>
|
||||
Jamie Gennis <jgennis@google.com>
|
||||
Jan H. Hosang <jan.hosang@gmail.com>
|
||||
Jan Mercl <befelemepeseveze@gmail.com>
|
||||
Jan Newmarch <jan.newmarch@gmail.com>
|
||||
Jani Monoses <jani.monoses@ubuntu.com> <jani.monoses@gmail.com>
|
||||
Jaroslavas Počepko <jp@webmaster.ms>
|
||||
Jeff Hodges <jeff@somethingsimilar.com>
|
||||
Jeff R. Allen <jra@nella.org> <jeff.allen@gmail.com>
|
||||
Jeremy Jackins <jeremyjackins@gmail.com>
|
||||
Jim McGrath <jimmc2@gmail.com>
|
||||
Joe Poirier <jdpoirier@gmail.com>
|
||||
Joel Sing <jsing@google.com>
|
||||
Johan Euphrosine <proppy@google.com>
|
||||
John Asmuth <jasmuth@gmail.com>
|
||||
John Beisley <huin@google.com>
|
||||
John DeNero <denero@google.com>
|
||||
Jonathan Allie <jonallie@google.com>
|
||||
Jonathan Mark <jhmark@xenops.com> <jhmark000@gmail.com>
|
||||
Jonathan Pittman <jmpittman@google.com> <jonathan.mark.pittman@gmail.com>
|
||||
Jonathan Wills <runningwild@gmail.com>
|
||||
Jongmin Kim <atomaths@gmail.com>
|
||||
Jos Visser <josv@google.com>
|
||||
Jose Luis Vázquez González <josvazg@gmail.com>
|
||||
Josh Goebel <dreamer3@gmail.com>
|
||||
@@ -181,11 +144,8 @@ Kevin Ballard <kevin@sb.org>
|
||||
Kirklin McDonald <kirklin.mcdonald@gmail.com>
|
||||
Kyle Consalus <consalus@gmail.com>
|
||||
Kyle Lemons <kyle@kylelemons.net> <kevlar@google.com>
|
||||
Lai Jiangshan <eag0628@gmail.com>
|
||||
Larry Hosken <lahosken@golang.org>
|
||||
Lorenzo Stoakes <lstoakes@gmail.com>
|
||||
Louis Kruger <louisk@google.com>
|
||||
Luca Greco <luca.greco@alcacoop.it>
|
||||
Lucio De Re <lucio.dere@gmail.com>
|
||||
Luit van Drongelen <luitvd@gmail.com>
|
||||
Luuk van Dijk <lvd@golang.org> <lvd@google.com>
|
||||
@@ -193,24 +153,15 @@ Marcel van Lohuizen <mpvl@golang.org>
|
||||
Mark Zavislak <zavislak@google.com>
|
||||
Markus Duft <markus.duft@salomon.at>
|
||||
Martin Neubauer <m.ne@gmx.net>
|
||||
Mateusz Czapliński <czapkofan@gmail.com>
|
||||
Mathieu Lonjaret <mathieu.lonjaret@gmail.com>
|
||||
Matt Jones <mrjones@google.com>
|
||||
Matthew Horsnell <matthew.horsnell@gmail.com>
|
||||
Maxim Pimenov <mpimenov@google.com>
|
||||
Maxim Ushakov <ushakov@google.com>
|
||||
Micah Stetson <micah.stetson@gmail.com>
|
||||
Michael Elkins <michael.elkins@gmail.com>
|
||||
Michael Hoisie <hoisie@gmail.com>
|
||||
Michael Shields <mshields@google.com>
|
||||
Michael T. Jones <mtj@google.com> <michael.jones@gmail.com>
|
||||
Michał Derkacz <ziutek@lnet.pl>
|
||||
Miek Gieben <miek@miek.nl> <remigius.gieben@gmail.com>
|
||||
Mikael Tillenius <mikti42@gmail.com>
|
||||
Mike Rosset <mike.rosset@gmail.com>
|
||||
Mike Samuel <mikesamuel@gmail.com>
|
||||
Mike Solomon <msolo@gmail.com>
|
||||
Miki Tebeka <miki.tebeka@gmail.com>
|
||||
Mikio Hara <mikioh.mikioh@gmail.com>
|
||||
Mikkel Krautz <mikkel@krautz.dk> <krautz@gmail.com>
|
||||
Moriyoshi Koizumi <mozo@mozo.jp>
|
||||
@@ -219,15 +170,11 @@ Nicholas Waples <nwaples@gmail.com>
|
||||
Nigel Kerr <nigel.kerr@gmail.com>
|
||||
Nigel Tao <nigeltao@golang.org>
|
||||
Olivier Antoine <olivier.antoine@gmail.com>
|
||||
Olivier Duperray <duperray.olivier@gmail.com>
|
||||
Padraig Kitterick <padraigkitterick@gmail.com>
|
||||
Paolo Giarrusso <p.giarrusso@gmail.com>
|
||||
Pascal S. de Kloe <pascal@quies.net>
|
||||
Patrick Gavlin <pgavlin@gmail.com>
|
||||
Patrick Mylund Nielsen <patrick@patrickmn.com>
|
||||
Paul Borman <borman@google.com>
|
||||
Paul Lalonde <paul.a.lalonde@gmail.com>
|
||||
Paul Sbarra <Sbarra.Paul@gmail.com>
|
||||
Petar Maymounkov <petarm@gmail.com>
|
||||
Peter Froehlich <peter.hans.froehlich@gmail.com>
|
||||
Peter McKenzie <petermck@google.com>
|
||||
@@ -239,44 +186,33 @@ Pieter Droogendijk <pieter@binky.org.uk>
|
||||
Quan Yong Zhai <qyzhai@gmail.com>
|
||||
Raif S. Naffah <go@naffah-raif.name>
|
||||
Raph Levien <raph@google.com>
|
||||
Rémy Oudompheng <oudomphe@phare.normalesup.org> <remyoudompheng@gmail.com>
|
||||
Risto Jaakko Saarelma <rsaarelm@gmail.com>
|
||||
Rob Pike <r@golang.org>
|
||||
Robert Figueiredo <robfig@gmail.com>
|
||||
Robert Griesemer <gri@golang.org>
|
||||
Robert Hencke <robert.hencke@gmail.com>
|
||||
Roger Pau Monné <royger@gmail.com>
|
||||
Roger Peppe <rogpeppe@gmail.com>
|
||||
Ron Minnich <rminnich@gmail.com>
|
||||
Ross Light <rlight2@gmail.com>
|
||||
Russ Cox <rsc@golang.org>
|
||||
Ryan Hitchman <hitchmanr@gmail.com>
|
||||
Sam Thorogood <thorogood@google.com> <sam.thorogood@gmail.com>
|
||||
Sameer Ajmani <sameer@golang.org> <ajmani@gmail.com>
|
||||
Sanjay Menakuru <balasanjay@gmail.com>
|
||||
Sameer Ajmani <ajmani@gmail.com>
|
||||
Scott Lawrence <bytbox@gmail.com>
|
||||
Scott Schwartz <scotts@golang.org>
|
||||
Sebastien Binet <seb.binet@gmail.com>
|
||||
Sébastien Paolacci <sebastien.paolacci@gmail.com>
|
||||
Sergei Skorobogatov <skorobo@rambler.ru>
|
||||
Sergey 'SnakE' Gromov <snake.scaly@gmail.com>
|
||||
Sergio Luis O. B. Correia <sergio@larces.uece.br>
|
||||
Shenghou Ma <minux.ma@gmail.com>
|
||||
Spring Mc <heresy.mc@gmail.com>
|
||||
Stefan Nilsson <snilsson@nada.kth.se> <trolleriprofessorn@gmail.com>
|
||||
Stefan Nilsson <snilsson@nada.kth.se>
|
||||
Stephen Ma <stephenm@golang.org>
|
||||
Stephen Weinberg <stephen@q5comm.com>
|
||||
Sugu Sougoumarane <ssougou@gmail.com>
|
||||
Sven Almgren <sven@tras.se>
|
||||
Szabolcs Nagy <nsz@port70.net>
|
||||
Tarmigan Casebolt <tarmigan@gmail.com>
|
||||
Taru Karttunen <taruti@taruti.net>
|
||||
Timo Savola <timo.savola@gmail.com>
|
||||
Tom Szymanski <tgs@google.com>
|
||||
Tor Andersson <tor.andersson@gmail.com>
|
||||
Trevor Strohman <trevor.strohman@gmail.com>
|
||||
Ugorji Nwoke <ugorji@gmail.com>
|
||||
Vadim Vygonets <unixdj@gmail.com>
|
||||
Vincent Ambo <tazjin@googlemail.com>
|
||||
Vincent Vanackere <vincent.vanackere@gmail.com>
|
||||
Vinu Rajashekhar <vinutheraj@gmail.com>
|
||||
@@ -286,10 +222,7 @@ Wei Guangjing <vcc.163@gmail.com>
|
||||
William Chan <willchan@chromium.org>
|
||||
William Josephson <wjosephson@gmail.com>
|
||||
Yasuhiro Matsumoto <mattn.jp@gmail.com>
|
||||
Yissakhar Z. Beck <yissakhar.beck@gmail.com>
|
||||
Yongjian Xu <i3dmaster@gmail.com>
|
||||
Yoshiyuki Kanno <nekotaroh@gmail.com> <yoshiyuki.kanno@stoic.co.jp>
|
||||
Yuusei Kuwana <kuwana@kumama.org>
|
||||
Yuval Pavel Zholkover <paulzhol@gmail.com>
|
||||
Yves Junqueira <yves.junqueira@gmail.com>
|
||||
Ziad Hatahet <hatahet@gmail.com>
|
||||
|
||||
2
LICENSE
@@ -1,4 +1,4 @@
|
||||
Copyright (c) 2012 The Go Authors. All rights reserved.
|
||||
Copyright (c) 2009 The Go Authors. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
|
||||
24534
api/go1.txt
BIN
doc/GoCourseDay1.pdf
Normal file
BIN
doc/GoCourseDay2.pdf
Normal file
BIN
doc/GoCourseDay3.pdf
Normal file
26
doc/Makefile
@@ -2,26 +2,10 @@
|
||||
# Use of this source code is governed by a BSD-style
|
||||
# license that can be found in the LICENSE file.
|
||||
|
||||
RAWHTML=\
|
||||
articles/defer_panic_recover.rawhtml\
|
||||
articles/error_handling.rawhtml\
|
||||
articles/slices_usage_and_internals.rawhtml\
|
||||
articles/laws_of_reflection.rawhtml\
|
||||
articles/c_go_cgo.rawhtml\
|
||||
articles/concurrency_patterns.rawhtml\
|
||||
articles/godoc_documenting_go_code.rawhtml\
|
||||
articles/gobs_of_data.rawhtml\
|
||||
articles/json_and_go.rawhtml\
|
||||
articles/json_rpc_tale_of_interfaces.rawhtml\
|
||||
articles/image_draw.rawhtml\
|
||||
articles/image_package.rawhtml\
|
||||
effective_go.rawhtml\
|
||||
go1.rawhtml\
|
||||
include ../src/Make.inc
|
||||
|
||||
all: $(RAWHTML)
|
||||
TARG=htmlgen
|
||||
GOFILES=\
|
||||
htmlgen.go\
|
||||
|
||||
%.rawhtml: %.html
|
||||
godoc -url /doc/$< >$@
|
||||
|
||||
clean:
|
||||
rm -f $(RAWHTML)
|
||||
include ../src/Make.cmd
|
||||
|
||||
205
doc/all.css
Normal file
@@ -0,0 +1,205 @@
|
||||
/* General Styles */
|
||||
body {
|
||||
font-family: "Bitstream Vera Sans", Verdana, sans-serif;
|
||||
font-size: 81.25%;
|
||||
line-height: 1.23em;
|
||||
padding: 0;
|
||||
margin: 1.23em;
|
||||
background: white;
|
||||
color: black;
|
||||
}
|
||||
a {
|
||||
color: #04a;
|
||||
text-decoration: none;
|
||||
}
|
||||
a:visited {
|
||||
color: #04a;
|
||||
}
|
||||
a:hover {
|
||||
color: #a40;
|
||||
text-decoration: underline;
|
||||
}
|
||||
a:active {
|
||||
color: #c00;
|
||||
}
|
||||
code, pre {
|
||||
font-size: 1.2em;
|
||||
}
|
||||
pre {
|
||||
background: #F0F0F0;
|
||||
padding: 0.5em 1em;
|
||||
}
|
||||
|
||||
/* Top bar */
|
||||
#container {
|
||||
width: 100%;
|
||||
margin: auto;
|
||||
}
|
||||
#topnav {
|
||||
height: 55px;
|
||||
background: url(/doc/logo.png) no-repeat top left;
|
||||
}
|
||||
a#logo-box {
|
||||
display: block;
|
||||
height: 55px;
|
||||
}
|
||||
h1#title {
|
||||
display: none;
|
||||
}
|
||||
#nav-main {
|
||||
float: right;
|
||||
width: 500px;
|
||||
margin-top: -5px;
|
||||
text-align: center;
|
||||
}
|
||||
#nav-main ul {
|
||||
padding-left: 0;
|
||||
margin-left: 0;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
#nav-main li a {
|
||||
display: inline;
|
||||
display: inline-block;
|
||||
padding: .46em .62em .38em .62em;
|
||||
}
|
||||
#nav-main li a:link,
|
||||
#nav-main li a:visited {
|
||||
color: #000;
|
||||
}
|
||||
#nav-main li {
|
||||
display: inline;
|
||||
display: inline-block;
|
||||
background: #e6e6e6 url(/doc/button_background.png) repeat-x;
|
||||
border: solid 1px #999;
|
||||
margin-left: -1px;
|
||||
text-shadow: #fff 0 1px 0;
|
||||
box-shadow: 0 1px 1px #ccc;
|
||||
-moz-box-shadow: 0 1px 1px #ccc;
|
||||
-webkit-box-shadow: 0 1px 1px #ccc;
|
||||
}
|
||||
#nav-main li:first-child {
|
||||
-moz-border-top-left-radius: 4px;
|
||||
border-top-left-radius: 4px;
|
||||
-moz-border-bottom-left-radius: 4px;
|
||||
border-bottom-left-radius: 4px;
|
||||
}
|
||||
#nav-main li:last-child {
|
||||
-moz-border-top-right-radius: 4px;
|
||||
border-top-right-radius: 4px;
|
||||
-moz-border-bottom-right-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
}
|
||||
#nav-main .quickref {
|
||||
color: #444;
|
||||
}
|
||||
#nav-main .quickref .sep {
|
||||
color: #999;
|
||||
}
|
||||
#search {
|
||||
width: 120px;
|
||||
margin-left: 0.5em;
|
||||
}
|
||||
#search.inactive {
|
||||
text-align: center;
|
||||
color: #444;
|
||||
}
|
||||
|
||||
/* Footer */
|
||||
#site-info {
|
||||
position: relative;
|
||||
text-align: center;
|
||||
}
|
||||
#site-info, #site-info a:link, #site-info a:visited {
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
/* Content */
|
||||
#content {
|
||||
clear: both;
|
||||
padding: 0;
|
||||
position: relative;
|
||||
margin-top: 1.5em;
|
||||
margin-bottom: 1.5em;
|
||||
border-top: solid 1px #aaa;
|
||||
border-bottom: solid 1px #aaa;
|
||||
}
|
||||
.left-column {
|
||||
width: 49%;
|
||||
float: left;
|
||||
}
|
||||
.right-column {
|
||||
width: 49%;
|
||||
float: right;
|
||||
}
|
||||
.end-columns {
|
||||
clear: both;
|
||||
}
|
||||
#content h1 {
|
||||
margin-bottom: -0em;
|
||||
padding: 0;
|
||||
}
|
||||
#content h2 {
|
||||
border-top: 2px solid #ddd;
|
||||
padding: 8px 0;
|
||||
margin: 1.5em 0 0;
|
||||
}
|
||||
#content .subtitle {
|
||||
margin-top: 1em;
|
||||
display: block;
|
||||
}
|
||||
.navtop a {
|
||||
font-weight: normal; font-size: 7pt;
|
||||
float: right; color: #999;
|
||||
}
|
||||
|
||||
/* Content and Code Highlighting */
|
||||
pre.ebnf, pre.grammar {
|
||||
background: #FFFFE0;
|
||||
}
|
||||
span.ln {
|
||||
font-size: 80%;
|
||||
color: #777777;
|
||||
}
|
||||
span.comment {
|
||||
color: #002090;
|
||||
}
|
||||
span.highlight {
|
||||
background: #FF9900;
|
||||
font-weight: bold;
|
||||
}
|
||||
span.highlight-comment {
|
||||
background: #FF9900;
|
||||
font-weight: bold;
|
||||
color: #002090;
|
||||
}
|
||||
span.selection {
|
||||
background: #FFFF00
|
||||
}
|
||||
span.selection-comment {
|
||||
color: #002090;
|
||||
background: #FFFF00
|
||||
}
|
||||
span.selection-highlight {
|
||||
background: #FF9900;
|
||||
font-weight: bold;
|
||||
}
|
||||
span.selection-highlight-comment {
|
||||
background: #FF9900;
|
||||
font-weight: bold;
|
||||
color: #002090;
|
||||
}
|
||||
span.alert {
|
||||
color: #D00000;
|
||||
}
|
||||
#nav table {
|
||||
width: 100%;
|
||||
}
|
||||
.detail {
|
||||
padding: 0.25em 1em;
|
||||
background: #F4F4F4;
|
||||
}
|
||||
sup.new {
|
||||
color: red;
|
||||
font-size: 8px;
|
||||
line-height: 0;
|
||||
}
|
||||
@@ -1,180 +0,0 @@
|
||||
<!--{
|
||||
"Title": "C? Go? Cgo!",
|
||||
"Template": true
|
||||
}-->
|
||||
|
||||
<p>
|
||||
Cgo lets Go packages call C code. Given a Go source file written with some
|
||||
special features, cgo outputs Go and C files that can be combined into a
|
||||
single Go package.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
To lead with an example, here's a Go package that provides two functions -
|
||||
<code>Random</code> and <code>Seed</code> - that wrap C's <code>random</code>
|
||||
and <code>srandom</code> functions.
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/cgo1.go" `/package rand/` `/END/`}}
|
||||
|
||||
<p>
|
||||
Let's look at what's happening here, starting with the import statement.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The <code>rand</code> package imports <code>"C"</code>, but you'll find there's
|
||||
no such package in the standard Go library. That's because <code>C</code> is a
|
||||
"pseudo-package", a special name interpreted by cgo as a reference to C's
|
||||
name space.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The <code>rand</code> package contains four references to the <code>C</code>
|
||||
package: the calls to <code>C.random</code> and <code>C.srandom</code>, the
|
||||
conversion <code>C.uint(i)</code>, and the <code>import</code> statement.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The <code>Random</code> function calls the standard C library's <code>random</code>
|
||||
function and returns the result. In C, <code>random</code> returns a value of the
|
||||
C type <code>long</code>, which cgo represents as the type <code>C.long</code>.
|
||||
It must be converted to a Go type before it can be used by Go code outside this
|
||||
package, using an ordinary Go type conversion:
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/cgo1.go" `/func Random/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
Here's an equivalent function that uses a temporary variable to illustrate
|
||||
the type conversion more explicitly:
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/cgo2.go" `/func Random/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
The <code>Seed</code> function does the reverse, in a way. It takes a
|
||||
regular Go <code>int</code>, converts it to the C <code>unsigned int</code>
|
||||
type, and passes it to the C function <code>srandom</code>.
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/cgo1.go" `/func Seed/` `/END/`}}
|
||||
|
||||
<p>
|
||||
Note that cgo knows the <code>unsigned int</code> type as <code>C.uint</code>;
|
||||
see the <a href="/cmd/cgo">cgo documentation</a> for a complete list of
|
||||
these numeric type names.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The one detail of this example we haven't examined yet is the comment
|
||||
above the <code>import</code> statement.
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/cgo1.go" `/\/\*/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
Cgo recognizes this comment. Any lines starting
|
||||
with <code>#cgo</code>
|
||||
followed
|
||||
by a space character are removed; these become directives for cgo.
|
||||
The remaining lines are used as a header when compiling the C parts of
|
||||
the package. In this case those lines are just a
|
||||
single <code>#include</code>
|
||||
statement, but they can be almost any C code. The <code>#cgo</code>
|
||||
directives are
|
||||
used to provide flags for the compiler and linker when building the C
|
||||
parts of the package.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
There is a limitation: if your program uses any <code>//export</code>
|
||||
directives, then the C code in the comment may only include declarations
|
||||
(<code>extern int f();</code>), not definitions (<code>int f() {
|
||||
return 1; }</code>). You can use <code>//export</code> directives to
|
||||
make Go functions accessible to C code.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The <code>#cgo</code> and <code>//export</code> directives are
|
||||
documented in
|
||||
the <a href="/cmd/cgo/">cgo documentation</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b>Strings and things</b>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Unlike Go, C doesn't have an explicit string type. Strings in C are
|
||||
represented by a zero-terminated array of chars.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Conversion between Go and C strings is done with the
|
||||
<code>C.CString</code>, <code>C.GoString</code>, and
|
||||
<code>C.GoStringN</code> functions. These conversions make a copy of the
|
||||
string data.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
This next example implements a <code>Print</code> function that writes a
|
||||
string to standard output using C's <code>fputs</code> function from the
|
||||
<code>stdio</code> library:
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/cgo3.go" `/package print/` `/END/`}}
|
||||
|
||||
<p>
|
||||
Memory allocations made by C code are not known to Go's memory manager.
|
||||
When you create a C string with <code>C.CString</code> (or any C memory
|
||||
allocation) you must remember to free the memory when you're done with it
|
||||
by calling <code>C.free</code>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The call to <code>C.CString</code> returns a pointer to the start of the
|
||||
char array, so before the function exits we convert it to an
|
||||
<a href="/pkg/unsafe/#Pointer"><code>unsafe.Pointer</code></a> and release
|
||||
the memory allocation with <code>C.free</code>. A common idiom in cgo programs
|
||||
is to <a href="/doc/articles/defer_panic_recover.html"><code>defer</code></a>
|
||||
the free immediately after allocating (especially when the code that follows
|
||||
is more complex than a single function call), as in this rewrite of
|
||||
<code>Print</code>:
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/cgo4.go" `/func Print/` `/END/`}}
|
||||
|
||||
<p>
|
||||
<b>Building cgo packages</b>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
To build cgo packages, just use <a href="/cmd/go/#Compile_packages_and_dependencies">"
|
||||
<code>go build</code>"</a> or
|
||||
<a href="/cmd/go/#Compile_and_install_packages_and_dependencies">"<code>go install</code>
|
||||
"</a> as usual. The go tool recognizes the special <code>"C"</code> import and automatically
|
||||
uses cgo for those files.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b>More cgo resources</b>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The <a href="/cmd/cgo/">cgo command</a> documentation has more detail about
|
||||
the C pseudo-package and the build process. The <a href="/misc/cgo/">cgo examples</a>
|
||||
in the Go tree demonstrate more advanced concepts.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
For a simple, idiomatic example of a cgo-based package, see Russ Cox's <a
|
||||
href="http://code.google.com/p/gosqlite/source/browse/sqlite/sqlite.go">gosqlite</a>.
|
||||
Also, the Go Project Dashboard lists <a
|
||||
href="https://godashboard.appspot.com/project?tag=cgo">several other
|
||||
cgo packages</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Finally, if you're curious as to how all this works internally, take a look
|
||||
at the introductory comment of the runtime package's <a href="/src/pkg/runtime/cgocall.c">cgocall.c</a>.
|
||||
</p>
|
||||
@@ -1,79 +0,0 @@
|
||||
<!--{
|
||||
"Title": "Go Concurrency Patterns: Timing out, moving on",
|
||||
"Template": true
|
||||
}-->
|
||||
|
||||
<p>
|
||||
Concurrent programming has its own idioms. A good example is timeouts. Although
|
||||
Go's channels do not support them directly, they are easy to implement. Say we
|
||||
want to receive from the channel <code>ch</code>, but want to wait at most one
|
||||
second for the value to arrive. We would start by creating a signalling channel
|
||||
and launching a goroutine that sleeps before sending on the channel:
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/timeout1.go" `/timeout :=/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
We can then use a <code>select</code> statement to receive from either
|
||||
<code>ch</code> or <code>timeout</code>. If nothing arrives on <code>ch</code>
|
||||
after one second, the timeout case is selected and the attempt to read from
|
||||
<cde>ch</cde> is abandoned.
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/timeout1.go" `/select {/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
The <code>timeout</code> channel is buffered with space for 1 value, allowing
|
||||
the timeout goroutine to send to the channel and then exit. The goroutine
|
||||
doesn't know (or care) whether the value is received. This means the goroutine
|
||||
won't hang around forever if the <code>ch</code> receive happens before the
|
||||
timeout is reached. The <code>timeout</code> channel will eventually be
|
||||
deallocated by the garbage collector.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
(In this example we used <code>time.Sleep</code> to demonstrate the mechanics
|
||||
of goroutines and channels. In real programs you should use <code>
|
||||
<a href="/pkg/time/#After">time.After</a></code>, a function that returns
|
||||
a channel and sends on that channel after the specified duration.)
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Let's look at another variation of this pattern. In this example we have a
|
||||
program that reads from multiple replicated databases simultaneously. The
|
||||
program needs only one of the answers, and it should accept the answer that
|
||||
arrives first.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The function <code>Query</code> takes a slice of database connections and a
|
||||
<code>query</code> string. It queries each of the databases in parallel and
|
||||
returns the first response it receives:
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/timeout2.go" `/func Query/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
In this example, the closure does a non-blocking send, which it achieves by
|
||||
using the send operation in <code>select</code> statement with a
|
||||
<code>default</code> case. If the send cannot go through immediately the
|
||||
default case will be selected. Making the send non-blocking guarantees that
|
||||
none of the goroutines launched in the loop will hang around. However, if the
|
||||
result arrives before the main function has made it to the receive, the send
|
||||
could fail since no one is ready.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
This problem is a textbook of example of what is known as a
|
||||
<a href="https://en.wikipedia.org/wiki/Race_condition">race condition</a>, but
|
||||
the fix is trivial. We just make sure to buffer the channel <code>ch</code> (by
|
||||
adding the buffer length as the second argument to <a href="/pkg/builtin/#make">make</a>),
|
||||
guaranteeing that the first send has a place to put the value. This ensures the
|
||||
send will always succeed, and the first value to arrive will be retrieved
|
||||
regardless of the order of execution.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
These two examples demonstrate the simplicity with which Go can express complex
|
||||
interactions between goroutines.
|
||||
</p>
|
||||
@@ -1,197 +0,0 @@
|
||||
<!--{
|
||||
"Title": "Defer, Panic, and Recover",
|
||||
"Template": true
|
||||
}-->
|
||||
|
||||
<p>
|
||||
Go has the usual mechanisms for control flow: if, for, switch, goto. It also
|
||||
has the go statement to run code in a separate goroutine. Here I'd like to
|
||||
discuss some of the less common ones: defer, panic, and recover.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
A <b>defer statement</b> pushes a function call onto a list. The list of saved
|
||||
calls is executed after the surrounding function returns. Defer is commonly
|
||||
used to simplify functions that perform various clean-up actions.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
For example, let's look at a function that opens two files and copies the
|
||||
contents of one file to the other:
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/defer.go" `/func CopyFile/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
This works, but there is a bug. If the call to os.Create fails, the
|
||||
function will return without closing the source file. This can be easily
|
||||
remedied by putting a call to src.Close before the second return statement,
|
||||
but if the function were more complex the problem might not be so easily
|
||||
noticed and resolved. By introducing defer statements we can ensure that the
|
||||
files are always closed:
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/defer2.go" `/func CopyFile/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
Defer statements allow us to think about closing each file right after opening
|
||||
it, guaranteeing that, regardless of the number of return statements in the
|
||||
function, the files <i>will</i> be closed.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The behavior of defer statements is straightforward and predictable. There are
|
||||
three simple rules:
|
||||
</p>
|
||||
|
||||
<p>
|
||||
1. <i>A deferred function's arguments are evaluated when the defer statement is
|
||||
evaluated.</i>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
In this example, the expression "i" is evaluated when the Println call is
|
||||
deferred. The deferred call will print "0" after the function returns.
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/defer.go" `/func a/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
2. <i>Deferred function calls are executed in Last In First Out order
|
||||
</i>after<i> the surrounding function returns.</i>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
This function prints "3210":
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/defer.go" `/func b/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
3. <i>Deferred functions may read and assign to the returning function's named
|
||||
return values.</i>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
In this example, a deferred function increments the return value i <i>after</i>
|
||||
the surrounding function returns. Thus, this function returns 2:
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/defer.go" `/func c/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
This is convenient for modifying the error return value of a function; we will
|
||||
see an example of this shortly.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b>Panic</b> is a built-in function that stops the ordinary flow of control and
|
||||
begins <i>panicking</i>. When the function F calls panic, execution of F stops,
|
||||
any deferred functions in F are executed normally, and then F returns to its
|
||||
caller. To the caller, F then behaves like a call to panic. The process
|
||||
continues up the stack until all functions in the current goroutine have
|
||||
returned, at which point the program crashes. Panics can be initiated by
|
||||
invoking panic directly. They can also be caused by runtime errors, such as
|
||||
out-of-bounds array accesses.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b>Recover</b> is a built-in function that regains control of a panicking
|
||||
goroutine. Recover is only useful inside deferred functions. During normal
|
||||
execution, a call to recover will return nil and have no other effect. If the
|
||||
current goroutine is panicking, a call to recover will capture the value given
|
||||
to panic and resume normal execution.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Here's an example program that demonstrates the mechanics of panic and defer:
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/defer2.go" `/package main/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
The function g takes the int i, and panics if i is greater than 3, or else it
|
||||
calls itself with the argument i+1. The function f defers a function that calls
|
||||
recover and prints the recovered value (if it is non-nil). Try to picture what
|
||||
the output of this program might be before reading on.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The program will output:
|
||||
</p>
|
||||
|
||||
<pre>Calling g.
|
||||
Printing in g 0
|
||||
Printing in g 1
|
||||
Printing in g 2
|
||||
Printing in g 3
|
||||
Panicking!
|
||||
Defer in g 3
|
||||
Defer in g 2
|
||||
Defer in g 1
|
||||
Defer in g 0
|
||||
Recovered in f 4
|
||||
Returned normally from f.</pre>
|
||||
|
||||
<p>
|
||||
If we remove the deferred function from f the panic is not recovered and
|
||||
reaches the top of the goroutine's call stack, terminating the program. This
|
||||
modified program will output:
|
||||
</p>
|
||||
|
||||
<pre>Calling g.
|
||||
Printing in g 0
|
||||
Printing in g 1
|
||||
Printing in g 2
|
||||
Printing in g 3
|
||||
Panicking!
|
||||
Defer in g 3
|
||||
Defer in g 2
|
||||
Defer in g 1
|
||||
Defer in g 0
|
||||
panic: 4
|
||||
|
||||
panic PC=0x2a9cd8
|
||||
[stack trace omitted]</pre>
|
||||
|
||||
<p>
|
||||
For a real-world example of <b>panic</b> and <b>recover</b>, see the
|
||||
<a href="/pkg/encoding/json/">json package</a> from the Go standard library.
|
||||
It decodes JSON-encoded data with a set of recursive functions.
|
||||
When malformed JSON is encountered, the parser calls panic to unwind the
|
||||
stack to the top-level function call, which recovers from the panic and returns
|
||||
an appropriate error value (see the 'error' and 'unmarshal' methods of
|
||||
the decodeState type in
|
||||
<a href="/src/pkg/encoding/json/decode.go">decode.go</a>).
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The convention in the Go libraries is that even when a package uses panic
|
||||
internally, its external API still presents explicit error return values.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Other uses of <b>defer</b> (beyond the file.Close example given earlier)
|
||||
include releasing a mutex:
|
||||
</p>
|
||||
|
||||
<pre>mu.Lock()
|
||||
defer mu.Unlock()</pre>
|
||||
|
||||
<p>
|
||||
printing a footer:
|
||||
</p>
|
||||
|
||||
<pre>printHeader()
|
||||
defer printFooter()</pre>
|
||||
|
||||
<p>
|
||||
and more.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
In summary, the defer statement (with or without panic and recover) provides an
|
||||
unusual and powerful mechanism for control flow. It can be used to model a
|
||||
number of features implemented by special-purpose structures in other
|
||||
programming languages. Try it out.
|
||||
</p>
|
||||
@@ -1,316 +0,0 @@
|
||||
<!--{
|
||||
"Title": "Error Handling and Go",
|
||||
"Template": true
|
||||
}-->
|
||||
|
||||
<p>
|
||||
If you have written any Go code you have probably encountered the built-in
|
||||
<code>error</code> type. Go code uses <code>error</code> values to
|
||||
indicate an abnormal state. For example, the <code>os.Open</code> function
|
||||
returns a non-nil <code>error</code> value when it fails to open a file.
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/error.go" `/func Open/`}}
|
||||
|
||||
<p>
|
||||
The following code uses <code>os.Open</code> to open a file. If an error
|
||||
occurs it calls <code>log.Fatal</code> to print the error message and stop.
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/error.go" `/func openFile/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
You can get a lot done in Go knowing just this about the <code>error</code>
|
||||
type, but in this article we'll take a closer look at <code>error</code> and
|
||||
discuss some good practices for error handling in Go.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b>The error type</b>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The <code>error</code> type is an interface type. An <code>error</code>
|
||||
variable represents any value that can describe itself as a string. Here is the
|
||||
interface's declaration:
|
||||
</p>
|
||||
|
||||
<pre>type error interface {
|
||||
Error() string
|
||||
}</pre>
|
||||
|
||||
<p>
|
||||
The <code>error</code> type, as with all built in types, is
|
||||
<a href="/doc/go_spec.html#Predeclared_identifiers">predeclared</a> in the
|
||||
<a href="/doc/go_spec.html#Blocks">universe block</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The most commonly-used <code>error</code> implementation is the
|
||||
<a href="/pkg/errors/">errors</a> package's unexported <code>errorString</code> type.
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/error.go" `/errorString/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
You can construct one of these values with the <code>errors.New</code>
|
||||
function. It takes a string that it converts to an <code>errors.errorString</code>
|
||||
and returns as an <code>error</code> value.
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/error.go" `/New/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
Here's how you might use <code>errors.New</code>:
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/error.go" `/func Sqrt/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
A caller passing a negative argument to <code>Sqrt</code> receives a non-nil
|
||||
<code>error</code> value (whose concrete representation is an
|
||||
<code>errors.errorString</code> value). The caller can access the error string
|
||||
("math: square root of...") by calling the <code>error</code>'s
|
||||
<code>Error</code> method, or by just printing it:
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/error.go" `/func printErr/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
The <a href="/pkg/fmt/">fmt</a> package formats an <code>error</code> value
|
||||
by calling its <code>Error() string</code> method.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
It is the error implementation's responsibility to summarize the context.
|
||||
The error returned by <code>os.Open</code> formats as "open /etc/passwd:
|
||||
permission denied," not just "permission denied." The error returned by our
|
||||
<code>Sqrt</code> is missing information about the invalid argument.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
To add that information, a useful function is the <code>fmt</code> package's
|
||||
<code>Errorf</code>. It formats a string according to <code>Printf</code>'s
|
||||
rules and returns it as an <code>error</code> created by
|
||||
<code>errors.New</code>.
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/error.go" `/fmtError/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
In many cases <code>fmt.Errorf</code> is good enough, but since
|
||||
<code>error</code> is an interface, you can use arbitrary data structures as
|
||||
error values, to allow callers to inspect the details of the error.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
For instance, our hypothetical callers might want to recover the invalid
|
||||
argument passed to <code>Sqrt</code>. We can enable that by defining a new
|
||||
error implementation instead of using <code>errors.errorString</code>:
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/error.go" `/type NegativeSqrtError/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
A sophisticated caller can then use a
|
||||
<a href="/doc/go_spec.html#Type_assertions">type assertion</a> to check for a
|
||||
<code>NegativeSqrtError</code> and handle it specially, while callers that just
|
||||
pass the error to <code>fmt.Println</code> or <code>log.Fatal</code> will see
|
||||
no change in behavior.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
As another example, the <a href="/pkg/encoding/json/">json</a> package specifies a
|
||||
<code>SyntaxError</code> type that the <code>json.Decode</code> function
|
||||
returns when it encounters a syntax error parsing a JSON blob.
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/error.go" `/type SyntaxError/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
The <code>Offset</code> field isn't even shown in the default formatting of the
|
||||
error, but callers can use it to add file and line information to their error
|
||||
messages:
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/error.go" `/func decodeError/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
(This is a slightly simplified version of some
|
||||
<a href="http://camlistore.org/code/?p=camlistore.git;a=blob;f=lib/go/camli/jsonconfig/eval.go#l68">actual code</a>
|
||||
from the <a href="http://camlistore.org">Camlistore</a> project.)
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The <code>error</code> interface requires only a <code>Error</code> method;
|
||||
specific error implementations might have additional methods. For instance, the
|
||||
<a href="/pkg/net/">net</a> package returns errors of type
|
||||
<code>error</code>, following the usual convention, but some of the error
|
||||
implementations have additional methods defined by the <code>net.Error</code>
|
||||
interface:
|
||||
</p>
|
||||
|
||||
<pre>package net
|
||||
|
||||
type Error interface {
|
||||
error
|
||||
Timeout() bool // Is the error a timeout?
|
||||
Temporary() bool // Is the error temporary?
|
||||
}</pre>
|
||||
|
||||
<p>
|
||||
Client code can test for a <code>net.Error</code> with a type assertion and
|
||||
then distinguish transient network errors from permanent ones. For instance, a
|
||||
web crawler might sleep and retry when it encounters a temporary error and give
|
||||
up otherwise.
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/error.go" `/func netError/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
<b>Simplifying repetitive error handling</b>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
In Go, error handling is important. The language's design and conventions
|
||||
encourage you to explicitly check for errors where they occur (as distinct from
|
||||
the convention in other languages of throwing exceptions and sometimes catching
|
||||
them). In some cases this makes Go code verbose, but fortunately there are some
|
||||
techniques you can use to minimize repetitive error handling.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Consider an <a href="http://code.google.com/appengine/docs/go/">App Engine</a>
|
||||
application with an HTTP handler that retrieves a record from the datastore and
|
||||
formats it with a template.
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/error2.go" `/func init/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
This function handles errors returned by the <code>datastore.Get</code>
|
||||
function and <code>viewTemplate</code>'s <code>Execute</code> method. In both
|
||||
cases, it presents a simple error message to the user with the HTTP status code
|
||||
500 ("Internal Server Error"). This looks like a manageable amount of code, but
|
||||
add some more HTTP handlers and you quickly end up with many copies of
|
||||
identical error handling code.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
To reduce the repetition we can define our own HTTP <code>appHandler</code>
|
||||
type that includes an <code>error</code> return value:
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/error3.go" `/type appHandler/`}}
|
||||
|
||||
<p>
|
||||
Then we can change our <code>viewRecord</code> function to return errors:
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/error3.go" `/func viewRecord/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
This is simpler than the original version, but the <a
|
||||
href="/pkg/net/http/">http</a> package doesn't understand functions that return
|
||||
<code>error</code>.
|
||||
To fix this we can implement the <code>http.Handler</code> interface's
|
||||
<code>ServeHTTP</code> method on <code>appHandler</code>:
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/error3.go" `/ServeHTTP/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
The <code>ServeHTTP</code> method calls the <code>appHandler</code> function
|
||||
and displays the returned error (if any) to the user. Notice that the method's
|
||||
receiver, <code>fn</code>, is a function. (Go can do that!) The method invokes
|
||||
the function by calling the receiver in the expression <code>fn(w, r)</code>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Now when registering <code>viewRecord</code> with the http package we use the
|
||||
<code>Handle</code> function (instead of <code>HandleFunc</code>) as
|
||||
<code>appHandler</code> is an <code>http.Handler</code> (not an
|
||||
<code>http.HandlerFunc</code>).
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/error3.go" `/func init/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
With this basic error handling infrastructure in place, we can make it more
|
||||
user friendly. Rather than just displaying the error string, it would be better
|
||||
to give the user a simple error message with an appropriate HTTP status code,
|
||||
while logging the full error to the App Engine developer console for debugging
|
||||
purposes.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
To do this we create an <code>appError</code> struct containing an
|
||||
<code>error</code> and some other fields:
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/error4.go" `/type appError/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
Next we modify the appHandler type to return <code>*appError</code> values:
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/error4.go" `/type appHandler/`}}
|
||||
|
||||
<p>
|
||||
(It's usually a mistake to pass back the concrete type of an error rather than
|
||||
<code>error</code>,
|
||||
for reasons discussed in <a href="/doc/go_faq.html#nil_error">the Go FAQ</a>,
|
||||
but it's the right thing to do here because <code>ServeHTTP</code> is the only
|
||||
place that sees the value and uses its contents.)
|
||||
</p>
|
||||
|
||||
<p>
|
||||
And make <code>appHandler</code>'s <code>ServeHTTP</code> method display the
|
||||
<code>appError</code>'s <code>Message</code> to the user with the correct HTTP
|
||||
status <code>Code</code> and log the full <code>Error</code> to the developer
|
||||
console:
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/error4.go" `/ServeHTTP/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
Finally, we update <code>viewRecord</code> to the new function signature and
|
||||
have it return more context when it encounters an error:
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/error4.go" `/func viewRecord/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
This version of <code>viewRecord</code> is the same length as the original, but
|
||||
now each of those lines has specific meaning and we are providing a friendlier
|
||||
user experience.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
It doesn't end there; we can further improve the error handling in our
|
||||
application. Some ideas:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>give the error handler a pretty HTML template,
|
||||
<li>make debugging easier by writing the stack trace to the HTTP response when
|
||||
the user is an administrator,
|
||||
<li>write a constructor function for <code>appError</code> that stores the
|
||||
stack trace for easier debugging,
|
||||
<li>recover from panics inside the <code>appHandler</code>, logging the error
|
||||
to the console as "Critical," while telling the user "a serious error
|
||||
has occurred." This is a nice touch to avoid exposing the user to inscrutable
|
||||
error messages caused by programming errors.
|
||||
See the <a href="defer_panic_recover.html">Defer, Panic, and Recover</a>
|
||||
article for more details.
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
<b>Conclusion</b>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Proper error handling is an essential requirement of good software. By
|
||||
employing the techniques described in this post you should be able to write
|
||||
more reliable and succinct Go code.
|
||||
</p>
|
||||
@@ -1,265 +0,0 @@
|
||||
<!--{
|
||||
"title": "About the go command"
|
||||
}-->
|
||||
|
||||
<p>The Go distribution includes a command, named
|
||||
"<code><a href="/cmd/go/">go</a></code>", that
|
||||
automates the downloading, building, installation, and testing of Go packages
|
||||
and commands. This document talks about why we wrote a new command, what it
|
||||
is, what it's not, and how to use it.</p>
|
||||
|
||||
<h2>Motivation</h2>
|
||||
|
||||
<p>You might have seen early Go talks in which Rob Pike jokes that the idea
|
||||
for Go arose while waiting for a large Google server to compile. That
|
||||
really was the motivation for Go: to build a language that worked well
|
||||
for building the large software that Google writes and runs. It was
|
||||
clear from the start that such a language must provide a way to
|
||||
express dependencies between code libraries clearly, hence the package
|
||||
grouping and the explicit import blocks. It was also clear from the
|
||||
start that you might want arbitrary syntax for describing the code
|
||||
being imported; this is why import paths are string literals.</p>
|
||||
|
||||
<p>An explicit goal for Go from the beginning was to be able to build Go
|
||||
code using only the information found in the source itself, not
|
||||
needing to write a makefile or one of the many modern replacements for
|
||||
makefiles. If Go needed a configuration file to explain how to build
|
||||
your program, then Go would have failed.</p>
|
||||
|
||||
<p>At first, there was no Go compiler, and the initial development
|
||||
focused on building one and then building libraries for it. For
|
||||
expedience, we postponed the automation of building Go code by using
|
||||
make and writing makefiles. When compiling a single package involved
|
||||
multiple invocations of the Go compiler, we even used a program to
|
||||
write the makefiles for us. You can find it if you dig through the
|
||||
repository history.</p>
|
||||
|
||||
<p>The purpose of the new go command is our return to this ideal, that Go
|
||||
programs should compile without configuration or additional effort on
|
||||
the part of the developer beyond writing the necessary import
|
||||
statements.</p>
|
||||
|
||||
<h2>Configuration versus convention</h2>
|
||||
|
||||
<p>The way to achieve the simplicity of a configuration-free system is to
|
||||
establish conventions. The system works only to the extent that those conventions
|
||||
are followed. When we first launched Go, many people published packages that
|
||||
had to be installed in certain places, under certain names, using certain build
|
||||
tools, in order to be used. That's understandable: that's the way it works in
|
||||
most other languages. Over the last few years we consistently reminded people
|
||||
about the <code>goinstall</code> command
|
||||
(now replaced by <a href="/cmd/go/#Download_and_install_packages_and_dependencies"><code>go get</code></a>)
|
||||
and its conventions: first, that the import path is derived in a known way from
|
||||
the URL of the source code; second, that that the place to store the sources in
|
||||
the local file system is derived in a known way from the import path; third,
|
||||
that each directory in a source tree corresponds to a single package; and
|
||||
fourth, that the package is built using only information in the source code.
|
||||
Today, the vast majority of packages follow these conventions.
|
||||
The Go ecosystem is simpler and more powerful as a result.</p>
|
||||
|
||||
<p>We received many requests to allow a makefile in a package directory to
|
||||
provide just a little extra configuration beyond what's in the source code.
|
||||
But that would have introduced new rules. Because we did not accede to such
|
||||
requests, we were able to write the go command and eliminate our use of make
|
||||
or any other build system.</p>
|
||||
|
||||
<p>It is important to understand that the go command is not a general
|
||||
build tool. It cannot be configured and it does not attempt to build
|
||||
anything but Go packages. These are important simplifying
|
||||
assumptions: they simplify not only the implementation but also, more
|
||||
important, the use of the tool itself.</p>
|
||||
|
||||
<h2>Go's conventions</h2>
|
||||
|
||||
<p>The <code>go</code> command requires that code adheres to a few key,
|
||||
well-established conventions.</p>
|
||||
|
||||
<p>First, the import path is derived in an known way from the URL of the
|
||||
source code. For Bitbucket, GitHub, Google Code, and Launchpad, the
|
||||
root directory of the repository is identified by the repository's
|
||||
main URL, without the <code>http://</code> prefix. Subdirectories are named by
|
||||
adding to that path. For example, the supplemental networking
|
||||
libraries for Go are obtained by running</p>
|
||||
|
||||
<pre>
|
||||
hg clone http://code.google.com/p/go.net
|
||||
</pre>
|
||||
|
||||
<p>and thus the import path for the root directory of that repository is
|
||||
"<code>code.google.com/p/go.net</code>". The websocket package is stored in a
|
||||
subdirectory, so its import path is
|
||||
"<code>code.google.com/p/go.net/websocket</code>".</p>
|
||||
|
||||
<p>These paths are on the long side, but in exchange we get an
|
||||
automatically managed name space for import paths and the ability for
|
||||
a tool like the go command to look at an unfamiliar import path and
|
||||
deduce where to obtain the source code.</p>
|
||||
|
||||
<p>Second, the place to store sources in the local file system is derived
|
||||
in a known way from the import path. Specifically, the first choice
|
||||
is <code>$GOPATH/src/<import-path></code>. If <code>$GOPATH</code> is
|
||||
unset, the go command will fall back to storing source code alongside the
|
||||
standard Go packages, in <code>$GOROOT/src/pkg/<import-path></code>.
|
||||
If <code>$GOPATH</code> is set to a list of paths, the go command tries
|
||||
<code><dir>/src/<import-path></code> for each of the directories in
|
||||
that list.</p>
|
||||
|
||||
<p>Each of those trees contains, by convention, a top-level directory named
|
||||
"<code>bin</code>", for holding compiled executables, and a top-level directory
|
||||
named "<code>pkg</code>", for holding compiled packages that can be imported,
|
||||
and the "<code>src</code>" directory, for holding package source files.
|
||||
Imposing this structure lets us keep each of these directory trees
|
||||
self-contained: the compiled form and the sources are always near each
|
||||
other.</p>
|
||||
|
||||
<p>These naming conventions also let us work in the reverse direction,
|
||||
from a directory name to its import path. This mapping is important
|
||||
for many of the go command's subcommands, as we'll see below.</p>
|
||||
|
||||
<p>Third, each directory in a source tree corresponds to a single
|
||||
package. By restricting a directory to a single package, we don't have
|
||||
to create hybrid import paths that specify first the directory and
|
||||
then the package within that directory. Also, most file management
|
||||
tools and UIs work on directories as fundamental units. Tying the
|
||||
fundamental Go unit—the package—to file system structure means
|
||||
that file system tools become Go package tools. Copying, moving, or
|
||||
deleting a package corresponds to copying, moving, or deleting a
|
||||
directory.</p>
|
||||
|
||||
<p>Fourth, each package is built using only the information present in
|
||||
the source files. This makes it much more likely that the tool will
|
||||
be able to adapt to changing build environments and conditions. For
|
||||
example, if we allowed extra configuration such as compiler flags or
|
||||
command line recipes, then that configuration would need to be updated
|
||||
each time the build tools changed; it would also be inherently tied
|
||||
to the use of a specific tool chain.</p>
|
||||
|
||||
<h2>Getting started with the go command</h2>
|
||||
|
||||
<p>Finally, a quick tour of how to use the go command, to supplement
|
||||
the information in <a href="/doc/code.html">How to Write Go Code</a>,
|
||||
which you might want to read first. Assuming you want
|
||||
to keep your source code separate from the Go distribution source
|
||||
tree, the first step is to set <code>$GOPATH</code>, the one piece of global
|
||||
configuration that the go command needs. The <code>$GOPATH</code> can be a
|
||||
list of directories, but by far the most common usage should be to set it to a
|
||||
single directory. In particular, you do not need a separate entry in
|
||||
<code>$GOPATH</code> for each of your projects. One <code>$GOPATH</code> can
|
||||
support many projects.</p>
|
||||
|
||||
<p>Here’s an example. Let’s say we decide to keep our Go code in the directory
|
||||
<code>$HOME/mygo</code>. We need to create that directory and set
|
||||
<code>$GOPATH</code> accordingly.</p>
|
||||
|
||||
<pre>
|
||||
$ mkdir $HOME/mygo
|
||||
$ export GOPATH=$HOME/mygo
|
||||
$
|
||||
</pre>
|
||||
|
||||
<p>Into this directory, we now add some source code. Suppose we want to use
|
||||
the indexing library from the codesearch project along with a left-leaning
|
||||
red-black tree. We can install both with the "<code>go get</code>"
|
||||
subcommand:</p>
|
||||
|
||||
<pre>
|
||||
$ go get code.google.com/p/codesearch/index
|
||||
$ go get github.com/petar/GoLLRB/llrb
|
||||
$
|
||||
</pre>
|
||||
|
||||
<p>Both of these projects are now downloaded and installed into our
|
||||
<code>$GOPATH</code> directory. The one tree now contains the two directories
|
||||
<code>src/code.google.com/p/codesearch/index/</code> and
|
||||
<code>src/github.com/petar/GoLLRB/llrb/</code>, along with the compiled
|
||||
packages (in <code>pkg/</code>) for those libraries and their dependencies.</p>
|
||||
|
||||
<p>Because we used version control systems (Mercurial and Git) to check
|
||||
out the sources, the source tree also contains the other files in the
|
||||
corresponding repositories, such as related packages. The "<code>go list</code>"
|
||||
subcommand lists the import paths corresponding to its arguments, and
|
||||
the pattern "<code>./...</code>" means start in the current directory
|
||||
("<code>./</code>") and find all packages below that directory
|
||||
("<code>...</code>"):</p>
|
||||
|
||||
<pre>
|
||||
$ go list ./...
|
||||
code.google.com/p/codesearch/cmd/cgrep
|
||||
code.google.com/p/codesearch/cmd/cindex
|
||||
code.google.com/p/codesearch/cmd/csearch
|
||||
code.google.com/p/codesearch/index
|
||||
code.google.com/p/codesearch/regexp
|
||||
code.google.com/p/codesearch/sparse
|
||||
github.com/petar/GoLLRB/example
|
||||
github.com/petar/GoLLRB/llrb
|
||||
$
|
||||
</pre>
|
||||
|
||||
<p>We can also test those packages:</p>
|
||||
|
||||
<pre>
|
||||
$ go test ./...
|
||||
? code.google.com/p/codesearch/cmd/cgrep [no test files]
|
||||
? code.google.com/p/codesearch/cmd/cindex [no test files]
|
||||
? code.google.com/p/codesearch/cmd/csearch [no test files]
|
||||
ok code.google.com/p/codesearch/index 0.239s
|
||||
ok code.google.com/p/codesearch/regexp 0.021s
|
||||
? code.google.com/p/codesearch/sparse [no test files]
|
||||
? github.com/petar/GoLLRB/example [no test files]
|
||||
ok github.com/petar/GoLLRB/llrb 0.231s
|
||||
$
|
||||
</pre>
|
||||
|
||||
<p>If a go subcommand is invoked with no paths listed, it operates on the
|
||||
current directory:</p>
|
||||
|
||||
<pre>
|
||||
$ cd $GOPATH/src/code.google.com/p/codesearch/regexp
|
||||
$ go list
|
||||
code.google.com/p/codesearch/regexp
|
||||
$ go test -v
|
||||
=== RUN TestNstateEnc
|
||||
--- PASS: TestNstateEnc (0.00 seconds)
|
||||
=== RUN TestMatch
|
||||
--- PASS: TestMatch (0.01 seconds)
|
||||
=== RUN TestGrep
|
||||
--- PASS: TestGrep (0.00 seconds)
|
||||
PASS
|
||||
ok code.google.com/p/codesearch/regexp 0.021s
|
||||
$ go install
|
||||
$
|
||||
</pre>
|
||||
|
||||
<p>That "<code>go install</code>" subcommand installs the latest copy of the
|
||||
package into the pkg directory. Because the go command can analyze the
|
||||
dependency graph, "<code>go install</code>" also installs any packages that
|
||||
this package imports but that are out of date, recursively.</p>
|
||||
|
||||
<p>Notice that "<code>go install</code>" was able to determine the name of the
|
||||
import path for the package in the current directory, because of the convention
|
||||
for directory naming. It would be a little more convenient if we could pick
|
||||
the name of the directory where we kept source code, and we probably wouldn't
|
||||
pick such a long name, but that ability would require additional configuration
|
||||
and complexity in the tool. Typing an extra directory name or two is a small
|
||||
price to pay for the increased simplicity and power.</p>
|
||||
|
||||
<p>As the example shows, it’s fine to work with packages from many different
|
||||
projects at once within a single <code>$GOPATH</code> root directory.</p>
|
||||
|
||||
<h2>Limitations</h2>
|
||||
|
||||
<p>As mentioned above, the go command is not a general-purpose build
|
||||
tool. In particular, it does not have any facility for generating Go
|
||||
source files during a build. Instead, if you want to use a tool like
|
||||
yacc or the protocol buffer compiler, you will need to write a
|
||||
makefile (or a configuration file for the build tool of your choice)
|
||||
to generate the Go files and then check those generated source files
|
||||
into your repository. This is more work for you, the package author,
|
||||
but it is significantly less work for your users, who can use
|
||||
"<code>go get</code>" without needing to obtain and build
|
||||
any additional tools.</p>
|
||||
|
||||
<h2>More information</h2>
|
||||
|
||||
<p>For more information, read <a href="/doc/code.html">How to Write Go Code</a>
|
||||
and see the <a href="/cmd/go/">go command documentation</a>.</p>
|
||||
@@ -1,315 +0,0 @@
|
||||
<!--{
|
||||
"Title": "Gobs of data",
|
||||
"Template": true
|
||||
}-->
|
||||
|
||||
<p>
|
||||
To transmit a data structure across a network or to store it in a file, it must
|
||||
be encoded and then decoded again. There are many encodings available, of
|
||||
course: <a href="http://www.json.org/">JSON</a>,
|
||||
<a href="http://www.w3.org/XML/">XML</a>, Google's
|
||||
<a href="http://code.google.com/p/protobuf">protocol buffers</a>, and more.
|
||||
And now there's another, provided by Go's <a href="/pkg/encoding/gob/">gob</a>
|
||||
package.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Why define a new encoding? It's a lot of work and redundant at that. Why not
|
||||
just use one of the existing formats? Well, for one thing, we do! Go has
|
||||
<a href="/pkg/">packages</a> supporting all the encodings just mentioned (the
|
||||
<a href="http://code.google.com/p/goprotobuf">protocol buffer package</a> is in
|
||||
a separate repository but it's one of the most frequently downloaded). And for
|
||||
many purposes, including communicating with tools and systems written in other
|
||||
languages, they're the right choice.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
But for a Go-specific environment, such as communicating between two servers
|
||||
written in Go, there's an opportunity to build something much easier to use and
|
||||
possibly more efficient.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Gobs work with the language in a way that an externally-defined,
|
||||
language-independent encoding cannot. At the same time, there are lessons to be
|
||||
learned from the existing systems.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b>Goals</b>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The gob package was designed with a number of goals in mind.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
First, and most obvious, it had to be very easy to use. First, because Go has
|
||||
reflection, there is no need for a separate interface definition language or
|
||||
"protocol compiler". The data structure itself is all the package should need
|
||||
to figure out how to encode and decode it. On the other hand, this approach
|
||||
means that gobs will never work as well with other languages, but that's OK:
|
||||
gobs are unashamedly Go-centric.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Efficiency is also important. Textual representations, exemplified by XML and
|
||||
JSON, are too slow to put at the center of an efficient communications network.
|
||||
A binary encoding is necessary.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Gob streams must be self-describing. Each gob stream, read from the beginning,
|
||||
contains sufficient information that the entire stream can be parsed by an
|
||||
agent that knows nothing a priori about its contents. This property means that
|
||||
you will always be able to decode a gob stream stored in a file, even long
|
||||
after you've forgotten what data it represents.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
There were also some things to learn from our experiences with Google protocol
|
||||
buffers.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b>Protocol buffer misfeatures</b>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Protocol buffers had a major effect on the design of gobs, but have three
|
||||
features that were deliberately avoided. (Leaving aside the property that
|
||||
protocol buffers aren't self-describing: if you don't know the data definition
|
||||
used to encode a protocol buffer, you might not be able to parse it.)
|
||||
</p>
|
||||
|
||||
<p>
|
||||
First, protocol buffers only work on the data type we call a struct in Go. You
|
||||
can't encode an integer or array at the top level, only a struct with fields
|
||||
inside it. That seems a pointless restriction, at least in Go. If all you want
|
||||
to send is an array of integers, why should you have to put it into a
|
||||
struct first?
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Next, a protocol buffer definition may specify that fields <code>T.x</code> and
|
||||
<code>T.y</code> are required to be present whenever a value of type
|
||||
<code>T</code> is encoded or decoded. Although such required fields may seem
|
||||
like a good idea, they are costly to implement because the codec must maintain a
|
||||
separate data structure while encoding and decoding, to be able to report when
|
||||
required fields are missing. They're also a maintenance problem. Over time, one
|
||||
may want to modify the data definition to remove a required field, but that may
|
||||
cause existing clients of the data to crash. It's better not to have them in the
|
||||
encoding at all. (Protocol buffers also have optional fields. But if we don't
|
||||
have required fields, all fields are optional and that's that. There will be
|
||||
more to say about optional fields a little later.)
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The third protocol buffer misfeature is default values. If a protocol buffer
|
||||
omits the value for a "defaulted" field, then the decoded structure behaves as
|
||||
if the field were set to that value. This idea works nicely when you have
|
||||
getter and setter methods to control access to the field, but is harder to
|
||||
handle cleanly when the container is just a plain idiomatic struct. Required
|
||||
fields are also tricky to implement: where does one define the default values,
|
||||
what types do they have (is text UTF-8? uninterpreted bytes? how many bits in a
|
||||
float?) and despite the apparent simplicity, there were a number of
|
||||
complications in their design and implementation for protocol buffers. We
|
||||
decided to leave them out of gobs and fall back to Go's trivial but effective
|
||||
defaulting rule: unless you set something otherwise, it has the "zero value"
|
||||
for that type - and it doesn't need to be transmitted.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
So gobs end up looking like a sort of generalized, simplified protocol buffer.
|
||||
How do they work?
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b>Values</b>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The encoded gob data isn't about <code>int8</code>s and <code>uint16</code>s.
|
||||
Instead, somewhat analogous to constants in Go, its integer values are abstract,
|
||||
sizeless numbers, either signed or unsigned. When you encode an
|
||||
<code>int8</code>, its value is transmitted as an unsized, variable-length
|
||||
integer. When you encode an <code>int64</code>, its value is also transmitted as
|
||||
an unsized, variable-length integer. (Signed and unsigned are treated
|
||||
distinctly, but the same unsized-ness applies to unsigned values too.) If both
|
||||
have the value 7, the bits sent on the wire will be identical. When the receiver
|
||||
decodes that value, it puts it into the receiver's variable, which may be of
|
||||
arbitrary integer type. Thus an encoder may send a 7 that came from an
|
||||
<code>int8</code>, but the receiver may store it in an <code>int64</code>. This
|
||||
is fine: the value is an integer and as a long as it fits, everything works. (If
|
||||
it doesn't fit, an error results.) This decoupling from the size of the variable
|
||||
gives some flexibility to the encoding: we can expand the type of the integer
|
||||
variable as the software evolves, but still be able to decode old data.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
This flexibility also applies to pointers. Before transmission, all pointers are
|
||||
flattened. Values of type <code>int8</code>, <code>*int8</code>,
|
||||
<code>**int8</code>, <code>****int8</code>, etc. are all transmitted as an
|
||||
integer value, which may then be stored in <code>int</code> of any size, or
|
||||
<code>*int</code>, or <code>******int</code>, etc. Again, this allows for
|
||||
flexibility.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Flexibility also happens because, when decoding a struct, only those fields
|
||||
that are sent by the encoder are stored in the destination. Given the value
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/gobs1.go" `/type T/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
the encoding of <code>t</code> sends only the 7 and 8. Because it's zero, the
|
||||
value of <code>Y</code> isn't even sent; there's no need to send a zero value.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The receiver could instead decode the value into this structure:
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/gobs1.go" `/type U/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
and acquire a value of <code>u</code> with only <code>X</code> set (to the
|
||||
address of an <code>int8</code> variable set to 7); the <code>Z</code> field is
|
||||
ignored - where would you put it? When decoding structs, fields are matched by
|
||||
name and compatible type, and only fields that exist in both are affected. This
|
||||
simple approach finesses the "optional field" problem: as the type
|
||||
<code>T</code> evolves by adding fields, out of date receivers will still
|
||||
function with the part of the type they recognize. Thus gobs provide the
|
||||
important result of optional fields - extensibility - without any additional
|
||||
mechanism or notation.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
From integers we can build all the other types: bytes, strings, arrays, slices,
|
||||
maps, even floats. Floating-point values are represented by their IEEE 754
|
||||
floating-point bit pattern, stored as an integer, which works fine as long as
|
||||
you know their type, which we always do. By the way, that integer is sent in
|
||||
byte-reversed order because common values of floating-point numbers, such as
|
||||
small integers, have a lot of zeros at the low end that we can avoid
|
||||
transmitting.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
One nice feature of gobs that Go makes possible is that they allow you to define
|
||||
your own encoding by having your type satisfy the
|
||||
<a href="/pkg/encoding/gob/#GobEncoder">GobEncoder</a> and
|
||||
<a href="/pkg/encoding/gob/#GobDecoder">GobDecoder</a> interfaces, in a manner
|
||||
analogous to the <a href="/pkg/encoding/json/">JSON</a> package's
|
||||
<a href="/pkg/encoding/json/#Marshaler">Marshaler</a> and
|
||||
<a href="/pkg/encoding/json/#Unmarshaler">Unmarshaler</a> and also to the
|
||||
<a href="/pkg/fmt/#Stringer">Stringer</a> interface from
|
||||
<a href="/pkg/fmt/">package fmt</a>. This facility makes it possible to
|
||||
represent special features, enforce constraints, or hide secrets when you
|
||||
transmit data. See the <a href="/pkg/encoding/gob/">documentation</a> for
|
||||
details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b>Types on the wire</b>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The first time you send a given type, the gob package includes in the data
|
||||
stream a description of that type. In fact, what happens is that the encoder is
|
||||
used to encode, in the standard gob encoding format, an internal struct that
|
||||
describes the type and gives it a unique number. (Basic types, plus the layout
|
||||
of the type description structure, are predefined by the software for
|
||||
bootstrapping.) After the type is described, it can be referenced by its type
|
||||
number.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Thus when we send our first type <code>T</code>, the gob encoder sends a
|
||||
description of <code>T</code> and tags it with a type number, say 127. All
|
||||
values, including the first, are then prefixed by that number, so a stream of
|
||||
<code>T</code> values looks like:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
("define type id" 127, definition of type T)(127, T value)(127, T value), ...
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
These type numbers make it possible to describe recursive types and send values
|
||||
of those types. Thus gobs can encode types such as trees:
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/gobs1.go" `/type Node/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
(It's an exercise for the reader to discover how the zero-defaulting rule makes
|
||||
this work, even though gobs don't represent pointers.)
|
||||
</p>
|
||||
|
||||
<p>
|
||||
With the type information, a gob stream is fully self-describing except for the
|
||||
set of bootstrap types, which is a well-defined starting point.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b>Compiling a machine</b>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The first time you encode a value of a given type, the gob package builds a
|
||||
little interpreted machine specific to that data type. It uses reflection on
|
||||
the type to construct that machine, but once the machine is built it does not
|
||||
depend on reflection. The machine uses package unsafe and some trickery to
|
||||
convert the data into the encoded bytes at high speed. It could use reflection
|
||||
and avoid unsafe, but would be significantly slower. (A similar high-speed
|
||||
approach is taken by the protocol buffer support for Go, whose design was
|
||||
influenced by the implementation of gobs.) Subsequent values of the same type
|
||||
use the already-compiled machine, so they can be encoded right away.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Decoding is similar but harder. When you decode a value, the gob package holds
|
||||
a byte slice representing a value of a given encoder-defined type to decode,
|
||||
plus a Go value into which to decode it. The gob package builds a machine for
|
||||
that pair: the gob type sent on the wire crossed with the Go type provided for
|
||||
decoding. Once that decoding machine is built, though, it's again a
|
||||
reflectionless engine that uses unsafe methods to get maximum speed.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b>Use</b>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
There's a lot going on under the hood, but the result is an efficient,
|
||||
easy-to-use encoding system for transmitting data. Here's a complete example
|
||||
showing differing encoded and decoded types. Note how easy it is to send and
|
||||
receive values; all you need to do is present values and variables to the
|
||||
<a href="/pkg/encoding/gob/">gob package</a> and it does all the work.
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/gobs2.go" `/package main/` `$`}}
|
||||
|
||||
<p>
|
||||
You can compile and run this example code in the
|
||||
<a href="http://play.golang.org/p/_-OJV-rwMq">Go Playground</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The <a href="/pkg/net/rpc/">rpc package</a> builds on gobs to turn this
|
||||
encode/decode automation into transport for method calls across the network.
|
||||
That's a subject for another article.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b>Details</b>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The <a href="/pkg/encoding/gob/">gob package documentation</a>, especially the
|
||||
file <a href="/src/pkg/encoding/gob/doc.go">doc.go</a>, expands on many of the
|
||||
details described here and includes a full worked example showing how the
|
||||
encoding represents data. If you are interested in the innards of the gob
|
||||
implementation, that's a good place to start.
|
||||
</p>
|
||||
@@ -1,139 +0,0 @@
|
||||
<!--{
|
||||
"Title": "Godoc: documenting Go code",
|
||||
"Template": true
|
||||
}-->
|
||||
|
||||
<p>
|
||||
The Go project takes documentation seriously. Documentation is a huge part of
|
||||
making software accessible and maintainable. Of course it must be well-written
|
||||
and accurate, but it also must be easy to write and to maintain. Ideally, it
|
||||
should be coupled to the code itself so the documentation evolves along with the
|
||||
code. The easier it is for programmers to produce good documentation, the better
|
||||
for everyone.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
To that end, we have developed the <a href="/cmd/godoc/">godoc</a> documentation
|
||||
tool. This article describes godoc's approach to documentation, and explains how
|
||||
you can use our conventions and tools to write good documentation for your own
|
||||
projects.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Godoc parses Go source code - including comments - and produces documentation as
|
||||
HTML or plain text. The end result is documentation tightly coupled with the
|
||||
code it documents. For example, through godoc's web interface you can navigate
|
||||
from a function's <a href="/pkg/strings/#HasPrefix">documentation</a> to its
|
||||
<a href="/src/pkg/strings/strings.go?#L312">implementation</a> with one click.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Godoc is conceptually related to Python's
|
||||
<a href="http://www.python.org/dev/peps/pep-0257/">Docstring</a> and Java's
|
||||
<a href="http://www.oracle.com/technetwork/java/javase/documentation/index-jsp-135444.html">Javadoc</a>,
|
||||
but its design is simpler. The comments read by godoc are not language
|
||||
constructs (as with Docstring) nor must they have their own machine-readable
|
||||
syntax (as with Javadoc). Godoc comments are just good comments, the sort you
|
||||
would want to read even if godoc didn't exist.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The convention is simple: to document a type, variable, constant, function, or
|
||||
even a package, write a regular comment directly preceding its declaration, with
|
||||
no intervening blank line. Godoc will then present that comment as text
|
||||
alongside the item it documents. For example, this is the documentation for the
|
||||
<code>fmt</code> package's <a href="/pkg/fmt/#Fprint"><code>Fprint</code></a>
|
||||
function:
|
||||
</p>
|
||||
|
||||
{{code "/src/pkg/fmt/print.go" `/Fprint formats using the default/` `/func Fprint/`}}
|
||||
|
||||
<p>
|
||||
Notice this comment is a complete sentence that begins with the name of the
|
||||
element it describes. This important convention allows us to generate
|
||||
documentation in a variety of formats, from plain text to HTML to UNIX man
|
||||
pages, and makes it read better when tools truncate it for brevity, such as when
|
||||
they extract the first line or sentence.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Comments on package declarations should provide general package documentation.
|
||||
These comments can be short, like the <a href="/pkg/sort/"><code>sort</code></a>
|
||||
package's brief description:
|
||||
</p>
|
||||
|
||||
{{code "/src/pkg/sort/sort.go" `/Package sort provides/` `/package sort/`}}
|
||||
|
||||
<p>
|
||||
They can also be detailed like the <a href="/pkg/encoding/gob/">gob package</a>'s
|
||||
overview. That package uses another convention for packages
|
||||
that need large amounts of introductory documentation: the package comment is
|
||||
placed in its own file, <a href="/src/pkg/encoding/gob/doc.go">doc.go</a>, which
|
||||
contains only those comments and a package clause.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
When writing package comments of any size, keep in mind that their first
|
||||
sentence will appear in godoc's <a href="/pkg/">package list</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Comments that are not adjacent to a top-level declaration are omitted from
|
||||
godoc's output, with one notable exception. Top-level comments that begin with
|
||||
the word <code>"BUG(who)”</code> are recognized as known bugs, and included in
|
||||
the "Bugs” section of the package documentation. The "who” part should be the
|
||||
user name of someone who could provide more information. For example, this is a
|
||||
known issue from the <a href="/pkg/bytes/#bugs">bytes package</a>:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
// BUG(r): The rule Title uses for word boundaries does not handle Unicode punctuation properly.
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Godoc treats executable commands somewhat differently. Instead of inspecting the
|
||||
command source code, it looks for a Go source file belonging to the special
|
||||
package "documentation”. The comment on the "package documentation” clause is
|
||||
used as the command's documentation. For example, see the
|
||||
<a href="/cmd/godoc/">godoc documentation</a> and its corresponding
|
||||
<a href="/src/cmd/godoc/doc.go">doc.go</a> file.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
There are a few formatting rules that Godoc uses when converting comments to
|
||||
HTML:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
Subsequent lines of text are considered part of the same paragraph; you must
|
||||
leave a blank line to separate paragraphs.
|
||||
</li>
|
||||
<li>
|
||||
Pre-formatted text must be indented relative to the surrounding comment text
|
||||
(see gob's <a href="/src/pkg/encoding/gob/doc.go">doc.go</a> for an example).
|
||||
</li>
|
||||
<li>
|
||||
URLs will be converted to HTML links; no special markup is necessary.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
Note that none of these rules requires you to do anything out of the ordinary.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
In fact, the best thing about godoc's minimal approach is how easy it is to use.
|
||||
As a result, a lot of Go code, including all of the standard library, already
|
||||
follows the conventions.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Your own code can present good documentation just by having comments as
|
||||
described above. Any Go packages installed inside <code>$GOROOT/src/pkg</code>
|
||||
and any <code>GOPATH</code> work spaces will already be accessible via godoc's
|
||||
command-line and HTTP interfaces, and you can specify additional paths for
|
||||
indexing via the <code>-path</code> flag or just by running <code>"godoc ."</code>
|
||||
in the source directory. See the <a href="/cmd/godoc/">godoc documentation</a>
|
||||
for more details.
|
||||
</p>
|
||||
@@ -1,348 +0,0 @@
|
||||
<!--{
|
||||
"Title": "Go's Declaration Syntax"
|
||||
}-->
|
||||
|
||||
<p>
|
||||
Newcomers to Go wonder why the declaration syntax is different from the
|
||||
tradition established in the C family. In this post we'll compare the
|
||||
two approaches and explain why Go's declarations look as they do.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b>C syntax</b>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
First, let's talk about C syntax. C took an unusual and clever approach
|
||||
to declaration syntax. Instead of describing the types with special
|
||||
syntax, one writes an expression involving the item being declared, and
|
||||
states what type that expression will have. Thus
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
int x;
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
declares x to be an int: the expression 'x' will have type int. In
|
||||
general, to figure out how to write the type of a new variable, write an
|
||||
expression involving that variable that evaluates to a basic type, then
|
||||
put the basic type on the left and the expression on the right.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Thus, the declarations
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
int *p;
|
||||
int a[3];
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
state that p is a pointer to int because '*p' has type int, and that a
|
||||
is an array of ints because a[3] (ignoring the particular index value,
|
||||
which is punned to be the size of the array) has type int.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
What about functions? Originally, C's function declarations wrote the
|
||||
types of the arguments outside the parens, like this:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
int main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{ /* ... */ }
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Again, we see that main is a function because the expression main(argc,
|
||||
argv) returns an int. In modern notation we'd write
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
int main(int argc, char *argv[]) { /* ... */ }
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
but the basic structure is the same.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
This is a clever syntactic idea that works well for simple types but can
|
||||
get confusing fast. The famous example is declaring a function pointer.
|
||||
Follow the rules and you get this:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
int (*fp)(int a, int b);
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Here, fp is a pointer to a function because if you write the expression
|
||||
(*fp)(a, b) you'll call a function that returns int. What if one of fp's
|
||||
arguments is itself a function?
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
int (*fp)(int (*ff)(int x, int y), int b)
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
That's starting to get hard to read.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Of course, we can leave out the name of the parameters when we declare a
|
||||
function, so main can be declared
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
int main(int, char *[])
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Recall that argv is declared like this,
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
char *argv[]
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
so you drop the name from the <em>middle</em> of its declaration to construct
|
||||
its type. It's not obvious, though, that you declare something of type
|
||||
char *[] by putting its name in the middle.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
And look what happens to fp's declaration if you don't name the
|
||||
parameters:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
int (*fp)(int (*)(int, int), int)
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Not only is it not obvious where to put the name inside
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
int (*)(int, int)
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
it's not exactly clear that it's a function pointer declaration at all.
|
||||
And what if the return type is a function pointer?
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
int (*(*fp)(int (*)(int, int), int))(int, int)
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
It's hard even to see that this declaration is about fp.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
You can construct more elaborate examples but these should illustrate
|
||||
some of the difficulties that C's declaration syntax can introduce.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
There's one more point that needs to be made, though. Because type and
|
||||
declaration syntax are the same, it can be difficult to parse
|
||||
expressions with types in the middle. This is why, for instance, C casts
|
||||
always parenthesize the type, as in
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
(int)M_PI
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
<b>Go syntax</b>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Languages outside the C family usually use a distinct type syntax in
|
||||
declarations. Although it's a separate point, the name usually comes
|
||||
first, often followed by a colon. Thus our examples above become
|
||||
something like (in a fictional but illustrative language)
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
x: int
|
||||
p: pointer to int
|
||||
a: array[3] of int
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
These declarations are clear, if verbose - you just read them left to
|
||||
right. Go takes its cue from here, but in the interests of brevity it
|
||||
drops the colon and removes some of the keywords:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
x int
|
||||
p *int
|
||||
a [3]int
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
There is no direct correspondence between the look of [3]int and how to
|
||||
use a in an expression. (We'll come back to pointers in the next
|
||||
section.) You gain clarity at the cost of a separate syntax.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Now consider functions. Let's transcribe the declaration for main, even
|
||||
though the main function in Go takes no arguments:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
func main(argc int, argv *[]byte) int
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Superficially that's not much different from C, but it reads well from
|
||||
left to right:
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<em>function main takes an int and a pointer to a slice of bytes and returns an int.</em>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Drop the parameter names and it's just as clear - they're always first
|
||||
so there's no confusion.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
func main(int, *[]byte) int
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
One value of this left-to-right style is how well it works as the types
|
||||
become more complex. Here's a declaration of a function variable
|
||||
(analogous to a function pointer in C):
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
f func(func(int,int) int, int) int
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Or if f returns a function:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
f func(func(int,int) int, int) func(int, int) int
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
It still reads clearly, from left to right, and it's always obvious
|
||||
which name is being declared - the name comes first.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The distinction between type and expression syntax makes it easy to
|
||||
write and invoke closures in Go:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
sum := func(a, b int) int { return a+b } (3, 4)
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
<b>Pointers</b>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Pointers are the exception that proves the rule. Notice that in arrays
|
||||
and slices, for instance, Go's type syntax puts the brackets on the left
|
||||
of the type but the expression syntax puts them on the right of the
|
||||
expression:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
var a []int
|
||||
x = a[1]
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
For familiarity, Go's pointers use the * notation from C, but we could
|
||||
not bring ourselves to make a similar reversal for pointer types. Thus
|
||||
pointers work like this
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
var p *int
|
||||
x = *p
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
We couldn't say
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
var p *int
|
||||
x = p*
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
because that postfix * would conflate with multiplication. We could have
|
||||
used the Pascal ^, for example:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
var p ^int
|
||||
x = p^
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
and perhaps we should have (and chosen another operator for xor),
|
||||
because the prefix asterisk on both types and expressions complicates
|
||||
things in a number of ways. For instance, although one can write
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
[]int("hi")
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
as a conversion, one must parenthesize the type if it starts with a *:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
(*int)(nil)
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Had we been willing to give up * as pointer syntax, those parentheses
|
||||
would be unnecessary.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
So Go's pointer syntax is tied to the familiar C form, but those ties
|
||||
mean that we cannot break completely from using parentheses to
|
||||
disambiguate types and expressions in the grammar.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Overall, though, we believe Go's type syntax is easier to understand
|
||||
than C's, especially when things get complicated.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b>Notes</b>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Go's declarations read left to right. It's been pointed out that C's
|
||||
read in a spiral! See <a href="http://c-faq.com/decl/spiral.anderson.html">
|
||||
The "Clockwise/Spiral Rule"</a> by David Anderson.
|
||||
</p>
|
||||
|
Before Width: | Height: | Size: 93 KiB |
|
Before Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 93 KiB |
|
Before Width: | Height: | Size: 59 KiB |
|
Before Width: | Height: | Size: 67 KiB |
|
Before Width: | Height: | Size: 94 KiB |
|
Before Width: | Height: | Size: 61 KiB |
|
Before Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 1.6 KiB |
@@ -1,222 +0,0 @@
|
||||
<!--{
|
||||
"Title": "The Go image/draw package",
|
||||
"Template": true
|
||||
}-->
|
||||
|
||||
<p>
|
||||
<a href="/pkg/image/draw/">Package image/draw</a> defines
|
||||
only one operation: drawing a source image onto a destination
|
||||
image, through an optional mask image. This one operation is
|
||||
surprisingly versatile and can perform a number of common image
|
||||
manipulation tasks elegantly and efficiently.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Composition is performed pixel by pixel in the style of the Plan 9
|
||||
graphics library and the X Render extension. The model is based on
|
||||
the classic "Compositing Digital Images" paper by Porter and Duff,
|
||||
with an additional mask parameter: <code>dst = (src IN mask) OP dst</code>.
|
||||
For a fully opaque mask, this reduces to the original Porter-Duff
|
||||
formula: <code>dst = src OP dst</code>. In Go, a nil mask image is equivalent
|
||||
to an infinitely sized, fully opaque mask image.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The Porter-Duff paper presented
|
||||
<a href="http://www.w3.org/TR/SVGCompositing/examples/compop-porterduff-examples.png">12 different composition operators</a>,
|
||||
but with an explicit mask, only 2 of these are needed in practice:
|
||||
source-over-destination and source. In Go, these operators are
|
||||
represented by the <code>Over</code> and <code>Src</code> constants. The <code>Over</code> operator
|
||||
performs the natural layering of a source image over a destination
|
||||
image: the change to the destination image is smaller where the
|
||||
source (after masking) is more transparent (that is, has lower
|
||||
alpha). The <code>Src</code> operator merely copies the source (after masking)
|
||||
with no regard for the destination image's original content. For
|
||||
fully opaque source and mask images, the two operators produce the
|
||||
same output, but the <code>Src</code> operator is usually faster.
|
||||
</p>
|
||||
|
||||
<p><b>Geometric Alignment</b></p>
|
||||
|
||||
<p>
|
||||
Composition requires associating destination pixels with source and
|
||||
mask pixels. Obviously, this requires destination, source and mask
|
||||
images, and a composition operator, but it also requires specifying
|
||||
what rectangle of each image to use. Not every drawing should write
|
||||
to the entire destination: when updating an animating image, it is
|
||||
more efficient to only draw the parts of the image that have
|
||||
changed. Not every drawing should read from the entire source: when
|
||||
using a sprite that combines many small images into one large one,
|
||||
only a part of the image is needed. Not every drawing should read
|
||||
from the entire mask: a mask image that collects a font's glyphs is
|
||||
similar to a sprite. Thus, drawing also needs to know three
|
||||
rectangles, one for each image. Since each rectangle has the same
|
||||
width and height, it suffices to pass a destination rectangle `r`
|
||||
and two points <code>sp</code> and <code>mp</code>: the source rectangle is equal to <code>r</code>
|
||||
translated so that <code>r.Min</code> in the destination image aligns with
|
||||
<code>sp</code> in the source image, and similarly for <code>mp</code>. The effective
|
||||
rectangle is also clipped to each image's bounds in their
|
||||
respective co-ordinate space.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<img src="image-20.png">
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The <a href="/pkg/image/draw/#DrawMask"><code>DrawMask</code></a>
|
||||
function takes seven arguments, but an explicit mask and mask-point
|
||||
are usually unnecessary, so the
|
||||
<a href="/pkg/image/draw/#Draw"><code>Draw</code></a> function takes five:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
// Draw calls DrawMask with a nil mask.
|
||||
func Draw(dst Image, r image.Rectangle, src image.Image, sp image.Point, op Op)
|
||||
func DrawMask(dst Image, r image.Rectangle, src image.Image, sp image.Point,
|
||||
mask image.Image, mp image.Point, op Op)
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
The destination image must be mutable, so the image/draw package
|
||||
defines a <a href="/pkg/image/draw/#Image"><code>draw.Image</code></a>
|
||||
interface which has a <code>Set</code> method.
|
||||
</p>
|
||||
|
||||
{{code "../src/pkg/image/draw/draw.go" `/type Image/` `/}/`}}
|
||||
|
||||
<p><b>Filling a Rectangle</b></p>
|
||||
|
||||
<p>
|
||||
To fill a rectangle with a solid color, use an <code>image.Uniform</code>
|
||||
source. The <code>ColorImage</code> type re-interprets a <code>Color</code> as a
|
||||
practically infinite-sized <code>Image</code> of that color. For those
|
||||
familiar with the design of Plan 9's draw library, there is no need
|
||||
for an explicit "repeat bit" in Go's slice-based image types; the
|
||||
concept is subsumed by <code>Uniform</code>.
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/image_draw.go" `/ZERO/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
To initialize a new image to all-blue:
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/image_draw.go" `/BLUE/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
To reset an image to transparent (or black, if the destination
|
||||
image's color model cannot represent transparency), use
|
||||
<code>image.Transparent</code>, which is an <code>image.Uniform</code>:
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/image_draw.go" `/RESET/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
<img src="image-2a.png">
|
||||
</p>
|
||||
|
||||
|
||||
<p><b>Copying an Image</b></p>
|
||||
|
||||
<p>
|
||||
To copy from a rectangle <code>sr</code> in the source image to a rectangle
|
||||
starting at a point <code>dp</code> in the destination, convert the source
|
||||
rectangle into the destination image's co-ordinate space:
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/image_draw.go" `/RECT/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
Alternatively:
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/image_draw.go" `/RECT2/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
To copy the entire source image, use <code>sr = src.Bounds()</code>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<img src="image-2b.png">
|
||||
</p>
|
||||
|
||||
<p><b>Scrolling an Image</b></p>
|
||||
|
||||
<p>
|
||||
Scrolling an image is just copying an image to itself, with
|
||||
different destination and source rectangles. Overlapping
|
||||
destination and source images are perfectly valid, just as Go's
|
||||
built-in copy function can handle overlapping destination and
|
||||
source slices. To scroll an image m by 20 pixels:
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/image_draw.go" `/SCROLL/` `/STOP/`}}
|
||||
|
||||
<p><img src="image-2c.png"></p>
|
||||
|
||||
<p><b>Converting an Image to RGBA</b></p>
|
||||
|
||||
<p>
|
||||
The result of decoding an image format might not be an
|
||||
<code>image.RGBA</code>: decoding a GIF results in an <code>image.Paletted</code>,
|
||||
decoding a JPEG results in a <code>ycbcr.YCbCr</code>, and the result of
|
||||
decoding a PNG depends on the image data. To convert any image to
|
||||
an <code>image.RGBA</code>:
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/image_draw.go" `/CONV/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
<img src="image-2d.png">
|
||||
</p>
|
||||
|
||||
<p><b>Drawing Through a Mask</b></p>
|
||||
|
||||
<p>
|
||||
To draw an image through a circular mask with center <code>p</code> and radius
|
||||
<code>r</code>:
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/image_draw.go" `/CIRCLESTRUCT/` `/STOP/`}}
|
||||
{{code "/doc/progs/image_draw.go" `/CIRCLE2/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
<img src="image-2e.png">
|
||||
</p>
|
||||
|
||||
<p><b>Drawing Font Glyphs</b></p>
|
||||
|
||||
<p>
|
||||
To draw a font glyph in blue starting from a point <code>p</code>, draw with
|
||||
an <code>image.ColorImage</code> source and an <code>image.Alpha mask</code>. For
|
||||
simplicity, we aren't performing any sub-pixel positioning or
|
||||
rendering, or correcting for a font's height above a baseline.
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/image_draw.go" `/GLYPH/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
<img src="image-2f.png">
|
||||
</p>
|
||||
|
||||
<p><b>Performance</b></p>
|
||||
|
||||
<p>
|
||||
The image/draw package implementation demonstrates how to provide
|
||||
an image manipulation function that is both general purpose, yet
|
||||
efficient for common cases. The <code>DrawMask</code> function takes arguments
|
||||
of interface types, but immediately makes type assertions that its
|
||||
arguments are of specific struct types, corresponding to common
|
||||
operations like drawing one <code>image.RGBA</code> image onto another, or
|
||||
drawing an <code>image.Alpha</code> mask (such as a font glyph) onto an
|
||||
<code>image.RGBA</code> image. If a type assertion succeeds, that type
|
||||
information is used to run a specialized implementation of the
|
||||
general algorithm. If the assertions fail, the fallback code path
|
||||
uses the generic <code>At</code> and <code>Set</code> methods. The fast-paths are purely
|
||||
a performance optimization; the resultant destination image is the
|
||||
same either way. In practice, only a small number of special cases
|
||||
are necessary to support typical applications.
|
||||
</p>
|
||||
|
||||
|
||||
@@ -1,312 +0,0 @@
|
||||
<!--{
|
||||
"Title": "The Go image package",
|
||||
"Template": true
|
||||
}-->
|
||||
|
||||
<p>
|
||||
The <a href="/pkg/image/">image</a> and
|
||||
<a href="/pkg/image/color/">image/color</a> packages define a number of types:
|
||||
<code>color.Color</code> and <code>color.Model</code> describe colors,
|
||||
<code>image.Point</code> and <code>image.Rectangle</code> describe basic 2-D
|
||||
geometry, and <code>image.Image</code> brings the two concepts together to
|
||||
represent a rectangular grid of colors. A
|
||||
<a href="/doc/articles/image_draw.html">separate article</a> covers image
|
||||
composition with the <a href="/pkg/image/draw/">image/draw</a> package.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b>Colors and Color Models</b>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<a href="/pkg/image/color/#Color">Color</a> is an interface that defines the minimal
|
||||
method set of any type that can be considered a color: one that can be converted
|
||||
to red, green, blue and alpha values. The conversion may be lossy, such as
|
||||
converting from CMYK or YCbCr color spaces.
|
||||
</p>
|
||||
|
||||
{{code "/src/pkg/image/color/color.go" `/type Color interface/` `/^}/`}}
|
||||
|
||||
<p>
|
||||
There are three important subtleties about the return values. First, the red,
|
||||
green and blue are alpha-premultiplied: a fully saturated red that is also 25%
|
||||
transparent is represented by RGBA returning a 75% r. Second, the channels have
|
||||
a 16-bit effective range: 100% red is represented by RGBA returning an r of
|
||||
65535, not 255, so that converting from CMYK or YCbCr is not as lossy. Third,
|
||||
the type returned is <code>uint32</code>, even though the maximum value is 65535, to
|
||||
guarantee that multiplying two values together won't overflow. Such
|
||||
multiplications occur when blending two colors according to an alpha mask from a
|
||||
third color, in the style of
|
||||
<a href="https://en.wikipedia.org/wiki/Alpha_compositing">Porter and Duff's</a>
|
||||
classic algebra:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
dstr, dstg, dstb, dsta := dst.RGBA()
|
||||
srcr, srcg, srcb, srca := src.RGBA()
|
||||
_, _, _, m := mask.RGBA()
|
||||
const M = 1<<16 - 1
|
||||
// The resultant red value is a blend of dstr and srcr, and ranges in [0, M].
|
||||
// The calculation for green, blue and alpha is similar.
|
||||
dstr = (dstr*(M-m) + srcr*m) / M
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
The last line of that code snippet would have been more complicated if we worked
|
||||
with non-alpha-premultiplied colors, which is why <code>Color</code> uses
|
||||
alpha-premultiplied values.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The image/color package also defines a number of concrete types that implement
|
||||
the <code>Color</code> interface. For example,
|
||||
<a href="/pkg/image/color/#RGBA"><code>RGBA</code></a> is a struct that represents
|
||||
the classic "8 bits per channel" color.
|
||||
</p>
|
||||
|
||||
{{code "/src/pkg/image/color/color.go" `/type RGBA struct/` `/^}/`}}
|
||||
|
||||
<p>
|
||||
Note that the <code>R</code> field of an <code>RGBA</code> is an 8-bit
|
||||
alpha-premultiplied color in the range [0, 255]. <code>RGBA</code> satisfies the
|
||||
<code>Color</code> interface by multiplying that value by 0x101 to generate a
|
||||
16-bit alpha-premultiplied color in the range [0, 65535]. Similarly, the
|
||||
<a href="/pkg/image/color/#NRGBA"><code>NRGBA</code></a> struct type represents
|
||||
an 8-bit non-alpha-premultiplied color, as used by the PNG image format. When
|
||||
manipulating an <code>NRGBA</code>'s fields directly, the values are
|
||||
non-alpha-premultiplied, but when calling the <code>RGBA</code> method, the
|
||||
return values are alpha-premultiplied.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
A <a href="/pkg/image/color/#Model"><code>Model</code></a> is simply
|
||||
something that can convert <code>Color</code>s to other <code>Color</code>s, possibly lossily. For
|
||||
example, the <code>GrayModel</code> can convert any <code>Color</code> to a
|
||||
desaturated <a href="/pkg/image/color/#Gray"><code>Gray</code></a>. A
|
||||
<code>Palette</code> can convert any <code>Color</code> to one from a
|
||||
limited palette.
|
||||
</p>
|
||||
|
||||
{{code "/src/pkg/image/color/color.go" `/type Model interface/` `/^}/`}}
|
||||
|
||||
{{code "/src/pkg/image/color/color.go" `/type Palette \[\]Color/`}}
|
||||
|
||||
<p>
|
||||
<b>Points and Rectangles</b>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
A <a href="/pkg/image/#Point"><code>Point</code></a> is an (x, y) co-ordinate
|
||||
on the integer grid, with axes increasing right and down. It is neither a pixel
|
||||
nor a grid square. A <code>Point</code> has no intrinsic width, height or
|
||||
color, but the visualizations below use a small colored square.
|
||||
</p>
|
||||
|
||||
{{code "/src/pkg/image/geom.go" `/type Point struct/` `/^}/`}}
|
||||
|
||||
<p>
|
||||
<img src="image-package-01.png" width="400" height="300">
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/image_package1.go" `/p := image.Point/`}}
|
||||
|
||||
<p>
|
||||
A <a href="/pkg/image/#Rectangle"><code>Rectangle</code></a> is an axis-aligned
|
||||
rectangle on the integer grid, defined by its top-left and bottom-right
|
||||
<code>Point</code>. A <code>Rectangle</code> also has no intrinsic color, but
|
||||
the visualizations below outline rectangles with a thin colored line, and call
|
||||
out their <code>Min</code> and <code>Max</code> <code>Point</code>s.
|
||||
</p>
|
||||
|
||||
{{code "/src/pkg/image/geom.go" `/type Rectangle struct/` `/^}/`}}
|
||||
|
||||
<p>
|
||||
For convenience, <code>image.Rect(x0, y0, x1, y1)</code> is equivalent to
|
||||
<code>image.Rectangle{image.Point{x0, y0}, image.Point{x1, y1}}</code>, but is
|
||||
much easier to type.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
A <code>Rectangle</code> is inclusive at the top-left and exclusive at the
|
||||
bottom-right. For a <code>Point p</code> and a <code>Rectangle r</code>,
|
||||
<code>p.In(r)</code> if and only if
|
||||
<code>r.Min.X <= p.X && p.X < r.Max.X</code>, and similarly for <code>Y</code>. This is analagous to how
|
||||
a slice <code>s[i0:i1]</code> is inclusive at the low end and exclusive at the
|
||||
high end. (Unlike arrays and slices, a <code>Rectangle</code> often has a
|
||||
non-zero origin.)
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<img src="image-package-02.png" width="400" height="300">
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/image_package2.go" `/r := image.Rect/` `/fmt.Println/`}}
|
||||
|
||||
<p>
|
||||
Adding a <code>Point</code> to a <code>Rectangle</code> translates the
|
||||
<code>Rectangle</code>. Points and Rectangles are not restricted to be in the
|
||||
bottom-right quadrant.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<img src="image-package-03.png" width="400" height="300">
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/image_package3.go" `/r := image.Rect/` `/fmt.Println/`}}
|
||||
|
||||
<p>
|
||||
Intersecting two Rectangles yields another Rectangle, which may be empty.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<img src="image-package-04.png" width="400" height="300">
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/image_package4.go" `/r := image.Rect/` `/fmt.Printf/`}}
|
||||
|
||||
<p>
|
||||
Points and Rectangles are passed and returned by value. A function that takes a
|
||||
<code>Rectangle</code> argument will be as efficient as a function that takes
|
||||
two <code>Point</code> arguments, or four <code>int</code> arguments.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b>Images</b>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
An <a href="/pkg/image/#Image">Image</a> maps every grid square in a
|
||||
<code>Rectangle</code> to a <code>Color</code> from a <code>Model</code>.
|
||||
"The pixel at (x, y)" refers to the color of the grid square defined by the
|
||||
points (x, y), (x+1, y), (x+1, y+1) and (x, y+1).
|
||||
</p>
|
||||
|
||||
{{code "/src/pkg/image/image.go" `/type Image interface/` `/^}/`}}
|
||||
|
||||
<p>
|
||||
A common mistake is assuming that an <code>Image</code>'s bounds start at (0,
|
||||
0). For example, an animated GIF contains a sequence of Images, and each
|
||||
<code>Image</code> after the first typically only holds pixel data for the area
|
||||
that changed, and that area doesn't necessarily start at (0, 0). The correct
|
||||
way to iterate over an <code>Image</code> m's pixels looks like:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
b := m.Bounds()
|
||||
for y := b.Min.Y; y < b.Max.Y; y++ {
|
||||
for x := b.Min.X; y < b.Max.X; x++ {
|
||||
doStuffWith(m.At(x, y))
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
<code>Image</code> implementations do not have to be based on an in-memory
|
||||
slice of pixel data. For example, a
|
||||
<a href="/pkg/image/#Uniform"><code>Uniform</code></a> is an
|
||||
<code>Image</code> of enormous bounds and uniform color, whose in-memory
|
||||
representation is simply that color.
|
||||
</p>
|
||||
|
||||
{{code "/src/pkg/image/names.go" `/type Uniform struct/` `/^}/`}}
|
||||
|
||||
<p>
|
||||
Typically, though, programs will want an image based on a slice. Struct types
|
||||
like <a href="/pkg/image/#RGBA"><code>RGBA</code></a> and
|
||||
<a href="/pkg/image/#Gray"><code>Gray</code></a> (which other packages refer
|
||||
to as <code>image.RGBA</code> and <code>image.Gray</code>) hold slices of pixel
|
||||
data and implement the <code>Image</code> interface.
|
||||
</p>
|
||||
|
||||
{{code "/src/pkg/image/image.go" `/type RGBA struct/` `/^}/`}}
|
||||
|
||||
<p>
|
||||
These types also provide a <code>Set(x, y int, c color.Color)</code> method
|
||||
that allows modifying the image one pixel at a time.
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/image_package5.go" `/m := image.New/` `/m.Set/`}}
|
||||
|
||||
<p>
|
||||
If you're reading or writing a lot of pixel data, it can be more efficient, but
|
||||
more complicated, to access these struct type's <code>Pix</code> field directly.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The slice-based <code>Image</code> implementations also provide a
|
||||
<code>SubImage</code> method, which returns an <code>Image</code> backed by the
|
||||
same array. Modifying the pixels of a sub-image will affect the pixels of the
|
||||
original image, analagous to how modifying the contents of a sub-slice
|
||||
<code>s[i0:i1]</code> will affect the contents of the original slice
|
||||
<code>s</code>.
|
||||
</p>
|
||||
|
||||
<img src="image-package-05.png" width="400" height="300">
|
||||
|
||||
{{code "/doc/progs/image_package6.go" `/m0 := image.New/` `/fmt.Println\(m0.Stride/`}}
|
||||
|
||||
<p>
|
||||
For low-level code that works on an image's <code>Pix</code> field, be aware
|
||||
that ranging over <code>Pix</code> can affect pixels outside an image's bounds.
|
||||
In the example above, the pixels covered by <code>m1.Pix</code> are shaded in
|
||||
blue. Higher-level code, such as the <code>At</code> and <code>Set</code>
|
||||
methods or the <a href="/pkg/image/draw/">image/draw package</a>, will clip
|
||||
their operations to the image's bounds.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b>Image Formats</b>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The standard package library supports a number of common image formats, such as
|
||||
GIF, JPEG and PNG. If you know the format of a source image file, you can
|
||||
decode from an <a href="/pkg/io/#Reader"><code>io.Reader</code></a> directly.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
import (
|
||||
"image/jpeg"
|
||||
"image/png"
|
||||
"io"
|
||||
)
|
||||
|
||||
// convertJPEGToPNG converts from JPEG to PNG.
|
||||
func convertJPEGToPNG(w io.Writer, r io.Reader) error {
|
||||
img, err := jpeg.Decode(r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return png.Encode(w, img)
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
If you have image data of unknown format, the
|
||||
<a href="/pkg/image/#Decode"><code>image.Decode</code></a> function can detect
|
||||
the format. The set of recognized formats is constructed at run time and is not
|
||||
limited to those in the standard package library. An image format package
|
||||
typically registers its format in an init function, and the main package will
|
||||
"underscore import" such a package solely for the side effect of format
|
||||
registration.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
import (
|
||||
"image"
|
||||
"image/png"
|
||||
"io"
|
||||
|
||||
_ "code.google.com/p/vp8-go/webp"
|
||||
_ "image/jpeg"
|
||||
)
|
||||
|
||||
// convertToPNG converts from any recognized format to PNG.
|
||||
func convertToPNG(w io.Writer, r io.Reader) error {
|
||||
img, _, err := image.Decode(r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return png.Encode(w, img)
|
||||
}
|
||||
</pre>
|
||||
@@ -1,7 +0,0 @@
|
||||
<!--{
|
||||
"Title": "/doc/articles/"
|
||||
}-->
|
||||
|
||||
<p>
|
||||
See the <a href="/doc/#articles">Documents page</a> for a complete list of Go articles.
|
||||
</p>
|
||||
@@ -1,356 +0,0 @@
|
||||
<!--{
|
||||
"Title": "JSON and Go",
|
||||
"Template": true
|
||||
}-->
|
||||
|
||||
<p>
|
||||
JSON (JavaScript Object Notation) is a simple data interchange format.
|
||||
Syntactically it resembles the objects and lists of JavaScript. It is most
|
||||
commonly used for communication between web back-ends and JavaScript programs
|
||||
running in the browser, but it is used in many other places, too. Its home page,
|
||||
<a href="http://json.org">json.org</a>, provides a wonderfully clear and concise
|
||||
definition of the standard.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
With the <a href="/pkg/encoding/json/">json package</a> it's a snap to read and
|
||||
write JSON data from your Go programs.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b>Encoding</b>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
To encode JSON data we use the
|
||||
<a href="/pkg/encoding/json/#Marshal"><code>Marshal</code></a> function.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
func Marshal(v interface{}) ([]byte, error)
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Given the Go data structure, <code>Message</code>,
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/json1.go" `/type Message/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
and an instance of <code>Message</code>
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/json1.go" `/m :=/`}}
|
||||
|
||||
<p>
|
||||
we can marshal a JSON-encoded version of m using <code>json.Marshal</code>:
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/json1.go" `/b, err :=/`}}
|
||||
|
||||
<p>
|
||||
If all is well, <code>err</code> will be <code>nil</code> and <code>b</code>
|
||||
will be a <code>[]byte</code> containing this JSON data:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
b == []byte(`{"Name":"Alice","Body":"Hello","Time":1294706395881547000}`)
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Only data structures that can be represented as valid JSON will be encoded:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
JSON objects only support strings as keys; to encode a Go map type it must be
|
||||
of the form <code>map[string]T</code> (where <code>T</code> is any Go type
|
||||
supported by the json package).
|
||||
</li>
|
||||
<li>
|
||||
Channel, complex, and function types cannot be encoded.
|
||||
</li>
|
||||
<li>
|
||||
Cyclic data structures are not supported; they will cause <code>Marshal</code>
|
||||
to go into an infinite loop.
|
||||
</li>
|
||||
<li>
|
||||
Pointers will be encoded as the values they point to (or 'null' if the pointer
|
||||
is <code>nil</code>).
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
The json package only accesses the exported fields of struct types (those that
|
||||
begin with an uppercase letter). Therefore only the the exported fields of a
|
||||
struct will be present in the JSON output.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b>Decoding</b>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
To decode JSON data we use the
|
||||
<a href="/pkg/encoding/json/#Unmarshal"><code>Unmarshal</code></a> function.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
func Unmarshal(data []byte, v interface{}) error
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
We must first create a place where the decoded data will be stored
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/json1.go" `/var m Message/`}}
|
||||
|
||||
<p>
|
||||
and call <code>json.Unmarshal</code>, passing it a <code>[]byte</code> of JSON
|
||||
data and a pointer to <code>m</code>
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/json1.go" `/err := json.Unmarshal/`}}
|
||||
|
||||
<p>
|
||||
If <code>b</code> contains valid JSON that fits in <code>m</code>, after the
|
||||
call <code>err</code> will be <code>nil</code> and the data from <code>b</code>
|
||||
will have been stored in the struct <code>m</code>, as if by an assignment
|
||||
like:
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/json1.go" `/m = Message/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
How does <code>Unmarshal</code> identify the fields in which to store the
|
||||
decoded data? For a given JSON key <code>"Foo"</code>, <code>Unmarshal</code>
|
||||
will look through the destination struct's fields to find (in order of
|
||||
preference):
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
An exported field with a tag of <code>"Foo"</code> (see the
|
||||
<a href="/ref/spec#Struct_types">Go spec</a> for more on struct tags),
|
||||
</li>
|
||||
<li>
|
||||
An exported field named <code>"Foo"</code>, or
|
||||
</li>
|
||||
<li>
|
||||
An exported field named <code>"FOO"</code> or <code>"FoO"</code> or some other
|
||||
case-insensitive match of <code>"Foo"</code>.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
What happens when the structure of the JSON data doesn't exactly match the Go
|
||||
type?
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/json1.go" `/"Food":"Pickle"/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
<code>Unmarshal</code> will decode only the fields that it can find in the
|
||||
destination type. In this case, only the Name field of m will be populated,
|
||||
and the Food field will be ignored. This behavior is particularly useful when
|
||||
you wish to pick only a few specific fields out of a large JSON blob. It also
|
||||
means that any unexported fields in the destination struct will be unaffected
|
||||
by <code>Unmarshal</code>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
But what if you don't know the structure of your JSON data beforehand?
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b>Generic JSON with interface{}</b>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The <code>interface{}</code> (empty interface) type describes an interface with
|
||||
zero methods. Every Go type implements at least zero methods and therefore
|
||||
satisfies the empty interface.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The empty interface serves as a general container type:
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/json2.go" `/var i interface{}/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
A type assertion accesses the underlying concrete type:
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/json2.go" `/r := i/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
Or, if the underlying type is unknown, a type switch determines the type:
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/json2.go" `/switch v/` `/STOP/`}}
|
||||
|
||||
|
||||
The json package uses <code>map[string]interface{}</code> and
|
||||
<code>[]interface{}</code> values to store arbitrary JSON objects and arrays;
|
||||
it will happily unmarshal any valid JSON blob into a plain
|
||||
<code>interface{}</code> value. The default concrete Go types are:
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<code>bool</code> for JSON booleans,
|
||||
</li>
|
||||
<li>
|
||||
<code>float64</code> for JSON numbers,
|
||||
</li>
|
||||
<li>
|
||||
<code>string</code> for JSON strings, and
|
||||
</li>
|
||||
<li>
|
||||
<code>nil</code> for JSON null.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
<b>Decoding arbitrary data</b>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Consider this JSON data, stored in the variable <code>b</code>:
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/json3.go" `/b :=/`}}
|
||||
|
||||
<p>
|
||||
Without knowing this data's structure, we can decode it into an
|
||||
<code>interface{}</code> value with <code>Unmarshal</code>:
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/json3.go" `/var f interface/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
At this point the Go value in <code>f</code> would be a map whose keys are
|
||||
strings and whose values are themselves stored as empty interface values:
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/json3.go" `/f = map/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
To access this data we can use a type assertion to access <code>f</code>'s
|
||||
underlying <code>map[string]interface{}</code>:
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/json3.go" `/m := f/`}}
|
||||
|
||||
<p>
|
||||
We can then iterate through the map with a range statement and use a type switch
|
||||
to access its values as their concrete types:
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/json3.go" `/for k, v/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
In this way you can work with unknown JSON data while still enjoying the
|
||||
benefits of type safety.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b>Reference Types</b>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Let's define a Go type to contain the data from the previous example:
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/json4.go" `/type FamilyMember/` `/STOP/`}}
|
||||
|
||||
{{code "/doc/progs/json4.go" `/var m FamilyMember/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
Unmarshaling that data into a <code>FamilyMember</code> value works as
|
||||
expected, but if we look closely we can see a remarkable thing has happened.
|
||||
With the var statement we allocated a <code>FamilyMember</code> struct, and
|
||||
then provided a pointer to that value to <code>Unmarshal</code>, but at that
|
||||
time the <code>Parents</code> field was a <code>nil</code> slice value. To
|
||||
populate the <code>Parents</code> field, <code>Unmarshal</code> allocated a new
|
||||
slice behind the scenes. This is typical of how <code>Unmarshal</code> works
|
||||
with the supported reference types (pointers, slices, and maps).
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Consider unmarshaling into this data structure:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
type Foo struct {
|
||||
Bar *Bar
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
If there were a <code>Bar</code> field in the JSON object,
|
||||
<code>Unmarshal</code> would allocate a new <code>Bar</code> and populate it.
|
||||
If not, <code>Bar</code> would be left as a <code>nil</code> pointer.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
From this a useful pattern arises: if you have an application that receives a
|
||||
few distinct message types, you might define "receiver" structure like
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
type IncomingMessage struct {
|
||||
Cmd *Command
|
||||
Msg *Message
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
and the sending party can populate the <code>Cmd</code> field and/or the
|
||||
<code>Msg</code> field of the top-level JSON object, depending on the type of
|
||||
message they want to communicate. <code>Unmarshal</code>, when decoding the
|
||||
JSON into an <code>IncomingMessage</code> struct, will only allocate the data
|
||||
structures present in the JSON data. To know which messages to process, the
|
||||
programmer need simply test that either <code>Cmd</code> or <code>Msg</code> is
|
||||
not <code>nil</code>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b>Streaming Encoders and Decoders</b>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The json package provides <code>Decoder</code> and <code>Encoder</code> types
|
||||
to support the common operation of reading and writing streams of JSON data.
|
||||
The <code>NewDecoder</code> and <code>NewEncoder</code> functions wrap the
|
||||
<a href="/pkg/io/#Reader"><code>io.Reader</code></a> and
|
||||
<a href="/pkg/io/#Writer"><code>io.Writer</code></a> interface types.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
func NewDecoder(r io.Reader) *Decoder
|
||||
func NewEncoder(w io.Writer) *Encoder
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Here's an example program that reads a series of JSON objects from standard
|
||||
input, removes all but the <code>Name</code> field from each object, and then
|
||||
writes the objects to standard output:
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/json5.go" `/package main/` `$`}}
|
||||
|
||||
<p>
|
||||
Due to the ubiquity of Readers and Writers, these <code>Encoder</code> and
|
||||
<code>Decoder</code> types can be used in a broad range of scenarios, such as
|
||||
reading and writing to HTTP connections, WebSockets, or files.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b>References</b>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
For more information see the <a href="/pkg/encoding/json/">json package documentation</a>. For an example usage of
|
||||
json see the source files of the <a href="/pkg/net/rpc/jsonrpc/">jsonrpc package</a>.
|
||||
</p>
|
||||
@@ -1,78 +0,0 @@
|
||||
<!--{
|
||||
"Title": "JSON-RPC: a tale of interfaces"
|
||||
}-->
|
||||
|
||||
<p>
|
||||
Here we present an example where Go's
|
||||
<a href="/doc/effective_go.html#interfaces_and_types">interfaces</a> made it
|
||||
easy to refactor some existing code to make it more flexible and extensible.
|
||||
Originally, the standard library's <a href="/pkg/net/rpc/">RPC package</a> used
|
||||
a custom wire format called <a href="/pkg/encoding/gob/">gob</a>. For a
|
||||
particular application, we wanted to use <a href="/pkg/encoding/json/">JSON</a>
|
||||
as an alternate wire format.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
We first defined a pair of interfaces to describe the functionality of the
|
||||
existing wire format, one for the client, and one for the server (depicted
|
||||
below).
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
type ServerCodec interface {
|
||||
ReadRequestHeader(*Request) error
|
||||
ReadRequestBody(interface{}) error
|
||||
WriteResponse(*Response, interface{}) error
|
||||
Close() error
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
On the server side, we then changed two internal function signatures to accept
|
||||
the <code>ServerCodec</code> interface instead of our existing
|
||||
<code>gob.Encoder</code>. Here's one of them:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
func sendResponse(sending *sync.Mutex, req *Request,
|
||||
reply interface{}, enc *gob.Encoder, errmsg string)
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
became
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
func sendResponse(sending *sync.Mutex, req *Request,
|
||||
reply interface{}, enc ServerCodec, errmsg string)
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
We then wrote a trivial <code>gobServerCodec</code> wrapper to reproduce the
|
||||
original functionality. From there it is simple to build a
|
||||
<code>jsonServerCodec</code>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
After some similar changes to the client side, this was the full extent of the
|
||||
work we needed to do on the RPC package. This whole exercise took about 20
|
||||
minutes! After tidying up and testing the new code, the
|
||||
<a href="http://code.google.com/p/go/source/diff?spec=svn9daf796ebf1cae97b2fcf760a4ab682f1f063f29&r=9daf796ebf1cae97b2fcf760a4ab682f1f063f29&format=side&path=/src/pkg/rpc/server.go">final changeset</a>
|
||||
was submitted.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
In an inheritance-oriented language like Java or C++, the obvious path would be
|
||||
to generalize the RPC class, and create JsonRPC and GobRPC subclasses. However,
|
||||
this approach becomes tricky if you want to make a further generalization
|
||||
orthogonal to that hierarchy. (For example, if you were to implement an
|
||||
alternate RPC standard). In our Go package, we took a route that is both
|
||||
conceptually simpler and requires less code be written or changed.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
A vital quality for any codebase is maintainability. As needs change, it is
|
||||
essential to adapt your code easily and cleanly, lest it become unwieldy to work
|
||||
with. We believe Go's lightweight, composition-oriented type system provides a
|
||||
means of structuring code that scales.
|
||||
</p>
|
||||
@@ -1,649 +0,0 @@
|
||||
<!--{
|
||||
"Title": "The Laws of Reflection",
|
||||
"Template": true
|
||||
}-->
|
||||
|
||||
<p>
|
||||
Reflection in computing is the
|
||||
ability of a program to examine its own structure, particularly
|
||||
through types; it's a form of metaprogramming. It's also a great
|
||||
source of confusion.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
In this article we attempt to clarify things by explaining how
|
||||
reflection works in Go. Each language's reflection model is
|
||||
different (and many languages don't support it at all), but
|
||||
this article is about Go, so for the rest of this article the word
|
||||
"reflection" should be taken to mean "reflection in Go".
|
||||
</p>
|
||||
|
||||
<p><b>Types and interfaces</b></p>
|
||||
|
||||
<p>
|
||||
Because reflection builds on the type system, let's start with a
|
||||
refresher about types in Go.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Go is statically typed. Every variable has a static type, that is,
|
||||
exactly one type known and fixed at compile time: <code>int</code>,
|
||||
<code>float32</code>, <code>*MyType</code>, <code>[]byte</code>,
|
||||
and so on. If we declare
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/interface.go" `/type MyInt/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
then <code>i</code> has type <code>int</code> and <code>j</code>
|
||||
has type <code>MyInt</code>. The variables <code>i</code> and
|
||||
<code>j</code> have distinct static types and, although they have
|
||||
the same underlying type, they cannot be assigned to one another
|
||||
without a conversion.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
One important category of type is interface types, which represent
|
||||
fixed sets of methods. An interface variable can store any concrete
|
||||
(non-interface) value as long as that value implements the
|
||||
interface's methods. A well-known pair of examples is
|
||||
<code>io.Reader</code> and <code>io.Writer</code>, the types
|
||||
<code>Reader</code> and <code>Writer</code> from the
|
||||
<a href="/pkg/io/">io package</a>:
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/interface.go" `/// Reader/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
Any type that implements a <code>Read</code> (or
|
||||
<code>Write</code>) method with this signature is said to implement
|
||||
<code>io.Reader</code> (or <code>io.Writer</code>). For the
|
||||
purposes of this discussion, that means that a variable of type
|
||||
<code>io.Reader</code> can hold any value whose type has a
|
||||
<code>Read</code> method:
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/interface.go" `/func readers/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
It's important to be clear that whatever concrete value
|
||||
<code>r</code> may hold, <code>r</code>'s type is always
|
||||
<code>io.Reader</code>: Go is statically typed and the static type
|
||||
of <code>r</code> is <code>io.Reader</code>.</p>
|
||||
|
||||
<p>
|
||||
An extremely important example of an interface type is the empty
|
||||
interface:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
interface{}
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
It represents the empty set of methods and is satisfied by any
|
||||
value at all, since any value has zero or more methods.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Some people say that Go's interfaces are dynamically typed, but
|
||||
that is misleading. They are statically typed: a variable of
|
||||
interface type always has the same static type, and even though at
|
||||
run time the value stored in the interface variable may change
|
||||
type, that value will always satisfy the interface.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
We need to be precise about all this because reflection and
|
||||
interfaces are closely related.
|
||||
</p>
|
||||
|
||||
<p><b>The representation of an interface</b></p>
|
||||
|
||||
<p>
|
||||
Russ Cox has written a
|
||||
<a href="http://research.swtch.com/2009/12/go-data-structures-interfaces.html">detailed blog post</a>
|
||||
about the representation of interface values in Go. It's not necessary to
|
||||
repeat the full story here, but a simplified summary is in order.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
A variable of interface type stores a pair: the concrete value
|
||||
assigned to the variable, and that value's type descriptor.
|
||||
To be more precise, the value is the underlying concrete data item
|
||||
that implements the interface and the type describes the full type
|
||||
of that item. For instance, after
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/interface.go" `/func typeAssertions/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
<code>r</code> contains, schematically, the (value, type) pair,
|
||||
(<code>tty</code>, <code>*os.File</code>). Notice that the type
|
||||
<code>*os.File</code> implements methods other than
|
||||
<code>Read</code>; even though the interface value provides access
|
||||
only to the <code>Read</code> method, the value inside carries all
|
||||
the type information about that value. That's why we can do things
|
||||
like this:
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/interface.go" `/var w io.Writer/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
The expression in this assignment is a type assertion; what it
|
||||
asserts is that the item inside <code>r</code> also implements
|
||||
<code>io.Writer</code>, and so we can assign it to <code>w</code>.
|
||||
After the assignment, <code>w</code> will contain the pair
|
||||
(<code>tty</code>, <code>*os.File</code>). That's the same pair as
|
||||
was held in <code>r</code>. The static type of the interface
|
||||
determines what methods may be invoked with an interface variable,
|
||||
even though the concrete value inside may have a larger set of
|
||||
methods.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Continuing, we can do this:
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/interface.go" `/var empty interface{}/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
and our empty interface value <code>e</code> will again contain
|
||||
that same pair, (<code>tty</code>, <code>*os.File</code>). That's
|
||||
handy: an empty interface can hold any value and contains all the
|
||||
information we could ever need about that value.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
(We don't need a type assertion here because it's known statically
|
||||
that <code>w</code> satisfies the empty interface. In the example
|
||||
where we moved a value from a <code>Reader</code> to a
|
||||
<code>Writer</code>, we needed to be explicit and use a type
|
||||
assertion because <code>Writer</code>'s methods are not a
|
||||
subset of <code>Reader</code>'s.)
|
||||
</p>
|
||||
|
||||
<p>
|
||||
One important detail is that the pair inside an interface always
|
||||
has the form (value, concrete type) and cannot have the form
|
||||
(value, interface type). Interfaces do not hold interface
|
||||
values.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Now we're ready to reflect.
|
||||
</p>
|
||||
|
||||
<p><b>The first law of reflection</b></p>
|
||||
|
||||
<p><b>1. Reflection goes from interface value to reflection object.</b></p>
|
||||
|
||||
<p>
|
||||
At the basic level, reflection is just a mechanism to examine the
|
||||
type and value pair stored inside an interface variable. To get
|
||||
started, there are two types we need to know about in
|
||||
<a href="/pkg/reflect/">package reflect</a>:
|
||||
<a href="/pkg/reflect/#Type">Type</a> and
|
||||
<a href="/pkg/reflect/#Value">Value</a>. Those two types
|
||||
give access to the contents of an interface variable, and two
|
||||
simple functions, called <code>reflect.TypeOf</code> and
|
||||
<code>reflect.ValueOf</code>, retrieve <code>reflect.Type</code>
|
||||
and <code>reflect.Value</code> pieces out of an interface value.
|
||||
(Also, from the <code>reflect.Value</code> it's easy to get
|
||||
to the <code>reflect.Type</code>, but let's keep the
|
||||
<code>Value</code> and <code>Type</code> concepts separate for
|
||||
now.)
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Let's start with <code>TypeOf</code>:
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/interface2.go" `/package main/` `/STOP main/`}}
|
||||
|
||||
<p>
|
||||
This program prints
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
type: float64
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
You might be wondering where the interface is here, since the program looks
|
||||
like it's passing the <code>float64</code> variable <code>x</code>, not an
|
||||
interface value, to <code>reflect.TypeOf</code>. But it's there; as
|
||||
<a href="/pkg/reflect/#Type.TypeOf">godoc reports</a>, the signature of
|
||||
<code>reflect.TypeOf</code> includes an empty interface:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
// TypeOf returns the reflection Type of the value in the interface{}.
|
||||
func TypeOf(i interface{}) Type
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
When we call <code>reflect.TypeOf(x)</code>, <code>x</code> is
|
||||
first stored in an empty interface, which is then passed as the
|
||||
argument; <code>reflect.TypeOf</code> unpacks that empty interface
|
||||
to recover the type information.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The <code>reflect.ValueOf</code> function, of course, recovers the
|
||||
value (from here on we'll elide the boilerplate and focus just on
|
||||
the executable code):
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/interface2.go" `/START f9/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
prints
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
value: <float64 Value>
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Both <code>reflect.Type</code> and <code>reflect.Value</code> have
|
||||
lots of methods to let us examine and manipulate them. One
|
||||
important example is that <code>Value</code> has a
|
||||
<code>Type</code> method that returns the <code>Type</code> of a
|
||||
<code>reflect.Value</code>. Another is that both <code>Type</code>
|
||||
and <code>Value</code> have a <code>Kind</code> method that returns
|
||||
a constant indicating what sort of item is stored:
|
||||
<code>Uint</code>, <code>Float64</code>, <code>Slice</code>, and so
|
||||
on. Also methods on <code>Value</code> with names like
|
||||
<code>Int</code> and <code>Float</code> let us grab values (as
|
||||
<code>int64</code> and <code>float64</code>) stored inside:
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/interface2.go" `/START f1/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
prints
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
type: float64
|
||||
kind is float64: true
|
||||
value: 3.4
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
There are also methods like <code>SetInt</code> and
|
||||
<code>SetFloat</code> but to use them we need to understand
|
||||
settability, the subject of the third law of reflection, discussed
|
||||
below.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The reflection library has a couple of properties worth singling
|
||||
out. First, to keep the API simple, the "getter" and "setter"
|
||||
methods of <code>Value</code> operate on the largest type that can
|
||||
hold the value: <code>int64</code> for all the signed integers, for
|
||||
instance. That is, the <code>Int</code> method of
|
||||
<code>Value</code> returns an <code>int64</code> and the
|
||||
<code>SetInt</code> value takes an <code>int64</code>; it may be
|
||||
necessary to convert to the actual type involved:
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/interface2.go" `/START f2/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
The second property is that the <code>Kind</code> of a reflection
|
||||
object describes the underlying type, not the static type. If a
|
||||
reflection object contains a value of a user-defined integer type,
|
||||
as in
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/interface2.go" `/START f3/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
the <code>Kind</code> of <code>v</code> is still
|
||||
<code>reflect.Int</code>, even though the static type of
|
||||
<code>x</code> is <code>MyInt</code>, not <code>int</code>. In
|
||||
other words, the <code>Kind</code> cannot discriminate an int from
|
||||
a <code>MyInt</code> even though the <code>Type</code> can.
|
||||
</p>
|
||||
|
||||
<p><b>The second law of reflection</b></p>
|
||||
|
||||
<p><b>2. Reflection goes from reflection object to interface
|
||||
value.</b></p>
|
||||
|
||||
<p>
|
||||
Like physical reflection, reflection in Go generates its own
|
||||
inverse.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Given a <code>reflect.Value</code> we can recover an interface
|
||||
value using the <code>Interface</code> method; in effect the method
|
||||
packs the type and value information back into an interface
|
||||
representation and returns the result:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
// Interface returns v's value as an interface{}.
|
||||
func (v Value) Interface() interface{}
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
As a consequence we can say
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/interface2.go" `/START f3b/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
to print the <code>float64</code> value represented by the
|
||||
reflection object <code>v</code>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
We can do even better, though. The arguments to
|
||||
<code>fmt.Println</code>, <code>fmt.Printf</code> and so on are all
|
||||
passed as empty interface values, which are then unpacked by the
|
||||
<code>fmt</code> package internally just as we have been doing in
|
||||
the previous examples. Therefore all it takes to print the contents
|
||||
of a <code>reflect.Value</code> correctly is to pass the result of
|
||||
the <code>Interface</code> method to the formatted print
|
||||
routine:
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/interface2.go" `/START f3c/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
(Why not <code>fmt.Println(v)</code>? Because <code>v</code> is a
|
||||
<code>reflect.Value</code>; we want the concrete value it holds.)
|
||||
Since our value is a <code>float64</code>, we can even use a
|
||||
floating-point format if we want:
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/interface2.go" `/START f3d/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
and get in this case
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
3.4e+00
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Again, there's no need to type-assert the result of
|
||||
<code>v.Interface()</code> to <code>float64</code>; the empty
|
||||
interface value has the concrete value's type information inside
|
||||
and <code>Printf</code> will recover it.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
In short, the <code>Interface</code> method is the inverse of the
|
||||
<code>ValueOf</code> function, except that its result is always of
|
||||
static type <code>interface{}</code>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Reiterating: Reflection goes from interface values to reflection
|
||||
objects and back again.
|
||||
</p>
|
||||
|
||||
<p><b>The third law of reflection</b></p>
|
||||
|
||||
<p><b>3. To modify a reflection object, the value must be settable.</b></p>
|
||||
|
||||
<p>
|
||||
The third law is the most subtle and confusing, but it's easy
|
||||
enough to understand if we start from first principles.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Here is some code that does not work, but is worth studying.
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/interface2.go" `/START f4/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
If you run this code, it will panic with the cryptic message
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
panic: reflect.Value.SetFloat using unaddressable value
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
The problem is not that the value <code>7.1</code> is not
|
||||
addressable; it's that <code>v</code> is not settable. Settability
|
||||
is a property of a reflection <code>Value</code>, and not all
|
||||
reflection <code>Values</code> have it.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The <code>CanSet</code> method of <code>Value</code> reports the
|
||||
settability of a <code>Value</code>; in our case,
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/interface2.go" `/START f5/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
prints
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
settability of v: false
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
It is an error to call a <code>Set</code> method on an non-settable
|
||||
<code>Value</code>. But what is settability?
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Settability is a bit like addressability, but stricter. It's the
|
||||
property that a reflection object can modify the actual storage
|
||||
that was used to create the reflection object. Settability is
|
||||
determined by whether the reflection object holds the original
|
||||
item. When we say
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/interface2.go" `/START f6/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
we pass a <em>copy</em> of <code>x</code> to
|
||||
<code>reflect.ValueOf</code>, so the interface value created as the
|
||||
argument to <code>reflect.ValueOf</code> is a <em>copy</em> of
|
||||
<code>x</code>, not <code>x</code> itself. Thus, if the
|
||||
statement
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/interface2.go" `/START f6b/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
were allowed to succeed, it would not update <code>x</code>, even
|
||||
though <code>v</code> looks like it was created from
|
||||
<code>x</code>. Instead, it would update the copy of <code>x</code>
|
||||
stored inside the reflection value and <code>x</code> itself would
|
||||
be unaffected. That would be confusing and useless, so it is
|
||||
illegal, and settability is the property used to avoid this
|
||||
issue.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
If this seems bizarre, it's not. It's actually a familiar situation
|
||||
in unusual garb. Think of passing <code>x</code> to a
|
||||
function:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
f(x)
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
We would not expect <code>f</code> to be able to modify
|
||||
<code>x</code> because we passed a copy of <code>x</code>'s value,
|
||||
not <code>x</code> itself. If we want <code>f</code> to modify
|
||||
<code>x</code> directly we must pass our function the address of
|
||||
<code>x</code> (that is, a pointer to <code>x</code>):</p>
|
||||
|
||||
<p>
|
||||
<code>f(&x)</code>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
This is straightforward and familiar, and reflection works the same
|
||||
way. If we want to modify <code>x</code> by reflection, we must
|
||||
give the reflection library a pointer to the value we want to
|
||||
modify.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Let's do that. First we initialize <code>x</code> as usual
|
||||
and then create a reflection value that points to it, called
|
||||
<code>p</code>.
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/interface2.go" `/START f7/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
The output so far is
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
type of p: *float64
|
||||
settability of p: false
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
The reflection object <code>p</code> isn't settable, but it's not
|
||||
<code>p</code> we want to set, it's (in effect) <code>*p</code>. To
|
||||
get to what <code>p</code> points to, we call the <code>Elem</code>
|
||||
method of <code>Value</code>, which indirects through the pointer,
|
||||
and save the result in a reflection <code>Value</code> called
|
||||
<code>v</code>:
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/interface2.go" `/START f7b/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
Now <code>v</code> is a settable reflection object, as the output
|
||||
demonstrates,
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
settability of v: true
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
and since it represents <code>x</code>, we are finally able to use
|
||||
<code>v.SetFloat</code> to modify the value of
|
||||
<code>x</code>:
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/interface2.go" `/START f7c/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
The output, as expected, is
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
7.1
|
||||
7.1
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Reflection can be hard to understand but it's doing exactly what
|
||||
the language does, albeit through reflection <code>Types</code> and
|
||||
<code>Values</code> that can disguise what's going on. Just keep in
|
||||
mind that reflection Values need the address of something in order
|
||||
to modify what they represent.
|
||||
</p>
|
||||
|
||||
<p><b>Structs</b></p>
|
||||
|
||||
<p>
|
||||
In our previous example <code>v</code> wasn't a pointer itself, it
|
||||
was just derived from one. A common way for this situation to arise
|
||||
is when using reflection to modify the fields of a structure. As
|
||||
long as we have the address of the structure, we can modify its
|
||||
fields.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Here's a simple example that analyzes a struct value, <code>t</code>. We create
|
||||
the reflection object with the address of the struct because we'll want to
|
||||
modify it later. Then we set <code>typeOfT</code> to its type and iterate over
|
||||
the fields using straightforward method calls
|
||||
(see <a href="/pkg/reflect/">package reflect</a> for details).
|
||||
Note that we extract the names of the fields from the struct type, but the
|
||||
fields themselves are regular <code>reflect.Value</code> objects.
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/interface2.go" `/START f8/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
The output of this program is
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
0: A int = 23
|
||||
1: B string = skidoo
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
There's one more point about settability introduced in
|
||||
passing here: the field names of <code>T</code> are upper case
|
||||
(exported) because only exported fields of a struct are
|
||||
settable.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Because <code>s</code> contains a settable reflection object, we
|
||||
can modify the fields of the structure.
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/interface2.go" `/START f8b/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
And here's the result:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
t is now {77 Sunset Strip}
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
If we modified the program so that <code>s</code> was created from
|
||||
<code>t</code>, not <code>&t</code>, the calls to
|
||||
<code>SetInt</code> and <code>SetString</code> would fail as the
|
||||
fields of <code>t</code> would not be settable.
|
||||
</p>
|
||||
|
||||
<p><b>Conclusion</b></p>
|
||||
|
||||
<p>
|
||||
Here again are the laws of reflection:
|
||||
</p>
|
||||
|
||||
<ol>
|
||||
<li>Reflection goes from interface value to reflection
|
||||
object.</li>
|
||||
<li>Reflection goes from reflection object to interface
|
||||
value.</li>
|
||||
<li>To modify a reflection object, the value must be settable.</li>
|
||||
</ol>
|
||||
|
||||
<p>
|
||||
Once you understand these laws reflection in Go becomes much easier
|
||||
to use, although it remains subtle. It's a powerful tool that
|
||||
should be used with care and avoided unless strictly
|
||||
necessary.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
There's plenty more to reflection that we haven't covered —
|
||||
sending and receiving on channels, allocating memory, using slices
|
||||
and maps, calling methods and functions — but this post is
|
||||
long enough. We'll cover some of those topics in a later
|
||||
article.
|
||||
</p>
|
||||
|
Before Width: | Height: | Size: 6.2 KiB |
|
Before Width: | Height: | Size: 7.1 KiB |
|
Before Width: | Height: | Size: 7.1 KiB |
|
Before Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 3.6 KiB |
@@ -1,438 +0,0 @@
|
||||
<!--{
|
||||
"Title": "Slices: usage and internals",
|
||||
"Template": true
|
||||
}-->
|
||||
|
||||
<p>
|
||||
Go's slice type provides a convenient and efficient means of working with
|
||||
sequences of typed data. Slices are analogous to arrays in other languages, but
|
||||
have some unusual properties. This article will look at what slices are and how
|
||||
they are used.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b>Arrays</b>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The slice type is an abstraction built on top of Go's array type, and so to
|
||||
understand slices we must first understand arrays.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
An array type definition specifies a length and an element type. For example,
|
||||
the type <code>[4]int</code> represents an array of four integers. An array's
|
||||
size is fixed; its length is part of its type (<code>[4]int</code> and
|
||||
<code>[5]int</code> are distinct, incompatible types). Arrays can be indexed in
|
||||
the usual way, so the expression <code>s[n]</code> accesses the <i>n</i>th
|
||||
element:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
var a [4]int
|
||||
a[0] = 1
|
||||
i := a[0]
|
||||
// i == 1
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Arrays do not need to be initialized explicitly; the zero value of an array is
|
||||
a ready-to-use array whose elements are themselves zeroed:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
// a[2] == 0, the zero value of the int type
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
The in-memory representation of <code>[4]int</code> is just four integer values laid out sequentially:
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<img src="slice-array.png">
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Go's arrays are values. An array variable denotes the entire array; it is not a
|
||||
pointer to the first array element (as would be the case in C). This means
|
||||
that when you assign or pass around an array value you will make a copy of its
|
||||
contents. (To avoid the copy you could pass a <i>pointer</i> to the array, but
|
||||
then that's a pointer to an array, not an array.) One way to think about arrays
|
||||
is as a sort of struct but with indexed rather than named fields: a fixed-size
|
||||
composite value.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
An array literal can be specified like so:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
b := [2]string{"Penn", "Teller"}
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Or, you can have the compiler count the array elements for you:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
b := [...]string{"Penn", "Teller"}
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
In both cases, the type of <code>b</code> is <code>[2]string</code>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b>Slices</b>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Arrays have their place, but they're a bit inflexible, so you don't see them
|
||||
too often in Go code. Slices, though, are everywhere. They build on arrays to
|
||||
provide great power and convenience.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The type specification for a slice is <code>[]T</code>, where <code>T</code> is
|
||||
the type of the elements of the slice. Unlike an array type, a slice type has
|
||||
no specified length.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
A slice literal is declared just like an array literal, except you leave out
|
||||
the element count:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
letters := []string{"a", "b", "c", "d"}
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
A slice can be created with the built-in function called <code>make</code>,
|
||||
which has the signature,
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
func make([]T, len, cap) []T
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
where T stands for the element type of the slice to be created. The
|
||||
<code>make</code> function takes a type, a length, and an optional capacity.
|
||||
When called, <code>make</code> allocates an array and returns a slice that
|
||||
refers to that array.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
var s []byte
|
||||
s = make([]byte, 5, 5)
|
||||
// s == []byte{0, 0, 0, 0, 0}
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
When the capacity argument is omitted, it defaults to the specified length.
|
||||
Here's a more succinct version of the same code:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
s := make([]byte, 5)
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
The length and capacity of a slice can be inspected using the built-in
|
||||
<code>len</code> and <code>cap</code> functions.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
len(s) == 5
|
||||
cap(s) == 5
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
The next two sections discuss the relationship between length and capacity.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The zero value of a slice is <code>nil</code>. The <code>len</code> and
|
||||
<code>cap</code> functions will both return 0 for a nil slice.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
A slice can also be formed by "slicing" an existing slice or array. Slicing is
|
||||
done by specifying a half-open range with two indices separated by a colon. For
|
||||
example, the expression <code>b[1:4]</code> creates a slice including elements
|
||||
1 through 3 of <code>b</code> (the indices of the resulting slice will be 0
|
||||
through 2).
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
b := []byte{'g', 'o', 'l', 'a', 'n', 'g'}
|
||||
// b[1:4] == []byte{'o', 'l', 'a'}, sharing the same storage as b
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
The start and end indices of a slice expression are optional; they default to zero and the slice's length respectively:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
// b[:2] == []byte{'g', 'o'}
|
||||
// b[2:] == []byte{'l', 'a', 'n', 'g'}
|
||||
// b[:] == b
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
This is also the syntax to create a slice given an array:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
x := [3]string{"Лайка", "Белка", "Стрелка"}
|
||||
s := x[:] // a slice referencing the storage of x
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
<b>Slice internals</b>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
A slice is a descriptor of an array segment. It consists of a pointer to the
|
||||
array, the length of the segment, and its capacity (the maximum length of the
|
||||
segment).
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<img src="slice-struct.png">
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Our variable <code>s</code>, created earlier by <code>make([]byte, 5)</code>,
|
||||
is structured like this:
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<img src="slice-1.png">
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The length is the number of elements referred to by the slice. The capacity is
|
||||
the number of elements in the underlying array (beginning at the element
|
||||
referred to by the slice pointer). The distinction between length and capacity
|
||||
will be made clear as we walk through the next few examples.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
As we slice <code>s</code>, observe the changes in the slice data structure and
|
||||
their relation to the underlying array:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
s = s[2:4]
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
<img src="slice-2.png">
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Slicing does not copy the slice's data. It creates a new slice value that
|
||||
points to the original array. This makes slice operations as efficient as
|
||||
manipulating array indices. Therefore, modifying the <i>elements</i> (not the
|
||||
slice itself) of a re-slice modifies the elements of the original slice:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
d := []byte{'r', 'o', 'a', 'd'}
|
||||
e := d[2:]
|
||||
// e == []byte{'a', 'd'}
|
||||
e[1] == 'm'
|
||||
// e == []byte{'a', 'm'}
|
||||
// d == []byte{'r', 'o', 'a', 'm'}
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Earlier we sliced <code>s</code> to a length shorter than its capacity. We can
|
||||
grow s to its capacity by slicing it again:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
s = s[:cap(s)]
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
<img src="slice-3.png">
|
||||
</p>
|
||||
|
||||
<p>
|
||||
A slice cannot be grown beyond its capacity. Attempting to do so will cause a
|
||||
runtime panic, just as when indexing outside the bounds of a slice or array.
|
||||
Similarly, slices cannot be re-sliced below zero to access earlier elements in
|
||||
the array.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b>Growing slices (the copy and append functions)</b>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
To increase the capacity of a slice one must create a new, larger slice and
|
||||
copy the contents of the original slice into it. This technique is how dynamic
|
||||
array implementations from other languages work behind the scenes. The next
|
||||
example doubles the capacity of <code>s</code> by making a new slice,
|
||||
<code>t</code>, copying the contents of <code>s</code> into <code>t</code>, and
|
||||
then assigning the slice value <code>t</code> to <code>s</code>:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
t := make([]byte, len(s), (cap(s)+1)*2) // +1 in case cap(s) == 0
|
||||
for i := range s {
|
||||
t[i] = s[i]
|
||||
}
|
||||
s = t
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
The looping piece of this common operation is made easier by the built-in copy
|
||||
function. As the name suggests, copy copies data from a source slice to a
|
||||
destination slice. It returns the number of elements copied.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
func copy(dst, src []T) int
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
The <code>copy</code> function supports copying between slices of different
|
||||
lengths (it will copy only up to the smaller number of elements). In addition,
|
||||
<code>copy</code> can handle source and destination slices that share the same
|
||||
underlying array, handling overlapping slices correctly.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Using <code>copy</code>, we can simplify the code snippet above:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
t := make([]byte, len(s), (cap(s)+1)*2)
|
||||
copy(t, s)
|
||||
s = t
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
A common operation is to append data to the end of a slice. This function
|
||||
appends byte elements to a slice of bytes, growing the slice if necessary, and
|
||||
returns the updated slice value:
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/slices.go" `/AppendByte/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
One could use <code>AppendByte</code> like this:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
p := []byte{2, 3, 5}
|
||||
p = AppendByte(p, 7, 11, 13)
|
||||
// p == []byte{2, 3, 5, 7, 11, 13}
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Functions like <code>AppendByte</code> are useful because they offer complete
|
||||
control over the way the slice is grown. Depending on the characteristics of
|
||||
the program, it may be desirable to allocate in smaller or larger chunks, or to
|
||||
put a ceiling on the size of a reallocation.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
But most programs don't need complete control, so Go provides a built-in
|
||||
<code>append</code> function that's good for most purposes; it has the
|
||||
signature
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
func append(s []T, x ...T) []T
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
The <code>append</code> function appends the elements <code>x</code> to the end
|
||||
of the slice <code>s</code>, and grows the slice if a greater capacity is
|
||||
needed.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
a := make([]int, 1)
|
||||
// a == []int{0}
|
||||
a = append(a, 1, 2, 3)
|
||||
// a == []int{0, 1, 2, 3}
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
To append one slice to another, use <code>...</code> to expand the second
|
||||
argument to a list of arguments.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
a := []string{"John", "Paul"}
|
||||
b := []string{"George", "Ringo", "Pete"}
|
||||
a = append(a, b...) // equivalent to "append(a, b[0], b[1], b[2])"
|
||||
// a == []string{"John", "Paul", "George", "Ringo", "Pete"}
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Since the zero value of a slice (<code>nil</code>) acts like a zero-length
|
||||
slice, you can declare a slice variable and then append to it in a loop:
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/slices.go" `/Filter/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
<b>A possible "gotcha"</b>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
As mentioned earlier, re-slicing a slice doesn't make a copy of the underlying
|
||||
array. The full array will be kept in memory until it is no longer referenced.
|
||||
Occasionally this can cause the program to hold all the data in memory when
|
||||
only a small piece of it is needed.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
For example, this <code>FindDigits</code> function loads a file into memory and
|
||||
searches it for the first group of consecutive numeric digits, returning them
|
||||
as a new slice.
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/slices.go" `/digit/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
This code behaves as advertised, but the returned <code>[]byte</code> points
|
||||
into an array containing the entire file. Since the slice references the
|
||||
original array, as long as the slice is kept around the garbage collector can't
|
||||
release the array; the few useful bytes of the file keep the entire contents in
|
||||
memory.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
To fix this problem one can copy the interesting data to a new slice before
|
||||
returning it:
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/slices.go" `/CopyDigits/` `/STOP/`}}
|
||||
|
||||
<p>
|
||||
A more concise version of this function could be constructed by using
|
||||
<code>append</code>. This is left as an exercise for the reader.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b>Further Reading</b>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<a href="/doc/effective_go.html">Effective Go</a> contains an
|
||||
in-depth treatment of <a href="/doc/effective_go.html#slices">slices</a>
|
||||
and <a href="/doc/effective_go.html#arrays">arrays</a>,
|
||||
and the Go <a href="/doc/go_spec.html">language specification</a>
|
||||
defines <a href="/doc/go_spec.html#Slice_types">slices</a> and their
|
||||
<a href="/doc/go_spec.html#Length_and_capacity">associated</a>
|
||||
<a href="/doc/go_spec.html#Making_slices_maps_and_channels">helper</a>
|
||||
<a href="/doc/go_spec.html#Appending_and_copying_slices">functions</a>.
|
||||
</p>
|
||||
@@ -1,6 +0,0 @@
|
||||
<h1>Editing {{.Title |html}}</h1>
|
||||
|
||||
<form action="/save/{{.Title |html}}" method="POST">
|
||||
<div><textarea name="body" rows="20" cols="80">{{printf "%s" .Body |html}}</textarea></div>
|
||||
<div><input type="submit" value="Save"></div>
|
||||
</form>
|
||||
@@ -1,5 +0,0 @@
|
||||
<h1>{{.Title |html}}</h1>
|
||||
|
||||
<p>[<a href="/edit/{{.Title |html}}">edit</a>]</p>
|
||||
|
||||
<div>{{printf "%s" .Body |html}}</div>
|
||||
BIN
doc/button_background.png
Normal file
|
After Width: | Height: | Size: 126 B |
103
doc/cmd.html
@@ -1,103 +0,0 @@
|
||||
<!--{
|
||||
"Title": "Command Documentation",
|
||||
"Path": "/doc/cmd"
|
||||
}-->
|
||||
|
||||
<p>
|
||||
There is a suite of programs to build and process Go source code.
|
||||
Instead of being run directly, programs in the suite are usually invoked
|
||||
by the <a href="/cmd/go/">go</a> program.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The most common way to run these programs is as a subcommand of the go program,
|
||||
for instance as <code>go fmt</code>. Run like this, the command operates on
|
||||
complete packages of Go source code, with the go program invoking the
|
||||
underlying binary with arguments appropriate to package-level processing.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The programs can also be run as stand-alone binaries, with unmodified arguments,
|
||||
using the go <code>tool</code> subcommand, such as <code>go tool vet</code>.
|
||||
This style of invocation allows, for instance, checking a single source file
|
||||
rather than an entire package: <code>go tool vet myprogram.go</code> as
|
||||
compared to <code>go vet mypackage</code>.
|
||||
Some of the commands, such as <code>yacc</code>, are accessible only through
|
||||
the go <code>tool</code> subcommand.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Finally, two of the commands, <code>fmt</code> and <code>doc</code>, are also
|
||||
installed as regular binaries called <code>gofmt</code> and <code>godoc</code>
|
||||
because they are so often referenced.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Click on the links for more documentation, invocation methods, and usage details.
|
||||
</p>
|
||||
|
||||
<table class="dir">
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th> </th>
|
||||
<th>Synopsis</th>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><a href="/cmd/go/">go</a></td>
|
||||
<td> </td>
|
||||
<td>
|
||||
The <code>go</code> program manages Go source code and runs the other
|
||||
commands listed here.
|
||||
See the command docs for usage
|
||||
details.
|
||||
<br><br>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><a href="/cmd/cgo/">cgo</a></td>
|
||||
<td> </td>
|
||||
<td>Cgo enables the creation of Go packages that call C code.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><a href="/cmd/fix/">fix</a></td>
|
||||
<td> </td>
|
||||
<td>Fix finds Go programs that use old features of the language and libraries
|
||||
and rewrites them to use newer ones.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><a href="/cmd/go/">doc</a></td>
|
||||
<td> </td>
|
||||
<td>Doc extracts and generates documentation for Go packages, it is also available as
|
||||
an independent <a href="/cmd/godoc/">godoc</a> command with more general options.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><a href="/cmd/go/">fmt</a></td>
|
||||
<td> </td>
|
||||
<td>Fmt formats Go packages, it is also available as an independent <a href="/cmd/gofmt/">
|
||||
gofmt</a> command with more general options.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><a href="/cmd/vet/">vet</a></td>
|
||||
<td> </td>
|
||||
<td>Vet examines Go source code and reports suspicious constructs, such as Printf
|
||||
calls whose arguments do not align with the format string.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><a href="/cmd/yacc/">yacc</a></td>
|
||||
<td> </td>
|
||||
<td>Yacc is a version of yacc that generates parsers implemented in Go.</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
|
||||
<p>
|
||||
This is an abridged list. See the <a href="/cmd/">full command reference</a>
|
||||
for documentation of the compilers and more.
|
||||
</p>
|
||||
693
doc/code.html
@@ -1,158 +1,164 @@
|
||||
<!--{
|
||||
"Title": "How to Write Go Code"
|
||||
}-->
|
||||
<!-- How to Write Go Code -->
|
||||
|
||||
<h2 id="Introduction">Introduction</h2>
|
||||
|
||||
<p>
|
||||
This document demonstrates the development of a simple Go package and
|
||||
introduces the <a href="/cmd/go/">go command</a>, the standard way to fetch,
|
||||
build, and install Go packages and commands.
|
||||
</p>
|
||||
|
||||
|
||||
<h2 id="GOPATH">Code organization</h2>
|
||||
|
||||
<h3><code>GOPATH</code> and workspaces</h3>
|
||||
|
||||
<p>
|
||||
One of Go's design goals is to make writing software easier. To that end, the
|
||||
<code>go</code> command doesn't use Makefiles or other configuration files to
|
||||
guide program construction. Instead, it uses the source code to find
|
||||
dependencies and determine build conditions. This means your source code and
|
||||
build scripts are always in sync; they are one and the same.
|
||||
This document explains how to write a new package
|
||||
and how to test code.
|
||||
It assumes you have installed Go using the
|
||||
<a href="install.html">installation instructions</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The one thing you must do is set a <code>GOPATH</code> environment variable.
|
||||
<code>GOPATH</code> tells the <code>go</code> command (and other related tools)
|
||||
where to find and install the Go packages on your system.
|
||||
Before embarking on a change to an existing
|
||||
package or the creation of a new package,
|
||||
be sure to send mail to the
|
||||
<a href="http://groups.google.com/group/golang-nuts">mailing list</a>
|
||||
to let people know what you are thinking of doing.
|
||||
Doing so helps avoid duplication of effort and
|
||||
enables discussions about design before any code
|
||||
has been written.
|
||||
</p>
|
||||
|
||||
<h2 id="Community_resources">Community resources</h2>
|
||||
|
||||
<p>
|
||||
For real-time help, there may be users or developers on
|
||||
<code>#go-nuts</code> on the <a href="http://freenode.net/">Freenode</a> IRC server.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<code>GOPATH</code> is a list of paths. It shares the syntax of your system's
|
||||
<code>PATH</code> environment variable. A typical <code>GOPATH</code> on
|
||||
a Unix system might look like this:
|
||||
The official mailing list for discussion of the Go language is
|
||||
<a href="http://groups.google.com/group/golang-nuts">Go Nuts</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Bugs can be reported using the <a href="http://code.google.com/p/go/issues/list">Go issue tracker</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
For those who wish to keep up with development,
|
||||
there is another mailing list, <a href="http://groups.google.com/group/golang-checkins">golang-checkins</a>,
|
||||
that receives a message summarizing each checkin to the Go repository.
|
||||
</p>
|
||||
|
||||
|
||||
<h2 id="New_package">Creating a new package</h2>
|
||||
|
||||
<p>
|
||||
The source code for the package with import path
|
||||
<code>x/y</code> is, by convention, kept in the
|
||||
directory <code>$GOROOT/src/pkg/x/y</code>.
|
||||
</p>
|
||||
|
||||
<h3>Makefile</h3>
|
||||
|
||||
<p>
|
||||
It would be nice to have Go-specific tools that
|
||||
inspect the source files to determine what to build and in
|
||||
what order, but for now, Go uses GNU <code>make</code>.
|
||||
Thus, the first file to create in a new package directory is
|
||||
usually the <code>Makefile</code>.
|
||||
The basic form used in the Go source tree
|
||||
is illustrated by <a href="../src/pkg/container/vector/Makefile"><code>src/pkg/container/vector/Makefile</code></a>:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
GOPATH=/home/user/ext:/home/user/mygo
|
||||
include ../../../Make.inc
|
||||
|
||||
TARG=container/vector
|
||||
GOFILES=\
|
||||
intvector.go\
|
||||
stringvector.go\
|
||||
vector.go\
|
||||
|
||||
include ../../../Make.pkg
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
(On a Windows system use semicolons as the path separator instead of colons.)
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Each path in the list (in this case <code>/home/user/ext</code> or
|
||||
<code>/home/user/mygo</code>) specifies the location of a <i>workspace</i>.
|
||||
A workspace contains Go source files and their associated package objects, and
|
||||
command executables. It has a prescribed structure of three subdirectories:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li><code>src</code> contains Go source files,
|
||||
<li><code>pkg</code> contains compiled package objects, and
|
||||
<li><code>bin</code> contains executable commands.
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
Subdirectories of the <code>src</code> directory hold independent packages, and
|
||||
all source files (<code>.go</code>, <code>.c</code>, <code>.h</code>, and
|
||||
<code>.s</code>) in each subdirectory are elements of that subdirectory's
|
||||
package.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
When building a program that imports the package "<code>widget</code>" the
|
||||
<code>go</code> command looks for <code>src/pkg/widget</code> inside the Go root,
|
||||
and then—if the package source isn't found there—it searches
|
||||
for <code>src/widget</code> inside each workspace in order.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Multiple workspaces can offer some flexibility and convenience, but for now
|
||||
we'll concern ourselves with only a single workspace.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Let's work through a simple example. First, create a <code>$HOME/mygo</code>
|
||||
directory and its <code>src</code> subdirectory:
|
||||
Outside the Go source tree (for personal packages), the standard form is
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
$ mkdir -p $HOME/mygo/src # create a place to put source code
|
||||
include $(GOROOT)/src/Make.inc
|
||||
|
||||
TARG=mypackage
|
||||
GOFILES=\
|
||||
my1.go\
|
||||
my2.go\
|
||||
|
||||
include $(GOROOT)/src/Make.pkg
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Next, set it as the <code>GOPATH</code>. You should also add the
|
||||
<code>bin</code> subdirectory to your <code>PATH</code> environment variable so
|
||||
that you can run the commands therein without specifying their full path.
|
||||
To do this, add the following lines to <code>$HOME/.profile</code> (or
|
||||
equivalent):
|
||||
The first and last lines <code>include</code> standard definitions and rules.
|
||||
Packages maintained in the standard Go tree use a relative path (instead of
|
||||
<code>$(GOROOT)/src</code>) so that <code>make</code> will work correctly
|
||||
even if <code>$(GOROOT)</code> contains spaces.
|
||||
This makes it easy for programmers to try Go.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
If you have not set <code>$GOROOT</code> in your environment,
|
||||
you must run <code>gomake</code> to use this form of makefile.
|
||||
<code>Gomake</code> also takes care to invoke GNU Make
|
||||
even on systems where it is installed as <code>gmake</code>
|
||||
rather than <code>make</code>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<code>TARG</code> is the target install path for the package,
|
||||
the string that clients will use to import it.
|
||||
Inside the Go tree, this string should be the same as the directory
|
||||
in which the <code>Makefile</code> appears, with the
|
||||
<code>$GOROOT/src/pkg/</code> prefix removed.
|
||||
Outside the Go tree, you can use any <code>TARG</code> you
|
||||
want that doesn't conflict with the standard Go package names.
|
||||
A common convention is to use an identifying top-level name
|
||||
to group your packages: <code>myname/tree</code>, <code>myname/filter</code>, etc.
|
||||
Note that even if you keep your package source outside the
|
||||
Go tree, running <code>make install</code> installs your
|
||||
package binaries in the standard location—<code>$GOROOT/pkg</code>—to
|
||||
make it easy to find them.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<code>GOFILES</code> is a list of source files to compile to
|
||||
create the package. The trailing <code>\</code> characters
|
||||
allow the list to be split onto multiple lines
|
||||
for easy sorting.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
If you create a new package directory in the Go tree, add it to the list in
|
||||
<code>$GOROOT/src/pkg/Makefile</code> so that it
|
||||
is included in the standard build. Then run:
|
||||
<pre>
|
||||
export GOPATH=$HOME/mygo
|
||||
export PATH=$PATH:$HOME/mygo/bin
|
||||
cd $GOROOT/src/pkg
|
||||
./deps.bash
|
||||
</pre>
|
||||
|
||||
|
||||
<h3>Import paths</h3>
|
||||
|
||||
<p>
|
||||
The standard packages are given short import paths such as <code>"fmt"</code>
|
||||
and <code>"net/http"</code> for convenience.
|
||||
For your own projects, it is important to choose a base import path that is
|
||||
unlikely to collide with future additions to the standard library or other
|
||||
external libraries.
|
||||
to update the dependency file <code>Make.deps</code>.
|
||||
(This happens automatically each time you run <code>all.bash</code>
|
||||
or <code>make.bash</code>.)
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The best way to choose an import path is to use the location of your version
|
||||
control repository.
|
||||
For instance, if your source repository is at <code>example.com</code>
|
||||
or <code>code.google.com/p/example</code>, you should begin your package
|
||||
paths with that URL, as in "<code>example.com/foo/bar</code>" or
|
||||
"<code>code.google.com/p/example/foo/bar</code>".
|
||||
Using this convention, the <code>go</code> command can automatically check out and
|
||||
build the source code by its import path alone.
|
||||
If you change the imports of an existing package,
|
||||
you do not need to edit <code>$GOROOT/src/pkg/Makefile</code>
|
||||
but you will still need to run <code>deps.bash</code> as above.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
If you don't intend to install your code in this way, you should at
|
||||
least use a unique prefix like "<code>widgets/</code>", as in
|
||||
"<code>widgets/foo/bar</code>". A good rule is to use a prefix such as your
|
||||
company or project name, since it is unlikely to be used by another group.
|
||||
</p>
|
||||
|
||||
<h3>Go source files</h3>
|
||||
|
||||
<p>
|
||||
We'll use <code>example/</code> as our base import path:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
$ mkdir -p $GOPATH/src/example
|
||||
</pre>
|
||||
|
||||
|
||||
<h3>Package names</h3>
|
||||
|
||||
<p>
|
||||
The first statement in a Go source file should be
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
package <i>name</i>
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
where <code><i>name</i></code> is the package's default name for imports.
|
||||
The first statement in each of the source files listed in the <code>Makefile</code>
|
||||
should be <code>package <i>name</i></code>, where <code><i>name</i></code>
|
||||
is the package's default name for imports.
|
||||
(All files in a package must use the same <code><i>name</i></code>.)
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Go's convention is that the package name is the last element of the
|
||||
import path: the package imported as "<code>crypto/rot13</code>"
|
||||
import path: the package imported as <code>"crypto/rot13"</code>
|
||||
should be named <code>rot13</code>.
|
||||
There is no requirement that package names be unique
|
||||
across all packages linked into a single binary,
|
||||
@@ -160,344 +166,203 @@ only that the import paths (their full file names) be unique.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Create a new package under <code>example</code> called <code>newmath</code>:
|
||||
Go compiles all the source files in a package at once, so one file
|
||||
can refer to constants, variables, types, and functions in another
|
||||
file without special arrangement or declarations.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Writing clean, idiomatic Go code is beyond the scope of this document.
|
||||
<a href="effective_go.html">Effective Go</a> is an introduction to
|
||||
that topic.
|
||||
</p>
|
||||
|
||||
<h2 id="Building_programs">Building programs</h2>
|
||||
<p>To build a Go program with gomake, create a Makefile alongside your program's
|
||||
source files. It should be similar to the example above, but include
|
||||
<code>Make.cmd</code> instead of <code>Make.pkg</code>:
|
||||
|
||||
<pre>
|
||||
$ cd $GOPATH/src/example
|
||||
$ mkdir newmath
|
||||
include $(GOROOT)/src/Make.inc
|
||||
|
||||
TARG=helloworld
|
||||
GOFILES=\
|
||||
helloworld.go\
|
||||
|
||||
include $(GOROOT)/src/Make.cmd
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Then create a file named <code>$GOPATH/src/example/newmath/sqrt.go</code>
|
||||
containing the following Go code:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
// Package newmath is a trivial example package.
|
||||
package newmath
|
||||
|
||||
// Sqrt returns an approximation to the square root of x.
|
||||
func Sqrt(x float64) float64 {
|
||||
// This is a terrible implementation.
|
||||
// Real code should import "math" and use math.Sqrt.
|
||||
z := 0.0
|
||||
for i := 0; i < 1000; i++ {
|
||||
z -= (z*z - x) / (2 * x)
|
||||
}
|
||||
return z
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
This package is imported by the path name of the directory it's in, starting
|
||||
after the <code>src</code> component:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
import "example/newmath"
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
See <a href="/doc/effective_go.html#names">Effective Go</a> to learn more about
|
||||
Go's naming conventions.
|
||||
</p>
|
||||
|
||||
|
||||
<h2>Building and installing</h2>
|
||||
|
||||
<p>
|
||||
The <code>go</code> command comprises several subcommands, the most central being
|
||||
<code>install</code>. Running <code>go install <i>importpath</i></code> builds
|
||||
and installs a package and its dependencies.
|
||||
<p>Running <code>gomake</code> will compile <code>helloworld.go</code>
|
||||
and produce an executable named <code>helloworld</code> in the current
|
||||
directory.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
To "install a package" means to write the package object or executable command
|
||||
to the <code>pkg</code> or <code>bin</code> subdirectory of the workspace in
|
||||
which the source resides.
|
||||
Running <code>gomake install</code> will build <code>helloworld</code> if
|
||||
necessary and copy it to the <code>$GOBIN</code> directory
|
||||
(<code>$GOROOT/bin/</code> is the default).
|
||||
</p>
|
||||
|
||||
<h3>Building a package</h3>
|
||||
|
||||
<p>
|
||||
To build and install the <code>newmath</code> package, type
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
$ go install example/newmath
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
This command will produce no output if the package and its dependencies
|
||||
are built and installed correctly.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
As a convenience, the <code>go</code> command will assume the current directory
|
||||
if no import path is specified on the command line. This sequence of commands
|
||||
has the same affect as the one above:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
$ cd $GOPATH/src/example/newmath
|
||||
$ go install
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
The resulting workspace directory tree (assuming we're running Linux on a 64-bit
|
||||
system) looks like this:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
pkg/
|
||||
linux_amd64/
|
||||
example/
|
||||
newmath.a # package object
|
||||
src/
|
||||
example/
|
||||
newmath/
|
||||
sqrt.go # package source
|
||||
</pre>
|
||||
|
||||
|
||||
<h3>Building a command</h3>
|
||||
|
||||
<p>
|
||||
The <code>go</code> command treats code belonging to <code>package main</code> as
|
||||
an executable command and installs the package binary to the
|
||||
<code>GOPATH</code>'s <code>bin</code> subdirectory.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Add a command named <code>hello</code> to the source tree.
|
||||
First create the <code>example/hello</code> directory:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
$ cd $GOPATH/src/example
|
||||
$ mkdir hello
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Then create the file <code>$GOPATH/src/example/hello/hello.go</code>
|
||||
containing the following Go code.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
// Hello is a trivial example of a main package.
|
||||
package main
|
||||
|
||||
import (
|
||||
"example/newmath"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Printf("Hello, world. Sqrt(2) = %v\n", newmath.Sqrt(2))
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Next, run <code>go install</code>, which builds and installs the binary to
|
||||
<code>$GOPATH/bin</code>:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
$ go install example/hello
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
To run the program, invoke it by name as you would any other command:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
$ $GOPATH/bin/hello
|
||||
Hello, world. Sqrt(2) = 1.414213562373095
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
If you added <code>$HOME/mygo/bin</code> to your <code>PATH</code>, you may omit
|
||||
the path to the executable:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
$ hello
|
||||
Hello, world. Sqrt(2) = 1.414213562373095
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
The workspace directory tree now looks like this:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
bin/
|
||||
hello # command executable
|
||||
pkg/
|
||||
linux_amd64/
|
||||
example/
|
||||
newmath.a # package object
|
||||
src/
|
||||
example/
|
||||
hello/
|
||||
hello.go # command source
|
||||
newmath/
|
||||
sqrt.go # package source
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
The <code>go</code> command also provides a <code>build</code> command, which is
|
||||
like <code>install</code> except it builds all objects in a temporary directory
|
||||
and does not install them under <code>pkg</code> or <code>bin</code>.
|
||||
When building a command an executable named after the last element of the
|
||||
import path is written to the current directory. When building a package,
|
||||
<code>go build</code> serves merely to test that the package and its
|
||||
dependencies can be built. (The resulting package object is thrown away.)
|
||||
</p>
|
||||
|
||||
|
||||
<h2 id="Testing">Testing</h2>
|
||||
|
||||
<p>
|
||||
Go has a lightweight test framework composed of the <code>go test</code>
|
||||
command and the <code>testing</code> package.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Go has a lightweight test framework known as <code>gotest</code>.
|
||||
You write a test by creating a file with a name ending in <code>_test.go</code>
|
||||
that contains functions named <code>TestXXX</code> with signature
|
||||
<code>func (t *testing.T)</code>.
|
||||
that contains functions named <code>TestXXX</code> with signature <code>func (t *testing.T)</code>.
|
||||
The test framework runs each such function;
|
||||
if the function calls a failure function such as <code>t.Error</code> or
|
||||
<code>t.Fail</code>, the test is considered to have failed.
|
||||
if the function calls a failure function such as <code>t.Error</code> or <code>t.Fail</code>, the test is considered to have failed.
|
||||
The <a href="/cmd/gotest/">gotest command documentation</a>
|
||||
and the <a href="/pkg/testing/">testing package documentation</a> give more detail.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Add a test to the <code>newmath</code> package by creating the file
|
||||
<code>$GOPATH/src/example/newmath/sqrt_test.go</code> containing the following
|
||||
Go code.
|
||||
The <code>*_test.go</code> files should not be listed in the <code>Makefile</code>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
To run the test, run either <code>make test</code> or <code>gotest</code>
|
||||
(they are equivalent).
|
||||
To run only the tests in a single test file, for instance <code>one_test.go</code>,
|
||||
run <code>gotest one_test.go</code>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
If your change affects performance, add a <code>Benchmark</code> function
|
||||
(see the <a href="/cmd/gotest/">gotest command documentation</a>)
|
||||
and run it using <code>gotest -test.bench=.</code>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Once your new code is tested and working,
|
||||
it's time to get it <a href="contribute.html">reviewed and submitted</a>.
|
||||
</p>
|
||||
|
||||
<h2 id="pkg_example">An example package with tests</h2>
|
||||
|
||||
<p>
|
||||
This example package, <code>numbers</code>, consists of the function
|
||||
<code>Double</code>, which takes an <code>int</code> and returns that value
|
||||
multiplied by 2. It consists of three files.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
First, the package implementation, <code>numbers.go</code>:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
package newmath
|
||||
package numbers
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestSqrt(t *testing.T) {
|
||||
const in, out = 9, 3
|
||||
if x := Sqrt(in); x != out {
|
||||
t.Errorf("Sqrt(%v) = %v, want %v", in, x, out)
|
||||
}
|
||||
func Double(i int) int {
|
||||
return i * 2
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Now run the test with <code>go test</code>:
|
||||
Next, the tests, <code>numbers_test.go</code>:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
$ go test example/newmath
|
||||
ok example/newmath
|
||||
package numbers
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
type doubleTest struct {
|
||||
in, out int
|
||||
}
|
||||
|
||||
var doubleTests = []doubleTest{
|
||||
doubleTest{1, 2},
|
||||
doubleTest{2, 4},
|
||||
doubleTest{-5, -10},
|
||||
}
|
||||
|
||||
func TestDouble(t *testing.T) {
|
||||
for _, dt := range doubleTests {
|
||||
v := Double(dt.in)
|
||||
if v != dt.out {
|
||||
t.Errorf("Double(%d) = %d, want %d.", dt.in, v, dt.out)
|
||||
}
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Run <code><a href="/cmd/go/#Test_packages">go help test</a></code> and see the
|
||||
<a href="/pkg/testing/">testing package documentation</a> for more detail.
|
||||
</p>
|
||||
|
||||
|
||||
<h2 id="remote">Remote packages</h2>
|
||||
|
||||
<p>
|
||||
An import path can describe how to obtain the package source code using a
|
||||
revision control system such as Git or Mercurial. The <code>go</code> command uses
|
||||
this property to automatically fetch packages from remote repositories.
|
||||
For instance, the examples described in this document are also kept in a
|
||||
Mercurial repository hosted at Google Code,
|
||||
<code><a href="http://code.google.com/p/go.example">code.google.com/p/go.example</a></code>.
|
||||
If you include the repository URL in the package's import path,
|
||||
<code>go get</code> will fetch, build, and install it automatically:
|
||||
Finally, the <code>Makefile</code>:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
$ go get code.google.com/p/go.example/hello
|
||||
$ $GOPATH/bin/hello
|
||||
Hello, world. Sqrt(2) = 1.414213562373095
|
||||
include $(GOROOT)/src/Make.inc
|
||||
|
||||
TARG=numbers
|
||||
GOFILES=\
|
||||
numbers.go\
|
||||
|
||||
include $(GOROOT)/src/Make.pkg
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
If the specified package is not present in a workspace, <code>go get</code>
|
||||
will place it inside the first workspace specified by <code>GOPATH</code>.
|
||||
(If the package does already exist, <code>go get</code> skips the remote
|
||||
fetch and behaves the same as <code>go install</code>.)
|
||||
Running <code>gomake install</code> will build and install the package to
|
||||
the <code>$GOROOT/pkg/</code> directory (it can then be used by any
|
||||
program on the system).
|
||||
</p>
|
||||
|
||||
<p>
|
||||
After issuing the above <code>go get</code> command, the workspace directory
|
||||
tree should now now look like this:
|
||||
Running <code>gomake test</code> (or just running the command
|
||||
<code>gotest</code>) will rebuild the package, including the
|
||||
<code>numbers_test.go</code> file, and then run the <code>TestDouble</code>
|
||||
function. The output "<code>PASS</code>" indicates that all tests passed
|
||||
successfully. Breaking the implementation by changing the multiplier from
|
||||
<code>2</code> to <code>3</code> will allow you to see how failing tests are
|
||||
reported.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
See the <a href="/cmd/gotest/">gotest documentation</a> and the
|
||||
<a href="/pkg/testing/">testing package</a> for more detail.
|
||||
</p>
|
||||
|
||||
<h2 id="arch_os_specific">Architecture- and operating system-specific code</h2>
|
||||
|
||||
<p>First, a disclaimer: very few Go packages should need to know about the
|
||||
hardware and operating system they run on. In the vast majority of cases the
|
||||
language and standard library handle most portability issues. This section is
|
||||
a guide for experienced systems programmers who have a good reason to write
|
||||
platform-specific code, such as assembly-language support for fast
|
||||
trigonometric functions or code that implements a common interface above
|
||||
different operating systems.</p>
|
||||
|
||||
<p>To compile such code, use the <code>$GOOS</code> and <code>$GOARCH</code>
|
||||
<a href="/doc/install.html#environment">environment variables</a> in your
|
||||
source file names and <code>Makefile</code>.</p>
|
||||
|
||||
<p>For example, this <code>Makefile</code> describes a package that builds on
|
||||
different operating systems by parameterizing the file name with
|
||||
<code>$GOOS</code>.</p>
|
||||
|
||||
<pre>
|
||||
include $(GOROOT)/src/Make.inc
|
||||
|
||||
TARG=mypackage
|
||||
GOFILES=\
|
||||
my.go\
|
||||
my_$(GOOS).go\
|
||||
|
||||
include $(GOROOT)/src/Make.pkg
|
||||
</pre>
|
||||
|
||||
<p>The OS-specific code goes in <code>my_linux.go</code>,
|
||||
<code>my_darwin.go</code>, and so on.</p>
|
||||
|
||||
<p>If you follow these conventional parameterizations, tools such as
|
||||
<a href="/cmd/goinstall/">goinstall</a> will work seamlessly with your package:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
bin/
|
||||
hello # command executable
|
||||
pkg/
|
||||
linux_amd64/
|
||||
code.google.com/p/go.example/
|
||||
newmath.a # package object
|
||||
example/
|
||||
newmath.a # package object
|
||||
src/
|
||||
code.google.com/p/go.example/
|
||||
hello/
|
||||
hello.go # command source
|
||||
newmath/
|
||||
sqrt.go # package source
|
||||
sqrt_test.go # test source
|
||||
example/
|
||||
hello/
|
||||
hello.go # command source
|
||||
newmath/
|
||||
sqrt.go # package source
|
||||
sqrt_test.go # test source
|
||||
my_$(GOOS).go
|
||||
my_$(GOARCH).go
|
||||
my_$(GOOS)_$(GOARCH).go
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
The <code>hello</code> command hosted at Google Code depends on the
|
||||
<code>newmath</code> package within the same repository. The imports in
|
||||
<code>hello.go</code> file use the same import path convention, so the <code>go
|
||||
get</code> command is able to locate and install the dependent package, too.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
import "code.google.com/p/go.example/newmath"
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
This convention is the easiest way to make your Go packages available for
|
||||
others to use.
|
||||
The <a href="http://godashboard.appspot.com/package">Go Package Dashboard</a>
|
||||
displays a list of packages recently installed with the <code>go</code> command.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
For more information on using remote repositories with the <code>go</code> command, see
|
||||
<code><a href="/cmd/go/#Remote_import_path_syntax">go help remote</a></code>.
|
||||
</p>
|
||||
|
||||
|
||||
<h2 id="more">Further reading</h2>
|
||||
|
||||
<p>
|
||||
See <a href="/doc/effective_go.html">Effective Go</a> for tips on writing
|
||||
clear, idiomatic Go code.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Take <a href="http://tour.golang.org/">A Tour of Go</a> to learn the language
|
||||
proper.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Visit the <a href="/doc/#articles">documentation page</a> for a set of in-depth
|
||||
articles about the Go language and its libraries and tools.
|
||||
</p>
|
||||
<p>The same holds for <code>.s</code> (assembly) files.</p>
|
||||
|
||||
@@ -2,19 +2,24 @@
|
||||
# Use of this source code is governed by a BSD-style
|
||||
# license that can be found in the LICENSE file.
|
||||
|
||||
include ../../../src/Make.inc
|
||||
|
||||
all: index.html
|
||||
|
||||
CLEANFILES:=srcextract.bin htmlify.bin get.bin
|
||||
include ../../../src/Make.common
|
||||
|
||||
index.html: wiki.html srcextract.bin htmlify.bin
|
||||
CLEANFILES+=index.html srcextract.bin htmlify.bin get.bin
|
||||
|
||||
index.html: srcextract.bin htmlify.bin
|
||||
PATH=.:$$PATH awk '/^!/{system(substr($$0,2)); next} {print}' < wiki.html | tr -d '\r' > index.html
|
||||
|
||||
test: get.bin
|
||||
bash ./test.sh
|
||||
rm -f get.6 get.bin
|
||||
|
||||
%.bin: %.go
|
||||
go build -o $@ $^
|
||||
%.bin: %.$O
|
||||
$(LD) -o $@ $<
|
||||
|
||||
%.$O: %.go
|
||||
$(GC) $*.go
|
||||
|
||||
clean:
|
||||
rm -f $(CLEANFILES)
|
||||
6
doc/codelab/wiki/edit.html
Normal file
@@ -0,0 +1,6 @@
|
||||
<h1>Editing {Title}</h1>
|
||||
|
||||
<form action="/save/{Title}" method="POST">
|
||||
<div><textarea name="body" rows="20" cols="80">{Body|html}</textarea></div>
|
||||
<div><input type="submit" value="Save"></div>
|
||||
</form>
|
||||
@@ -1,15 +1,11 @@
|
||||
// Copyright 2010 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"html/template"
|
||||
"http"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"regexp"
|
||||
"template"
|
||||
)
|
||||
|
||||
type Page struct {
|
||||
@@ -17,12 +13,12 @@ type Page struct {
|
||||
Body []byte
|
||||
}
|
||||
|
||||
func (p *Page) save() error {
|
||||
func (p *Page) save() os.Error {
|
||||
filename := p.Title + ".txt"
|
||||
return ioutil.WriteFile(filename, p.Body, 0600)
|
||||
}
|
||||
|
||||
func loadPage(title string) (*Page, error) {
|
||||
func loadPage(title string) (*Page, os.Error) {
|
||||
filename := title + ".txt"
|
||||
body, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
@@ -65,21 +61,21 @@ func saveHandler(w http.ResponseWriter, r *http.Request) {
|
||||
p := &Page{Title: title, Body: []byte(body)}
|
||||
err = p.save()
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
http.Error(w, err.String(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
http.Redirect(w, r, "/view/"+title, http.StatusFound)
|
||||
}
|
||||
|
||||
func renderTemplate(w http.ResponseWriter, tmpl string, p *Page) {
|
||||
t, err := template.ParseFiles(tmpl + ".html")
|
||||
t, err := template.ParseFile(tmpl+".html", nil)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
http.Error(w, err.String(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
err = t.Execute(w, p)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
http.Error(w, err.String(), http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,11 +83,11 @@ const lenPath = len("/view/")
|
||||
|
||||
var titleValidator = regexp.MustCompile("^[a-zA-Z0-9]+$")
|
||||
|
||||
func getTitle(w http.ResponseWriter, r *http.Request) (title string, err error) {
|
||||
func getTitle(w http.ResponseWriter, r *http.Request) (title string, err os.Error) {
|
||||
title = r.URL.Path[lenPath:]
|
||||
if !titleValidator.MatchString(title) {
|
||||
http.NotFound(w, r)
|
||||
err = errors.New("Invalid Page Title")
|
||||
err = os.NewError("Invalid Page Title")
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -1,13 +1,10 @@
|
||||
// Copyright 2010 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"html/template"
|
||||
"http"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"template"
|
||||
)
|
||||
|
||||
type Page struct {
|
||||
@@ -15,12 +12,12 @@ type Page struct {
|
||||
Body []byte
|
||||
}
|
||||
|
||||
func (p *Page) save() error {
|
||||
func (p *Page) save() os.Error {
|
||||
filename := p.Title + ".txt"
|
||||
return ioutil.WriteFile(filename, p.Body, 0600)
|
||||
}
|
||||
|
||||
func loadPage(title string) (*Page, error) {
|
||||
func loadPage(title string) (*Page, os.Error) {
|
||||
filename := title + ".txt"
|
||||
body, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
@@ -37,14 +34,14 @@ func editHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if err != nil {
|
||||
p = &Page{Title: title}
|
||||
}
|
||||
t, _ := template.ParseFiles("edit.html")
|
||||
t, _ := template.ParseFile("edit.html", nil)
|
||||
t.Execute(w, p)
|
||||
}
|
||||
|
||||
func viewHandler(w http.ResponseWriter, r *http.Request) {
|
||||
title := r.URL.Path[lenPath:]
|
||||
p, _ := loadPage(title)
|
||||
t, _ := template.ParseFiles("view.html")
|
||||
t, _ := template.ParseFile("view.html", nil)
|
||||
t.Execute(w, p)
|
||||
}
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
// Copyright 2010 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"html/template"
|
||||
"http"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"regexp"
|
||||
"template"
|
||||
)
|
||||
|
||||
type Page struct {
|
||||
@@ -16,12 +13,12 @@ type Page struct {
|
||||
Body []byte
|
||||
}
|
||||
|
||||
func (p *Page) save() error {
|
||||
func (p *Page) save() os.Error {
|
||||
filename := p.Title + ".txt"
|
||||
return ioutil.WriteFile(filename, p.Body, 0600)
|
||||
}
|
||||
|
||||
func loadPage(title string) (*Page, error) {
|
||||
func loadPage(title string) (*Page, os.Error) {
|
||||
filename := title + ".txt"
|
||||
body, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
@@ -52,21 +49,21 @@ func saveHandler(w http.ResponseWriter, r *http.Request, title string) {
|
||||
p := &Page{Title: title, Body: []byte(body)}
|
||||
err := p.save()
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
http.Error(w, err.String(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
http.Redirect(w, r, "/view/"+title, http.StatusFound)
|
||||
}
|
||||
|
||||
func renderTemplate(w http.ResponseWriter, tmpl string, p *Page) {
|
||||
t, err := template.ParseFiles(tmpl + ".html")
|
||||
t, err := template.ParseFile(tmpl+".html", nil)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
http.Error(w, err.String(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
err = t.Execute(w, p)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
http.Error(w, err.String(), http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
// Copyright 2010 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"html/template"
|
||||
"http"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"template"
|
||||
)
|
||||
|
||||
type Page struct {
|
||||
@@ -15,12 +12,12 @@ type Page struct {
|
||||
Body []byte
|
||||
}
|
||||
|
||||
func (p *Page) save() error {
|
||||
func (p *Page) save() os.Error {
|
||||
filename := p.Title + ".txt"
|
||||
return ioutil.WriteFile(filename, p.Body, 0600)
|
||||
}
|
||||
|
||||
func loadPage(title string) (*Page, error) {
|
||||
func loadPage(title string) (*Page, os.Error) {
|
||||
filename := title + ".txt"
|
||||
body, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
@@ -55,7 +52,7 @@ func saveHandler(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
func renderTemplate(w http.ResponseWriter, tmpl string, p *Page) {
|
||||
t, _ := template.ParseFiles(tmpl + ".html")
|
||||
t, _ := template.ParseFile(tmpl+".html", nil)
|
||||
t.Execute(w, p)
|
||||
}
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
// Copyright 2010 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"html/template"
|
||||
"http"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"regexp"
|
||||
"template"
|
||||
)
|
||||
|
||||
type Page struct {
|
||||
@@ -16,12 +13,12 @@ type Page struct {
|
||||
Body []byte
|
||||
}
|
||||
|
||||
func (p *Page) save() error {
|
||||
func (p *Page) save() os.Error {
|
||||
filename := p.Title + ".txt"
|
||||
return ioutil.WriteFile(filename, p.Body, 0600)
|
||||
}
|
||||
|
||||
func loadPage(title string) (*Page, error) {
|
||||
func loadPage(title string) (*Page, os.Error) {
|
||||
filename := title + ".txt"
|
||||
body, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
@@ -52,18 +49,24 @@ func saveHandler(w http.ResponseWriter, r *http.Request, title string) {
|
||||
p := &Page{Title: title, Body: []byte(body)}
|
||||
err := p.save()
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
http.Error(w, err.String(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
http.Redirect(w, r, "/view/"+title, http.StatusFound)
|
||||
}
|
||||
|
||||
var templates = template.Must(template.ParseFiles("edit.html", "view.html"))
|
||||
var templates = make(map[string]*template.Template)
|
||||
|
||||
func init() {
|
||||
for _, tmpl := range []string{"edit", "view"} {
|
||||
templates[tmpl] = template.MustParseFile(tmpl+".html", nil)
|
||||
}
|
||||
}
|
||||
|
||||
func renderTemplate(w http.ResponseWriter, tmpl string, p *Page) {
|
||||
err := templates.ExecuteTemplate(w, tmpl+".html", p)
|
||||
err := templates[tmpl].Execute(w, p)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
http.Error(w, err.String(), http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,12 @@
|
||||
// Copyright 2011 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"http"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
@@ -36,7 +32,7 @@ func main() {
|
||||
log.Fatal("no url supplied")
|
||||
}
|
||||
var r *http.Response
|
||||
var err error
|
||||
var err os.Error
|
||||
if *post != "" {
|
||||
b := strings.NewReader(*post)
|
||||
r, err = http.Post(url, "application/x-www-form-urlencoded", b)
|
||||
12
doc/codelab/wiki/htmlify.go
Normal file
@@ -0,0 +1,12 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"template"
|
||||
"io/ioutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
b, _ := ioutil.ReadAll(os.Stdin)
|
||||
template.HTMLFormatter(os.Stdout, "", b)
|
||||
}
|
||||
@@ -2,7 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"http"
|
||||
)
|
||||
|
||||
func handler(w http.ResponseWriter, r *http.Request) {
|
||||
1003
doc/codelab/wiki/index.html
Normal file
@@ -1,13 +1,10 @@
|
||||
// Copyright 2010 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"http"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
)
|
||||
|
||||
type Page struct {
|
||||
@@ -15,12 +12,12 @@ type Page struct {
|
||||
Body []byte
|
||||
}
|
||||
|
||||
func (p *Page) save() error {
|
||||
func (p *Page) save() os.Error {
|
||||
filename := p.Title + ".txt"
|
||||
return ioutil.WriteFile(filename, p.Body, 0600)
|
||||
}
|
||||
|
||||
func loadPage(title string) (*Page, error) {
|
||||
func loadPage(title string) (*Page, os.Error) {
|
||||
filename := title + ".txt"
|
||||
body, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
@@ -1,12 +1,9 @@
|
||||
// Copyright 2010 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
)
|
||||
|
||||
type Page struct {
|
||||
@@ -14,7 +11,7 @@ type Page struct {
|
||||
Body []byte
|
||||
}
|
||||
|
||||
func (p *Page) save() error {
|
||||
func (p *Page) save() os.Error {
|
||||
filename := p.Title + ".txt"
|
||||
return ioutil.WriteFile(filename, p.Body, 0600)
|
||||
}
|
||||
@@ -1,12 +1,9 @@
|
||||
// Copyright 2010 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
)
|
||||
|
||||
type Page struct {
|
||||
@@ -14,12 +11,12 @@ type Page struct {
|
||||
Body []byte
|
||||
}
|
||||
|
||||
func (p *Page) save() error {
|
||||
func (p *Page) save() os.Error {
|
||||
filename := p.Title + ".txt"
|
||||
return ioutil.WriteFile(filename, p.Body, 0600)
|
||||
}
|
||||
|
||||
func loadPage(title string) (*Page, error) {
|
||||
func loadPage(title string) (*Page, os.Error) {
|
||||
filename := title + ".txt"
|
||||
body, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
@@ -1,13 +1,10 @@
|
||||
// Copyright 2010 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"http"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
)
|
||||
|
||||
type Page struct {
|
||||
@@ -15,12 +12,12 @@ type Page struct {
|
||||
Body []byte
|
||||
}
|
||||
|
||||
func (p *Page) save() error {
|
||||
func (p *Page) save() os.Error {
|
||||
filename := p.Title + ".txt"
|
||||
return ioutil.WriteFile(filename, p.Body, 0600)
|
||||
}
|
||||
|
||||
func loadPage(title string) (*Page, error) {
|
||||
func loadPage(title string) (*Page, os.Error) {
|
||||
filename := title + ".txt"
|
||||
body, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
@@ -1,19 +1,15 @@
|
||||
// Copyright 2010 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"flag"
|
||||
"go/ast"
|
||||
"go/parser"
|
||||
"go/printer"
|
||||
"go/ast"
|
||||
"go/token"
|
||||
"log"
|
||||
"os"
|
||||
"text/template"
|
||||
"template"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -1,7 +1,4 @@
|
||||
#!/usr/bin/env bash
|
||||
# Copyright 2010 The Go Authors. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style
|
||||
# license that can be found in the LICENSE file.
|
||||
|
||||
set -e
|
||||
wiki_pid=
|
||||
@@ -11,10 +8,10 @@ cleanup() {
|
||||
}
|
||||
trap cleanup 0 INT
|
||||
|
||||
go build -o get.bin get.go
|
||||
gomake get.bin
|
||||
addr=$(./get.bin -addr)
|
||||
sed s/:8080/$addr/ < final.go > final-test.go
|
||||
go build -o final-test.bin final-test.go
|
||||
gomake final-test.bin
|
||||
(./final-test.bin) &
|
||||
wiki_pid=$!
|
||||
|
||||
5
doc/codelab/wiki/view.html
Normal file
@@ -0,0 +1,5 @@
|
||||
<h1>{Title}</h1>
|
||||
|
||||
<p>[<a href="/edit/{Title}">edit</a>]</p>
|
||||
|
||||
<div>{Body}</div>
|
||||
@@ -1,17 +1,13 @@
|
||||
<!--{
|
||||
"Title": "Writing Web Applications",
|
||||
"Template": true
|
||||
}-->
|
||||
|
||||
<!-- Codelab: Writing Web Applications -->
|
||||
<h2>Introduction</h2>
|
||||
|
||||
<p>
|
||||
Covered in this tutorial:
|
||||
Covered in this codelab:
|
||||
</p>
|
||||
<ul>
|
||||
<li>Creating a data structure with load and save methods</li>
|
||||
<li>Using the <code>net/http</code> package to build web applications
|
||||
<li>Using the <code>html/template</code> package to process HTML templates</li>
|
||||
<li>Using the <code>http</code> package to build web applications
|
||||
<li>Using the <code>template</code> package to process HTML templates</li>
|
||||
<li>Using the <code>regexp</code> package to validate user input</li>
|
||||
<li>Using closures</li>
|
||||
</ul>
|
||||
@@ -22,27 +18,30 @@ Assumed knowledge:
|
||||
<ul>
|
||||
<li>Programming experience</li>
|
||||
<li>Understanding of basic web technologies (HTTP, HTML)</li>
|
||||
<li>Some UNIX/DOS command-line knowledge</li>
|
||||
<li>Some UNIX command-line knowledge</li>
|
||||
</ul>
|
||||
|
||||
<h2>Getting Started</h2>
|
||||
|
||||
<p>
|
||||
At present, you need to have a FreeBSD, Linux, OS X, or Windows machine to run Go.
|
||||
We will use <code>$</code> to represent the command prompt.
|
||||
At present, you need to have a Linux, OS X, or FreeBSD machine to run Go. If
|
||||
you don't have access to one, you could set up a Linux Virtual Machine (using
|
||||
<a href="http://www.virtualbox.org/">VirtualBox</a> or similar) or a
|
||||
<a href="http://www.google.com/search?q=virtual+private+server">Virtual
|
||||
Private Server</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Install Go (see the <a href="/doc/install">Installation Instructions</a>).
|
||||
Install Go (see the <a href="http://golang.org/doc/install.html">Installation Instructions</a>).
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Make a new directory for this tutorial inside your <code>GOPATH</code> and cd to it:
|
||||
Make a new directory for this codelab and cd to it:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
$ mkdir gowiki
|
||||
$ cd gowiki
|
||||
$ mkdir ~/gowiki
|
||||
$ cd ~/gowiki
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
@@ -56,13 +55,15 @@ package main
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
)
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
We import the <code>fmt</code> and <code>ioutil</code> packages from the Go
|
||||
standard library. Later, as we implement additional functionality, we will
|
||||
add more packages to this <code>import</code> declaration.
|
||||
We import the <code>fmt</code>, <code>ioutil</code> and <code>os</code>
|
||||
packages from the Go standard library. Later, as we implement additional
|
||||
functionality, we will add more packages to this <code>import</code>
|
||||
declaration.
|
||||
</p>
|
||||
|
||||
<h2>Data Structures</h2>
|
||||
@@ -74,12 +75,14 @@ Here, we define <code>Page</code> as a struct with two fields representing
|
||||
the title and body.
|
||||
</p>
|
||||
|
||||
{{code "doc/articles/wiki/part1.go" `/^type Page/` `/}/`}}
|
||||
<pre>
|
||||
!srcextract.bin -src=part1.go -name=Page
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
The type <code>[]byte</code> means "a <code>byte</code> slice".
|
||||
(See <a href="/doc/articles/slices_usage_and_internals.html">Slices: usage and
|
||||
internals</a> for more on slices.)
|
||||
(See <a href="http://golang.org/doc/effective_go.html#slices">Effective Go</a>
|
||||
for more on slices.)
|
||||
The <code>Body</code> element is a <code>[]byte</code> rather than
|
||||
<code>string</code> because that is the type expected by the <code>io</code>
|
||||
libraries we will use, as you'll see below.
|
||||
@@ -91,12 +94,14 @@ But what about persistent storage? We can address that by creating a
|
||||
<code>save</code> method on <code>Page</code>:
|
||||
</p>
|
||||
|
||||
{{code "doc/articles/wiki/part1.go" `/^func.*Page.*save/` `/}/`}}
|
||||
<pre>
|
||||
!srcextract.bin -src=part1.go -name=save
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
This method's signature reads: "This is a method named <code>save</code> that
|
||||
takes as its receiver <code>p</code>, a pointer to <code>Page</code> . It takes
|
||||
no parameters, and returns a value of type <code>error</code>."
|
||||
no parameters, and returns a value of type <code>os.Error</code>."
|
||||
</p>
|
||||
|
||||
<p>
|
||||
@@ -105,7 +110,7 @@ file. For simplicity, we will use the <code>Title</code> as the file name.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The <code>save</code> method returns an <code>error</code> value because
|
||||
The <code>save</code> method returns an <code>os.Error</code> value because
|
||||
that is the return type of <code>WriteFile</code> (a standard library function
|
||||
that writes a byte slice to a file). The <code>save</code> method returns the
|
||||
error value, to let the application handle it should anything go wrong while
|
||||
@@ -125,7 +130,9 @@ read-write permissions for the current user only. (See the Unix man page
|
||||
We will want to load pages, too:
|
||||
</p>
|
||||
|
||||
{{code "doc/articles/wiki/part1-noerror.go" `/^func loadPage/` `/^}/`}}
|
||||
<pre>
|
||||
!srcextract.bin -src=part1-noerror.go -name=loadPage
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
The function <code>loadPage</code> constructs the file name from
|
||||
@@ -135,7 +142,7 @@ The function <code>loadPage</code> constructs the file name from
|
||||
|
||||
<p>
|
||||
Functions can return multiple values. The standard library function
|
||||
<code>io.ReadFile</code> returns <code>[]byte</code> and <code>error</code>.
|
||||
<code>io.ReadFile</code> returns <code>[]byte</code> and <code>os.Error</code>.
|
||||
In <code>loadPage</code>, error isn't being handled yet; the "blank identifier"
|
||||
represented by the underscore (<code>_</code>) symbol is used to throw away the
|
||||
error return value (in essence, assigning the value to nothing).
|
||||
@@ -144,16 +151,19 @@ error return value (in essence, assigning the value to nothing).
|
||||
<p>
|
||||
But what happens if <code>ReadFile</code> encounters an error? For example,
|
||||
the file might not exist. We should not ignore such errors. Let's modify the
|
||||
function to return <code>*Page</code> and <code>error</code>.
|
||||
function to return <code>*Page</code> and <code>os.Error</code>.
|
||||
</p>
|
||||
|
||||
{{code "doc/articles/wiki/part1.go" `/^func loadPage/` `/^}/`}}
|
||||
<pre>
|
||||
!srcextract.bin -src=part1.go -name=loadPage
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Callers of this function can now check the second parameter; if it is
|
||||
<code>nil</code> then it has successfully loaded a Page. If not, it will be an
|
||||
<code>error</code> that can be handled by the caller (see the
|
||||
<a href="/ref/spec#Errors">language specification</a> for details).
|
||||
<code>os.Error</code> that can be handled by the caller (see the <a
|
||||
href="http://golang.org/pkg/os/#Error">os package documentation</a> for
|
||||
details).
|
||||
</p>
|
||||
|
||||
<p>
|
||||
@@ -162,7 +172,9 @@ load from a file. Let's write a <code>main</code> function to test what we've
|
||||
written:
|
||||
</p>
|
||||
|
||||
{{code "doc/articles/wiki/part1.go" `/^func main/` `/^}/`}}
|
||||
<pre>
|
||||
!srcextract.bin -src=part1.go -name=main
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
After compiling and executing this code, a file named <code>TestPage.txt</code>
|
||||
@@ -176,27 +188,31 @@ You can compile and run the program like this:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
$ go build wiki.go
|
||||
$ ./wiki
|
||||
$ 8g wiki.go
|
||||
$ 8l wiki.8
|
||||
$ ./8.out
|
||||
This is a sample page.
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
(If you're using Windows you must type "<code>wiki</code>" without the
|
||||
"<code>./</code>" to run the program.)
|
||||
(The <code>8g</code> and <code>8l</code> commands are applicable to
|
||||
<code>GOARCH=386</code>. If you're on an <code>amd64</code> system,
|
||||
substitute 6's for the 8's.)
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<a href="part1.go">Click here to view the code we've written so far.</a>
|
||||
</p>
|
||||
|
||||
<h2>Introducing the <code>net/http</code> package (an interlude)</h2>
|
||||
<h2>Introducing the <code>http</code> package (an interlude)</h2>
|
||||
|
||||
<p>
|
||||
Here's a full working example of a simple web server:
|
||||
</p>
|
||||
|
||||
{{code "doc/articles/wiki/http-sample.go"}}
|
||||
<pre>
|
||||
!htmlify.bin < http-sample.go
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
The <code>main</code> function begins with a call to
|
||||
@@ -240,17 +256,18 @@ the program would present a page containing:
|
||||
</p>
|
||||
<pre>Hi there, I love monkeys!</pre>
|
||||
|
||||
<h2>Using <code>net/http</code> to serve wiki pages</h2>
|
||||
<h2>Using <code>http</code> to serve wiki pages</h2>
|
||||
|
||||
<p>
|
||||
To use the <code>net/http</code> package, it must be imported:
|
||||
To use the <code>http</code> package, it must be imported:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
import (
|
||||
"fmt"
|
||||
<b>"net/http"</b>
|
||||
<b>"http"</b>
|
||||
"io/ioutil"
|
||||
"os"
|
||||
)
|
||||
</pre>
|
||||
|
||||
@@ -258,9 +275,11 @@ import (
|
||||
Let's create a handler to view a wiki page:
|
||||
</p>
|
||||
|
||||
{{code "doc/articles/wiki/part2.go" `/^const lenPath/`}}
|
||||
<pre>
|
||||
!srcextract.bin -src=part2.go -name=lenPath
|
||||
|
||||
{{code "doc/articles/wiki/part2.go" `/^func viewHandler/` `/^}/`}}
|
||||
!srcextract.bin -src=part2.go -name=viewHandler
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
First, this function extracts the page title from <code>r.URL.Path</code>,
|
||||
@@ -278,7 +297,7 @@ HTML, and writes it to <code>w</code>, the <code>http.ResponseWriter</code>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Again, note the use of <code>_</code> to ignore the <code>error</code>
|
||||
Again, note the use of <code>_</code> to ignore the <code>os.Error</code>
|
||||
return value from <code>loadPage</code>. This is done here for simplicity
|
||||
and generally considered bad practice. We will attend to this later.
|
||||
</p>
|
||||
@@ -289,7 +308,9 @@ initializes <code>http</code> using the <code>viewHandler</code> to handle
|
||||
any requests under the path <code>/view/</code>.
|
||||
</p>
|
||||
|
||||
{{code "doc/articles/wiki/part2.go" `/^func main/` `/^}/`}}
|
||||
<pre>
|
||||
!srcextract.bin -src=part2.go -name=main
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
<a href="part2.go">Click here to view the code we've written so far.</a>
|
||||
@@ -297,17 +318,14 @@ any requests under the path <code>/view/</code>.
|
||||
|
||||
<p>
|
||||
Let's create some page data (as <code>test.txt</code>), compile our code, and
|
||||
try serving a wiki page.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Open <code>test.txt</code> file in your editor, and save the string "Hello world" (without quotes)
|
||||
in it.
|
||||
try serving a wiki page:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
$ go build wiki.go
|
||||
$ ./wiki
|
||||
$ echo "Hello world" > test.txt
|
||||
$ 8g wiki.go
|
||||
$ 8l wiki.8
|
||||
$ ./8.out
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
@@ -329,7 +347,9 @@ form.
|
||||
First, we add them to <code>main()</code>:
|
||||
</p>
|
||||
|
||||
{{code "doc/articles/wiki/final-noclosure.go" `/^func main/` `/^}/`}}
|
||||
<pre>
|
||||
!srcextract.bin -src=final-noclosure.go -name=main
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
The function <code>editHandler</code> loads the page
|
||||
@@ -337,24 +357,26 @@ The function <code>editHandler</code> loads the page
|
||||
and displays an HTML form.
|
||||
</p>
|
||||
|
||||
{{code "doc/articles/wiki/notemplate.go" `/^func editHandler/` `/^}/`}}
|
||||
<pre>
|
||||
!srcextract.bin -src=notemplate.go -name=editHandler
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
This function will work fine, but all that hard-coded HTML is ugly.
|
||||
Of course, there is a better way.
|
||||
</p>
|
||||
|
||||
<h2>The <code>html/template</code> package</h2>
|
||||
<h2>The <code>template</code> package</h2>
|
||||
|
||||
<p>
|
||||
The <code>html/template</code> package is part of the Go standard library.
|
||||
We can use <code>html/template</code> to keep the HTML in a separate file,
|
||||
allowing us to change the layout of our edit page without modifying the
|
||||
underlying Go code.
|
||||
The <code>template</code> package is part of the Go standard library. We can
|
||||
use <code>template</code> to keep the HTML in a separate file, allowing
|
||||
us to change the layout of our edit page without modifying the underlying Go
|
||||
code.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
First, we must add <code>html/template</code> to the list of imports:
|
||||
First, we must add <code>template</code> to the list of imports:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
@@ -362,7 +384,7 @@ import (
|
||||
"http"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
<b>"html/template"</b>
|
||||
<b>"template"</b>
|
||||
)
|
||||
</pre>
|
||||
|
||||
@@ -371,36 +393,38 @@ Let's create a template file containing the HTML form.
|
||||
Open a new file named <code>edit.html</code>, and add the following lines:
|
||||
</p>
|
||||
|
||||
{{code "doc/articles/wiki/edit.html"}}
|
||||
<pre>
|
||||
!htmlify.bin < edit.html
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Modify <code>editHandler</code> to use the template, instead of the hard-coded
|
||||
HTML:
|
||||
</p>
|
||||
|
||||
{{code "doc/articles/wiki/final-noerror.go" `/^func editHandler/` `/^}/`}}
|
||||
<pre>
|
||||
!srcextract.bin -src=final-noerror.go -name=editHandler
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
The function <code>template.ParseFiles</code> will read the contents of
|
||||
The function <code>template.ParseFile</code> will read the contents of
|
||||
<code>edit.html</code> and return a <code>*template.Template</code>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The method <code>t.Execute</code> executes the template, writing the
|
||||
generated HTML to the <code>http.ResponseWriter</code>.
|
||||
The <code>.Title</code> and <code>.Body</code> dotted identifiers refer to
|
||||
<code>p.Title</code> and <code>p.Body</code>.
|
||||
The method <code>t.Execute</code> replaces all occurrences of
|
||||
<code>{Title}</code> and <code>{Body}</code> with the values of
|
||||
<code>p.Title</code> and <code>p.Body</code>, and writes the resultant
|
||||
HTML to the <code>http.ResponseWriter</code>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Template directives are enclosed in double curly braces.
|
||||
The <code>printf "%s" .Body</code> instruction is a function call
|
||||
that outputs <code>.Body</code> as a string instead of a stream of bytes,
|
||||
the same as a call to <code>fmt.Printf</code>.
|
||||
The <code>|html</code> part of each directive pipes the value through the
|
||||
<code>html</code> formatter before outputting it, which escapes HTML
|
||||
characters (such as replacing <code>></code> with <code>&gt;</code>),
|
||||
preventing user data from corrupting the form HTML.
|
||||
Note that we've used <code>{Body|html}</code> in the above template.
|
||||
The <code>|html</code> part asks the template engine to pass the value
|
||||
<code>Body</code> through the <code>html</code> formatter before outputting it,
|
||||
which escapes HTML characters (such as replacing <code>></code> with
|
||||
<code>&gt;</code>).
|
||||
This will prevent user data from corrupting the form HTML.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
@@ -413,13 +437,17 @@ While we're working with templates, let's create a template for our
|
||||
<code>viewHandler</code> called <code>view.html</code>:
|
||||
</p>
|
||||
|
||||
{{code "doc/articles/wiki/view.html"}}
|
||||
<pre>
|
||||
!htmlify.bin < view.html
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Modify <code>viewHandler</code> accordingly:
|
||||
</p>
|
||||
|
||||
{{code "doc/articles/wiki/final-noerror.go" `/^func viewHandler/` `/^}/`}}
|
||||
<pre>
|
||||
!srcextract.bin -src=final-noerror.go -name=viewHandler
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Notice that we've used almost exactly the same templating code in both
|
||||
@@ -427,9 +455,13 @@ handlers. Let's remove this duplication by moving the templating code
|
||||
to its own function:
|
||||
</p>
|
||||
|
||||
{{code "doc/articles/wiki/final-template.go" `/^func viewHandler/` `/^}/`}}
|
||||
{{code "doc/articles/wiki/final-template.go" `/^func editHandler/` `/^}/`}}
|
||||
{{code "doc/articles/wiki/final-template.go" `/^func renderTemplate/` `/^}/`}}
|
||||
<pre>
|
||||
!srcextract.bin -src=final-template.go -name=viewHandler
|
||||
|
||||
!srcextract.bin -src=final-template.go -name=editHandler
|
||||
|
||||
!srcextract.bin -src=final-template.go -name=renderTemplate
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
The handlers are now shorter and simpler.
|
||||
@@ -438,14 +470,15 @@ The handlers are now shorter and simpler.
|
||||
<h2>Handling non-existent pages</h2>
|
||||
|
||||
<p>
|
||||
What if you visit <a href="http://localhost:8080/view/APageThatDoesntExist">
|
||||
<code>/view/APageThatDoesntExist</code></a>? The program will crash. This is
|
||||
because it ignores the error return value from <code>loadPage</code>. Instead,
|
||||
if the requested Page doesn't exist, it should redirect the client to the edit
|
||||
Page so the content may be created:
|
||||
What if you visit <code>/view/APageThatDoesntExist</code>? The program will
|
||||
crash. This is because it ignores the error return value from
|
||||
<code>loadPage</code>. Instead, if the requested Page doesn't exist, it should
|
||||
redirect the client to the edit Page so the content may be created:
|
||||
</p>
|
||||
|
||||
{{code "doc/articles/wiki/final-noclosure.go" `/^func viewHandler/` `/^}/`}}
|
||||
<pre>
|
||||
!srcextract.bin -src=final-noclosure.go -name=viewHandler
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
The <code>http.Redirect</code> function adds an HTTP status code of
|
||||
@@ -459,7 +492,9 @@ header to the HTTP response.
|
||||
The function <code>saveHandler</code> will handle the form submission.
|
||||
</p>
|
||||
|
||||
{{code "doc/articles/wiki/final-template.go" `/^func saveHandler/` `/^}/`}}
|
||||
<pre>
|
||||
!srcextract.bin -src=final-template.go -name=saveHandler
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
The page title (provided in the URL) and the form's only field,
|
||||
@@ -489,7 +524,9 @@ function and the user will be notified.
|
||||
First, let's handle the errors in <code>renderTemplate</code>:
|
||||
</p>
|
||||
|
||||
{{code "doc/articles/wiki/final-parsetemplate.go" `/^func renderTemplate/` `/^}/`}}
|
||||
<pre>
|
||||
!srcextract.bin -src=final-parsetemplate.go -name=renderTemplate
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
The <code>http.Error</code> function sends a specified HTTP response code
|
||||
@@ -501,7 +538,9 @@ Already the decision to put this in a separate function is paying off.
|
||||
Now let's fix up <code>saveHandler</code>:
|
||||
</p>
|
||||
|
||||
{{code "doc/articles/wiki/final-noclosure.go" `/^func saveHandler/` `/^}/`}}
|
||||
<pre>
|
||||
!srcextract.bin -src=final-noclosure.go -name=saveHandler
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Any errors that occur during <code>p.save()</code> will be reported
|
||||
@@ -512,28 +551,35 @@ to the user.
|
||||
|
||||
<p>
|
||||
There is an inefficiency in this code: <code>renderTemplate</code> calls
|
||||
<code>ParseFiles</code> every time a page is rendered.
|
||||
A better approach would be to call <code>ParseFiles</code> once at program
|
||||
initialization, parsing all templates into a single <code>*Template</code>.
|
||||
Then we can use the
|
||||
<a href="/pkg/html/template/#Template.ExecuteTemplate"><code>ExecuteTemplate</code></a>
|
||||
method to render a specific template.
|
||||
<code>ParseFile</code> every time a page is rendered.
|
||||
A better approach would be to call <code>ParseFile</code> once for each
|
||||
template at program initialization, and store the resultant
|
||||
<code>*Template</code> values in a data structure for later use.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
First we create a global variable named <code>templates</code>, and initialize
|
||||
it with <code>ParseFiles</code>.
|
||||
First we create a global map named <code>templates</code> in which to store
|
||||
our <code>*Template</code> values, keyed by <code>string</code>
|
||||
(the template name):
|
||||
</p>
|
||||
|
||||
{{code "doc/articles/wiki/final.go" `/var templates/`}}
|
||||
<pre>
|
||||
!srcextract.bin -src=final.go -name=templates
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
The function <code>template.Must</code> is a convenience wrapper that panics
|
||||
when passed a non-nil <code>error</code> value, and otherwise returns the
|
||||
<code>*Template</code> unaltered. A panic is appropriate here; if the templates
|
||||
can't be loaded the only sensible thing to do is exit the program.
|
||||
Then we create an <code>init</code> function, which will be called before
|
||||
<code>main</code> at program initialization. The function
|
||||
<code>template.MustParseFile</code> is a convenience wrapper around
|
||||
<code>ParseFile</code> that does not return an error code; instead, it panics
|
||||
if an error is encountered. A panic is appropriate here; if the templates can't
|
||||
be loaded the only sensible thing to do is exit the program.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
!srcextract.bin -src=final.go -name=init
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
A <code>for</code> loop is used with a <code>range</code> statement to iterate
|
||||
over an array constant containing the names of the templates we want parsed.
|
||||
@@ -542,17 +588,13 @@ that array.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
We then modify the <code>renderTemplate</code> function to call the
|
||||
<code>templates.ExecuteTemplate</code> method with the name of the appropriate
|
||||
template:
|
||||
</p>
|
||||
We then modify our <code>renderTemplate</code> function to call
|
||||
the <code>Execute</code> method on the appropriate <code>Template</code> from
|
||||
<code>templates</code>:
|
||||
|
||||
{{code "doc/articles/wiki/final.go" `/func renderTemplate/` `/^}/`}}
|
||||
|
||||
<p>
|
||||
Note that the template name is the template file name, so we must
|
||||
append <code>".html"</code> to the <code>tmpl</code> argument.
|
||||
</p>
|
||||
<pre>
|
||||
!srcextract.bin -src=final.go -name=renderTemplate
|
||||
</pre>
|
||||
|
||||
<h2>Validation</h2>
|
||||
|
||||
@@ -567,14 +609,17 @@ First, add <code>"regexp"</code> to the <code>import</code> list.
|
||||
Then we can create a global variable to store our validation regexp:
|
||||
</p>
|
||||
|
||||
{{code "doc/articles/wiki/final-noclosure.go" `/^var titleValidator/`}}
|
||||
<pre>
|
||||
!srcextract.bin -src=final-noclosure.go -name=titleValidator
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
The function <code>regexp.MustCompile</code> will parse and compile the
|
||||
regular expression, and return a <code>regexp.Regexp</code>.
|
||||
<code>MustCompile</code> is distinct from <code>Compile</code> in that it will
|
||||
panic if the expression compilation fails, while <code>Compile</code> returns
|
||||
an <code>error</code> as a second parameter.
|
||||
<code>MustCompile</code>, like <code>template.MustParseFile</code>,
|
||||
is distinct from <code>Compile</code> in that it will panic if
|
||||
the expression compilation fails, while <code>Compile</code> returns an
|
||||
<code>os.Error</code> as a second parameter.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
@@ -582,7 +627,9 @@ Now, let's write a function that extracts the title string from the request
|
||||
URL, and tests it against our <code>TitleValidator</code> expression:
|
||||
</p>
|
||||
|
||||
{{code "doc/articles/wiki/final-noclosure.go" `/func getTitle/` `/^}/`}}
|
||||
<pre>
|
||||
!srcextract.bin -src=final-noclosure.go -name=getTitle
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
If the title is valid, it will be returned along with a <code>nil</code>
|
||||
@@ -595,9 +642,13 @@ handler.
|
||||
Let's put a call to <code>getTitle</code> in each of the handlers:
|
||||
</p>
|
||||
|
||||
{{code "doc/articles/wiki/final-noclosure.go" `/^func viewHandler/` `/^}/`}}
|
||||
{{code "doc/articles/wiki/final-noclosure.go" `/^func editHandler/` `/^}/`}}
|
||||
{{code "doc/articles/wiki/final-noclosure.go" `/^func saveHandler/` `/^}/`}}
|
||||
<pre>
|
||||
!srcextract.bin -src=final-noclosure.go -name=viewHandler
|
||||
|
||||
!srcextract.bin -src=final-noclosure.go -name=editHandler
|
||||
|
||||
!srcextract.bin -src=final-noclosure.go -name=saveHandler
|
||||
</pre>
|
||||
|
||||
<h2>Introducing Function Literals and Closures</h2>
|
||||
|
||||
@@ -605,7 +656,7 @@ Let's put a call to <code>getTitle</code> in each of the handlers:
|
||||
Catching the error condition in each handler introduces a lot of repeated code.
|
||||
What if we could wrap each of the handlers in a function that does this
|
||||
validation and error checking? Go's
|
||||
<a href="/ref/spec#Function_declarations">function
|
||||
<a href="http://golang.org/doc/go_spec.html#Function_declarations">function
|
||||
literals</a> provide a powerful means of abstracting functionality
|
||||
that can help us here.
|
||||
</p>
|
||||
@@ -648,7 +699,9 @@ Now we can take the code from <code>getTitle</code> and use it here
|
||||
(with some minor modifications):
|
||||
</p>
|
||||
|
||||
{{code "doc/articles/wiki/final.go" `/func makeHandler/` `/^}/`}}
|
||||
<pre>
|
||||
!srcextract.bin -src=final.go -name=makeHandler
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
The closure returned by <code>makeHandler</code> is a function that takes
|
||||
@@ -669,16 +722,22 @@ Now we can wrap the handler functions with <code>makeHandler</code> in
|
||||
package:
|
||||
</p>
|
||||
|
||||
{{code "doc/articles/wiki/final.go" `/func main/` `/^}/`}}
|
||||
<pre>
|
||||
!srcextract.bin -src=final.go -name=main
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Finally we remove the calls to <code>getTitle</code> from the handler functions,
|
||||
making them much simpler:
|
||||
</p>
|
||||
|
||||
{{code "doc/articles/wiki/final.go" `/^func viewHandler/` `/^}/`}}
|
||||
{{code "doc/articles/wiki/final.go" `/^func editHandler/` `/^}/`}}
|
||||
{{code "doc/articles/wiki/final.go" `/^func saveHandler/` `/^}/`}}
|
||||
<pre>
|
||||
!srcextract.bin -src=final.go -name=viewHandler
|
||||
|
||||
!srcextract.bin -src=final.go -name=editHandler
|
||||
|
||||
!srcextract.bin -src=final.go -name=saveHandler
|
||||
</pre>
|
||||
|
||||
<h2>Try it out!</h2>
|
||||
|
||||
@@ -691,8 +750,9 @@ Recompile the code, and run the app:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
$ go build wiki.go
|
||||
$ ./wiki
|
||||
$ 8g wiki.go
|
||||
$ 8l wiki.8
|
||||
$ ./8.out
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
@@ -1,6 +1,4 @@
|
||||
<!--{
|
||||
"Title": "Using Mercurial Queues with Codereview"
|
||||
}-->
|
||||
<!-- Using Mercurial Queues with Codereview -->
|
||||
|
||||
<h2 id="Introduction">Introduction</h2>
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
turn.
|
||||
</step>
|
||||
|
||||
<step title="Multiple return values" src="doc/codewalk/pig.go:/\/\/ roll returns/,/true\n}/">
|
||||
<step title="Multiple return values" src="doc/codewalk/pig.go:/\/\/ roll returns/,/stay.*true\n}/">
|
||||
Go functions can return multiple values.
|
||||
<br/><br/>
|
||||
|
||||
@@ -82,6 +82,16 @@
|
||||
associated with the current player.
|
||||
</step>
|
||||
|
||||
<step title="Comparing functions" src="doc/codewalk/pig.go:/if action/,/currentPlayer\)\)\n\t\t}/">
|
||||
Functions can be compared for equality in Go. From the
|
||||
<a href="http://golang.org/doc/go_spec.html#Comparison_operators">language specification</a>:
|
||||
Function values are equal if they refer to the same function or if both are <code>nil</code>.
|
||||
<br/><br/>
|
||||
|
||||
We enforce that a <code>strategy</code> function can only return a legal
|
||||
<code>action</code>: either <code>roll</code> or <code>stay</code>.
|
||||
</step>
|
||||
|
||||
<step title="Simulating a tournament" src="doc/codewalk/pig.go:/\/\/ roundRobin/,/gamesPerStrategy\n}/">
|
||||
The <code>roundRobin</code> function simulates a tournament and tallies wins.
|
||||
Each strategy plays each other strategy <code>gamesPerSeries</code> times.
|
||||
|
||||
@@ -1,130 +0,0 @@
|
||||
// Copyright 2011 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
/*
|
||||
Generating random text: a Markov chain algorithm
|
||||
|
||||
Based on the program presented in the "Design and Implementation" chapter
|
||||
of The Practice of Programming (Kernighan and Pike, Addison-Wesley 1999).
|
||||
See also Computer Recreations, Scientific American 260, 122 - 125 (1989).
|
||||
|
||||
A Markov chain algorithm generates text by creating a statistical model of
|
||||
potential textual suffixes for a given prefix. Consider this text:
|
||||
|
||||
I am not a number! I am a free man!
|
||||
|
||||
Our Markov chain algorithm would arrange this text into this set of prefixes
|
||||
and suffixes, or "chain": (This table assumes a prefix length of two words.)
|
||||
|
||||
Prefix Suffix
|
||||
|
||||
"" "" I
|
||||
"" I am
|
||||
I am a
|
||||
I am not
|
||||
a free man!
|
||||
am a free
|
||||
am not a
|
||||
a number! I
|
||||
number! I am
|
||||
not a number!
|
||||
|
||||
To generate text using this table we select an initial prefix ("I am", for
|
||||
example), choose one of the suffixes associated with that prefix at random
|
||||
with probability determined by the input statistics ("a"),
|
||||
and then create a new prefix by removing the first word from the prefix
|
||||
and appending the suffix (making the new prefix is "am a"). Repeat this process
|
||||
until we can't find any suffixes for the current prefix or we exceed the word
|
||||
limit. (The word limit is necessary as the chain table may contain cycles.)
|
||||
|
||||
Our version of this program reads text from standard input, parsing it into a
|
||||
Markov chain, and writes generated text to standard output.
|
||||
The prefix and output lengths can be specified using the -prefix and -words
|
||||
flags on the command-line.
|
||||
*/
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"math/rand"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Prefix is a Markov chain prefix of one or more words.
|
||||
type Prefix []string
|
||||
|
||||
// String returns the Prefix as a string (for use as a map key).
|
||||
func (p Prefix) String() string {
|
||||
return strings.Join(p, " ")
|
||||
}
|
||||
|
||||
// Shift removes the first word from the Prefix and appends the given word.
|
||||
func (p Prefix) Shift(word string) {
|
||||
copy(p, p[1:])
|
||||
p[len(p)-1] = word
|
||||
}
|
||||
|
||||
// Chain contains a map ("chain") of prefixes to a list of suffixes.
|
||||
// A prefix is a string of prefixLen words joined with spaces.
|
||||
// A suffix is a single word. A prefix can have multiple suffixes.
|
||||
type Chain struct {
|
||||
chain map[string][]string
|
||||
prefixLen int
|
||||
}
|
||||
|
||||
// NewChain returns a new Chain with prefixes of prefixLen words.
|
||||
func NewChain(prefixLen int) *Chain {
|
||||
return &Chain{make(map[string][]string), prefixLen}
|
||||
}
|
||||
|
||||
// Build reads text from the provided Reader and
|
||||
// parses it into prefixes and suffixes that are stored in Chain.
|
||||
func (c *Chain) Build(r io.Reader) {
|
||||
br := bufio.NewReader(r)
|
||||
p := make(Prefix, c.prefixLen)
|
||||
for {
|
||||
var s string
|
||||
if _, err := fmt.Fscan(br, &s); err != nil {
|
||||
break
|
||||
}
|
||||
key := p.String()
|
||||
c.chain[key] = append(c.chain[key], s)
|
||||
p.Shift(s)
|
||||
}
|
||||
}
|
||||
|
||||
// Generate returns a string of at most n words generated from Chain.
|
||||
func (c *Chain) Generate(n int) string {
|
||||
p := make(Prefix, c.prefixLen)
|
||||
var words []string
|
||||
for i := 0; i < n; i++ {
|
||||
choices := c.chain[p.String()]
|
||||
if len(choices) == 0 {
|
||||
break
|
||||
}
|
||||
next := choices[rand.Intn(len(choices))]
|
||||
words = append(words, next)
|
||||
p.Shift(next)
|
||||
}
|
||||
return strings.Join(words, " ")
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Register command-line flags.
|
||||
numWords := flag.Int("words", 100, "maximum number of words to print")
|
||||
prefixLen := flag.Int("prefix", 2, "prefix length in words")
|
||||
|
||||
flag.Parse() // Parse command-line flags.
|
||||
rand.Seed(time.Now().UnixNano()) // Seed the random number generator.
|
||||
|
||||
c := NewChain(*prefixLen) // Initialize a new Chain.
|
||||
c.Build(os.Stdin) // Build chains from standard input.
|
||||
text := c.Generate(*numWords) // Generate text.
|
||||
fmt.Println(text) // Write text to standard output.
|
||||
}
|
||||
@@ -1,307 +0,0 @@
|
||||
<!--
|
||||
Copyright 2011 The Go Authors. All rights reserved.
|
||||
Use of this source code is governed by a BSD-style
|
||||
license that can be found in the LICENSE file.
|
||||
-->
|
||||
|
||||
<codewalk title="Generating arbitrary text: a Markov chain algorithm">
|
||||
|
||||
<step title="Introduction" src="doc/codewalk/markov.go:/Generating/,/line\./">
|
||||
This codewalk describes a program that generates random text using
|
||||
a Markov chain algorithm. The package comment describes the algorithm
|
||||
and the operation of the program. Please read it before continuing.
|
||||
</step>
|
||||
|
||||
<step title="Modeling Markov chains" src="doc/codewalk/markov.go:/ chain/">
|
||||
A chain consists of a prefix and a suffix. Each prefix is a set
|
||||
number of words, while a suffix is a single word.
|
||||
A prefix can have an arbitrary number of suffixes.
|
||||
To model this data, we use a <code>map[string][]string</code>.
|
||||
Each map key is a prefix (a <code>string</code>) and its values are
|
||||
lists of suffixes (a slice of strings, <code>[]string</code>).
|
||||
<br/><br/>
|
||||
Here is the example table from the package comment
|
||||
as modeled by this data structure:
|
||||
<pre>
|
||||
map[string][]string{
|
||||
" ": {"I"},
|
||||
" I": {"am"},
|
||||
"I am": {"a", "not"},
|
||||
"a free": {"man!"},
|
||||
"am a": {"free"},
|
||||
"am not": {"a"},
|
||||
"a number!": {"I"},
|
||||
"number! I": {"am"},
|
||||
"not a": {"number!"},
|
||||
}</pre>
|
||||
While each prefix consists of multiple words, we
|
||||
store prefixes in the map as a single <code>string</code>.
|
||||
It would seem more natural to store the prefix as a
|
||||
<code>[]string</code>, but we can't do this with a map because the
|
||||
key type of a map must implement equality (and slices do not).
|
||||
<br/><br/>
|
||||
Therefore, in most of our code we will model prefixes as a
|
||||
<code>[]string</code> and join the strings together with a space
|
||||
to generate the map key:
|
||||
<pre>
|
||||
Prefix Map key
|
||||
|
||||
[]string{"", ""} " "
|
||||
[]string{"", "I"} " I"
|
||||
[]string{"I", "am"} "I am"
|
||||
</pre>
|
||||
</step>
|
||||
|
||||
<step title="The Chain struct" src="doc/codewalk/markov.go:/type Chain/,/}/">
|
||||
The complete state of the chain table consists of the table itself and
|
||||
the word length of the prefixes. The <code>Chain</code> struct stores
|
||||
this data.
|
||||
</step>
|
||||
|
||||
<step title="The NewChain constructor function" src="doc/codewalk/markov.go:/func New/,/}/">
|
||||
The <code>Chain</code> struct has two unexported fields (those that
|
||||
do not begin with an upper case character), and so we write a
|
||||
<code>NewChain</code> constructor function that initializes the
|
||||
<code>chain</code> map with <code>make</code> and sets the
|
||||
<code>prefixLen</code> field.
|
||||
<br/><br/>
|
||||
This is constructor function is not strictly necessary as this entire
|
||||
program is within a single package (<code>main</code>) and therefore
|
||||
there is little practical difference between exported and unexported
|
||||
fields. We could just as easily write out the contents of this function
|
||||
when we want to construct a new Chain.
|
||||
But using these unexported fields is good practice; it clearly denotes
|
||||
that only methods of Chain and its constructor function should access
|
||||
those fields. Also, structuring <code>Chain</code> like this means we
|
||||
could easily move it into its own package at some later date.
|
||||
</step>
|
||||
|
||||
<step title="The Prefix type" src="doc/codewalk/markov.go:/type Prefix/">
|
||||
Since we'll be working with prefixes often, we define a
|
||||
<code>Prefix</code> type with the concrete type <code>[]string</code>.
|
||||
Defining a named type clearly allows us to be explicit when we are
|
||||
working with a prefix instead of just a <code>[]string</code>.
|
||||
Also, in Go we can define methods on any named type (not just structs),
|
||||
so we can add methods that operate on <code>Prefix</code> if we need to.
|
||||
</step>
|
||||
|
||||
<step title="The String method" src="doc/codewalk/markov.go:/func[^\n]+String/,/}/">
|
||||
The first method we define on <code>Prefix</code> is
|
||||
<code>String</code>. It returns a <code>string</code> representation
|
||||
of a <code>Prefix</code> by joining the slice elements together with
|
||||
spaces. We will use this method to generate keys when working with
|
||||
the chain map.
|
||||
</step>
|
||||
|
||||
<step title="Building the chain" src="doc/codewalk/markov.go:/func[^\n]+Build/,/\n}/">
|
||||
The <code>Build</code> method reads text from an <code>io.Reader</code>
|
||||
and parses it into prefixes and suffixes that are stored in the
|
||||
<code>Chain</code>.
|
||||
<br/><br/>
|
||||
The <code><a href="/pkg/io/#Reader">io.Reader</a></code> is an
|
||||
interface type that is widely used by the standard library and
|
||||
other Go code. Our code uses the
|
||||
<code><a href="/pkg/fmt/#Fscan">fmt.Fscan</a></code> function, which
|
||||
reads space-separated values from an <code>io.Reader</code>.
|
||||
<br/><br/>
|
||||
The <code>Build</code> method returns once the <code>Reader</code>'s
|
||||
<code>Read</code> method returns <code>io.EOF</code> (end of file)
|
||||
or some other read error occurs.
|
||||
</step>
|
||||
|
||||
<step title="Buffering the input" src="doc/codewalk/markov.go:/bufio\.NewReader/">
|
||||
This function does many small reads, which can be inefficient for some
|
||||
<code>Readers</code>. For efficiency we wrap the provided
|
||||
<code>io.Reader</code> with
|
||||
<code><a href="/pkg/bufio/">bufio.NewReader</a></code> to create a
|
||||
new <code>io.Reader</code> that provides buffering.
|
||||
</step>
|
||||
|
||||
<step title="The Prefix variable" src="doc/codewalk/markov.go:/make\(Prefix/">
|
||||
At the top of the function we make a <code>Prefix</code> slice
|
||||
<code>p</code> using the <code>Chain</code>'s <code>prefixLen</code>
|
||||
field as its length.
|
||||
We'll use this variable to hold the current prefix and mutate it with
|
||||
each new word we encounter.
|
||||
</step>
|
||||
|
||||
<step title="Scanning words" src="doc/codewalk/markov.go:/var s string/,/\n }/">
|
||||
In our loop we read words from the <code>Reader</code> into a
|
||||
<code>string</code> variable <code>s</code> using
|
||||
<code>fmt.Fscan</code>. Since <code>Fscan</code> uses space to
|
||||
separate each input value, each call will yield just one word
|
||||
(including punctuation), which is exactly what we need.
|
||||
<br/><br/>
|
||||
<code>Fscan</code> returns an error if it encounters a read error
|
||||
(<code>io.EOF</code>, for example) or if it can't scan the requested
|
||||
value (in our case, a single string). In either case we just want to
|
||||
stop scanning, so we <code>break</code> out of the loop.
|
||||
</step>
|
||||
|
||||
<step title="Adding a prefix and suffix to the chain" src="doc/codewalk/markov.go:/ key/,/key\], s\)">
|
||||
The word stored in <code>s</code> is a new suffix. We add the new
|
||||
prefix/suffix combination to the <code>chain</code> map by computing
|
||||
the map key with <code>p.String</code> and appending the suffix
|
||||
to the slice stored under that key.
|
||||
<br/><br/>
|
||||
The built-in <code>append</code> function appends elements to a slice
|
||||
and allocates new storage when necessary. When the provided slice is
|
||||
<code>nil</code>, <code>append</code> allocates a new slice.
|
||||
This behavior conveniently ties in with the semantics of our map:
|
||||
retrieving an unset key returns the zero value of the value type and
|
||||
the zero value of <code>[]string</code> is <code>nil</code>.
|
||||
When our program encounters a new prefix (yielding a <code>nil</code>
|
||||
value in the map) <code>append</code> will allocate a new slice.
|
||||
<br/><br/>
|
||||
For more information about the <code>append</code> function and slices
|
||||
in general see the
|
||||
<a href="/doc/articles/slices_usage_and_internals.html">Slices: usage and internals</a> article.
|
||||
</step>
|
||||
|
||||
<step title="Pushing the suffix onto the prefix" src="doc/codewalk/markov.go:/p\.Shift/">
|
||||
Before reading the next word our algorithm requires us to drop the
|
||||
first word from the prefix and push the current suffix onto the prefix.
|
||||
<br/><br/>
|
||||
When in this state
|
||||
<pre>
|
||||
p == Prefix{"I", "am"}
|
||||
s == "not" </pre>
|
||||
the new value for <code>p</code> would be
|
||||
<pre>
|
||||
p == Prefix{"am", "not"}</pre>
|
||||
This operation is also required during text generation so we put
|
||||
the code to perform this mutation of the slice inside a method on
|
||||
<code>Prefix</code> named <code>Shift</code>.
|
||||
</step>
|
||||
|
||||
<step title="The Shift method" src="doc/codewalk/markov.go:/func[^\n]+Shift/,/\n}/">
|
||||
The <code>Shift</code> method uses the built-in <code>copy</code>
|
||||
function to copy the last len(p)-1 elements of <code>p</code> to
|
||||
the start of the slice, effectively moving the elements
|
||||
one index to the left (if you consider zero as the leftmost index).
|
||||
<pre>
|
||||
p := Prefix{"I", "am"}
|
||||
copy(p, p[:1])
|
||||
// p == Prefix{"am", "am"}</pre>
|
||||
We then assign the provided <code>word</code> to the last index
|
||||
of the slice:
|
||||
<pre>
|
||||
// suffix == "not"
|
||||
p[len(p)-1] = suffix
|
||||
// p == Prefix{"am", "not"}</pre>
|
||||
</step>
|
||||
|
||||
<step title="Generating text" src="doc/codewalk/markov.go:/func[^\n]+Generate/,/\n}/">
|
||||
The <code>Generate</code> method is similar to <code>Build</code>
|
||||
except that instead of reading words from a <code>Reader</code>
|
||||
and storing them in a map, it reads words from the map and
|
||||
appends them to a slice (<code>words</code>).
|
||||
<br/><br/>
|
||||
<code>Generate</code> uses a conditional for loop to generate
|
||||
up to <code>n</code> words.
|
||||
</step>
|
||||
|
||||
<step title="Getting potential suffixes" src="doc/codewalk/markov.go:/choices/,/}\n/">
|
||||
At each iteration of the loop we retrieve a list of potential suffixes
|
||||
for the current prefix. We access the <code>chain</code> map at key
|
||||
<code>p.String()</code> and assign its contents to <code>choices</code>.
|
||||
<br/><br/>
|
||||
If <code>len(choices)</code> is zero we break out of the loop as there
|
||||
are no potential suffixes for that prefix.
|
||||
This test also works if the key isn't present in the map at all:
|
||||
in that case, <code>choices</code> will be <code>nil</code> and the
|
||||
length of a <code>nil</code> slice is zero.
|
||||
</step>
|
||||
|
||||
<step title="Choosing a suffix at random" src="doc/codewalk/markov.go:/next := choices/,/Shift/">
|
||||
To choose a suffix we use the
|
||||
<code><a href="/pkg/rand/#Intn">rand.Intn</a></code> function.
|
||||
It returns a random integer up to (but not including) the provided
|
||||
value. Passing in <code>len(choices)</code> gives us a random index
|
||||
into the full length of the list.
|
||||
<br/><br/>
|
||||
We use that index to pick our new suffix, assign it to
|
||||
<code>next</code> and append it to the <code>words</code> slice.
|
||||
<br/><br/>
|
||||
Next, we <code>Shift</code> the new suffix onto the prefix just as
|
||||
we did in the <code>Build</code> method.
|
||||
</step>
|
||||
|
||||
<step title="Returning the generated text" src="doc/codewalk/markov.go:/Join\(words/">
|
||||
Before returning the generated text as a string, we use the
|
||||
<code>strings.Join</code> function to join the elements of
|
||||
the <code>words</code> slice together, separated by spaces.
|
||||
</step>
|
||||
|
||||
<step title="Command-line flags" src="doc/codewalk/markov.go:/Register command-line flags/,/prefixLen/">
|
||||
To make it easy to tweak the prefix and generated text lengths we
|
||||
use the <code><a href="/pkg/flag/">flag</a></code> package to parse
|
||||
command-line flags.
|
||||
<br/><br/>
|
||||
These calls to <code>flag.Int</code> register new flags with the
|
||||
<code>flag</code> package. The arguments to <code>Int</code> are the
|
||||
flag name, its default value, and a description. The <code>Int</code>
|
||||
function returns a pointer to an integer that will contain the
|
||||
user-supplied value (or the default value if the flag was omitted on
|
||||
the command-line).
|
||||
</step>
|
||||
|
||||
<step title="Program set up" src="doc/codewalk/markov.go:/flag.Parse/,/rand.Seed/">
|
||||
The <code>main</code> function begins by parsing the command-line
|
||||
flags with <code>flag.Parse</code> and seeding the <code>rand</code>
|
||||
package's random number generator with the current time.
|
||||
<br/><br/>
|
||||
If the command-line flags provided by the user are invalid the
|
||||
<code>flag.Parse</code> function will print an informative usage
|
||||
message and terminate the program.
|
||||
</step>
|
||||
|
||||
<step title="Creating and building a new Chain" src="doc/codewalk/markov.go:/c := NewChain/,/c\.Build/">
|
||||
To create the new <code>Chain</code> we call <code>NewChain</code>
|
||||
with the value of the <code>prefix</code> flag.
|
||||
<br/><br/>
|
||||
To build the chain we call <code>Build</code> with
|
||||
<code>os.Stdin</code> (which implements <code>io.Reader</code>) so
|
||||
that it will read its input from standard input.
|
||||
</step>
|
||||
|
||||
<step title="Generating and printing text" src="doc/codewalk/markov.go:/c\.Generate/,/fmt.Println/">
|
||||
Finally, to generate text we call <code>Generate</code> with
|
||||
the value of the <code>words</code> flag and assigning the result
|
||||
to the variable <code>text</code>.
|
||||
<br/><br/>
|
||||
Then we call <code>fmt.Println</code> to write the text to standard
|
||||
output, followed by a carriage return.
|
||||
</step>
|
||||
|
||||
<step title="Using this program" src="doc/codewalk/markov.go">
|
||||
To use this program, first build it with the
|
||||
<a href="/cmd/go/">go</a> command:
|
||||
<pre>
|
||||
$ go build markov.go</pre>
|
||||
And then execute it while piping in some input text:
|
||||
<pre>
|
||||
$ echo "a man a plan a canal panama" \
|
||||
| ./markov -prefix=1
|
||||
a plan a man a plan a canal panama</pre>
|
||||
Here's a transcript of generating some text using the Go distribution's
|
||||
README file as source material:
|
||||
<pre>
|
||||
$ ./markov -words=10 < $GOROOT/go/README
|
||||
This is the source code repository for the Go source
|
||||
$ ./markov -prefix=1 -words=10 < $GOROOT/go/README
|
||||
This is the go directory (the one containing this README).
|
||||
$ ./markov -prefix=1 -words=10 < $GOROOT/go/README
|
||||
This is the variable if you have just untarred a</pre>
|
||||
</step>
|
||||
|
||||
<step title="An exercise for the reader" src="doc/codewalk/markov.go">
|
||||
The <code>Generate</code> function does a lot of allocations when it
|
||||
builds the <code>words</code> slice. As an exercise, modify it to
|
||||
take an <code>io.Writer</code> to which it incrementally writes the
|
||||
generated text with <code>Fprint</code>.
|
||||
Aside from being more efficient this makes <code>Generate</code>
|
||||
more symmetrical to <code>Build</code>.
|
||||
</step>
|
||||
|
||||
</codewalk>
|
||||
@@ -6,7 +6,7 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"rand"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -61,6 +61,9 @@ func play(strategy0, strategy1 strategy) int {
|
||||
currentPlayer := rand.Intn(2) // Randomly decide who plays first
|
||||
for s.player+s.thisTurn < win {
|
||||
action := strategies[currentPlayer](s)
|
||||
if action != roll && action != stay {
|
||||
panic(fmt.Sprintf("Player %d is cheating", currentPlayer))
|
||||
}
|
||||
s, turnIsOver = action(s)
|
||||
if turnIsOver {
|
||||
currentPlayer = (currentPlayer + 1) % 2
|
||||
|
||||
@@ -65,7 +65,7 @@ and then loops passing completed Resources back to the pending
|
||||
channel after appropriate delays.
|
||||
</step>
|
||||
|
||||
<step title="Creating channels" src="doc/codewalk/urlpoll.go:/Create our/,/complete/">
|
||||
<step title="Creating channels" src="doc/codewalk/urlpoll.go:/create our/,/complete/">
|
||||
First, main makes two channels of *Resource, pending and complete.
|
||||
<br/><br/>
|
||||
Inside main, a new goroutine sends one Resource per URL to pending
|
||||
@@ -75,7 +75,7 @@ The pending and complete channels are passed to each of the Poller
|
||||
goroutines, within which they are known as in and out.
|
||||
</step>
|
||||
|
||||
<step title="Initializing StateMonitor" src="doc/codewalk/urlpoll.go:/Launch the StateMonitor/,/statusInterval/">
|
||||
<step title="Initializing StateMonitor" src="doc/codewalk/urlpoll.go:/launch the StateMonitor/,/statusInterval/">
|
||||
StateMonitor will initialize and launch a goroutine that stores the state
|
||||
of each Resource. We will look at this function in detail later.
|
||||
<br/><br/>
|
||||
@@ -83,14 +83,14 @@ For now, the important thing to note is that it returns a channel of State,
|
||||
which is saved as status and passed to the Poller goroutines.
|
||||
</step>
|
||||
|
||||
<step title="Launching Poller goroutines" src="doc/codewalk/urlpoll.go:/Launch some Poller/,/}/">
|
||||
<step title="Launching Poller goroutines" src="doc/codewalk/urlpoll.go:/launch some Poller/,/}/">
|
||||
Now that it has the necessary channels, main launches a number of
|
||||
Poller goroutines, passing the channels as arguments.
|
||||
The channels provide the means of communication between the main, Poller, and
|
||||
StateMonitor goroutines.
|
||||
</step>
|
||||
|
||||
<step title="Send Resources to pending" src="doc/codewalk/urlpoll.go:/Send some Resources/,/}\(\)/">
|
||||
<step title="Send Resources to pending" src="doc/codewalk/urlpoll.go:/send some Resources/,/}\(\)/">
|
||||
To add the initial work to the system, main starts a new goroutine
|
||||
that allocates and sends one Resource per URL to pending.
|
||||
<br/><br/>
|
||||
|
||||
@@ -5,16 +5,17 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"http"
|
||||
"log"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
numPollers = 2 // number of Poller goroutines to launch
|
||||
pollInterval = 60 * time.Second // how often to poll each URL
|
||||
statusInterval = 10 * time.Second // how often to log status to stdout
|
||||
errTimeout = 10 * time.Second // back-off timeout on error
|
||||
numPollers = 2 // number of Poller goroutines to launch
|
||||
second = 1e9 // one second is 1e9 nanoseconds
|
||||
pollInterval = 60 * second // how often to poll each URL
|
||||
statusInterval = 10 * second // how often to log status to stdout
|
||||
errTimeout = 10 * second // back-off timeout on error
|
||||
)
|
||||
|
||||
var urls = []string{
|
||||
@@ -32,7 +33,7 @@ type State struct {
|
||||
// StateMonitor maintains a map that stores the state of the URLs being
|
||||
// polled, and prints the current state every updateInterval nanoseconds.
|
||||
// It returns a chan State to which resource state should be sent.
|
||||
func StateMonitor(updateInterval time.Duration) chan<- State {
|
||||
func StateMonitor(updateInterval int64) chan<- State {
|
||||
updates := make(chan State)
|
||||
urlStatus := make(map[string]string)
|
||||
ticker := time.NewTicker(updateInterval)
|
||||
@@ -60,7 +61,7 @@ func logState(s map[string]string) {
|
||||
// Resource represents an HTTP URL to be polled by this program.
|
||||
type Resource struct {
|
||||
url string
|
||||
errCount int
|
||||
errCount int64
|
||||
}
|
||||
|
||||
// Poll executes an HTTP HEAD request for url
|
||||
@@ -70,7 +71,7 @@ func (r *Resource) Poll() string {
|
||||
if err != nil {
|
||||
log.Println("Error", r.url, err)
|
||||
r.errCount++
|
||||
return err.Error()
|
||||
return err.String()
|
||||
}
|
||||
r.errCount = 0
|
||||
return resp.Status
|
||||
@@ -78,8 +79,8 @@ func (r *Resource) Poll() string {
|
||||
|
||||
// Sleep sleeps for an appropriate interval (dependant on error state)
|
||||
// before sending the Resource to done.
|
||||
func (r *Resource) Sleep(done chan<- *Resource) {
|
||||
time.Sleep(pollInterval + errTimeout*time.Duration(r.errCount))
|
||||
func (r *Resource) Sleep(done chan *Resource) {
|
||||
time.Sleep(pollInterval + errTimeout*r.errCount)
|
||||
done <- r
|
||||
}
|
||||
|
||||
@@ -92,18 +93,18 @@ func Poller(in <-chan *Resource, out chan<- *Resource, status chan<- State) {
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Create our input and output channels.
|
||||
// create our input and output channels
|
||||
pending, complete := make(chan *Resource), make(chan *Resource)
|
||||
|
||||
// Launch the StateMonitor.
|
||||
// launch the StateMonitor
|
||||
status := StateMonitor(statusInterval)
|
||||
|
||||
// Launch some Poller goroutines.
|
||||
// launch some Poller goroutines
|
||||
for i := 0; i < numPollers; i++ {
|
||||
go Poller(pending, complete, status)
|
||||
}
|
||||
|
||||
// Send some Resources to the pending queue.
|
||||
// send some Resources to the pending queue
|
||||
go func() {
|
||||
for _, url := range urls {
|
||||
pending <- &Resource{url: url}
|
||||
|
||||
53
doc/community.html
Normal file
@@ -0,0 +1,53 @@
|
||||
<!-- title Community -->
|
||||
|
||||
<div class="left-column">
|
||||
|
||||
<h2 id="developer_info">The Go Community</h2>
|
||||
|
||||
<h3 id="mailinglist"><a href="http://groups.google.com/group/golang-nuts">Go Nuts Mailing List</a></h3>
|
||||
<p>The <a href="http://groups.google.com/group/golang-nuts">golang-nuts</a>
|
||||
mailing list is for general Go discussion.</p>
|
||||
|
||||
<h3 id=""><a href="http://godashboard.appspot.com/package">Go Packages Dashboard</a></h3>
|
||||
<p>A list of the most popular <a href="/cmd/goinstall/">goinstall</a>'d
|
||||
Go libraries.</p>
|
||||
|
||||
<h3 id=""><a href="http://godashboard.appspot.com/project">Go Project Dashboard</a></h3>
|
||||
<p>A list of external Go projects including programs and libraries.</p>
|
||||
|
||||
<h3 id="irc"><a href="irc:irc.freenode.net/go-nuts">Go IRC Channel</a></h3>
|
||||
<p><b>#go-nuts</b> on <b>irc.freenode.net</b> is the official Go IRC channel.</p>
|
||||
|
||||
<h3 id="twitter"><a href="http://twitter.com/go_nuts">@go_nuts at Twitter</a></h3>
|
||||
<p>The Go project's official Twitter account.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="right-column">
|
||||
|
||||
<h2 id="blogs">Blogs</h2>
|
||||
|
||||
<h3 id="blog_go"><a href="http://blog.golang.org/">The Go Blog</a></h3>
|
||||
<p>
|
||||
The Go project's official blog, maintained by the core Go developers.
|
||||
</p>
|
||||
|
||||
<h3 id="blog_rsc"><a href="http://research.swtch.com/search/label/Go">research!rsc</a></h3>
|
||||
<p>
|
||||
Posts labelled 'Go' by Russ Cox, one of the core Go developers.
|
||||
</p>
|
||||
|
||||
<h3 id="blog_iant"><a href="http://www.airs.com/blog/archives/category/programming">Airs</a></h3>
|
||||
<p>
|
||||
Posts labelled 'Programming' by Ian Lance Taylor, one of the core Go developers.
|
||||
</p>
|
||||
|
||||
<h3 id="blog_adg"><a href="http://nf.id.au/tag/go">nf.id.au</a></h3>
|
||||
<p>
|
||||
Posts labelled 'Go' by Andrew Gerrand, one of the core Go developers.
|
||||
</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="end-columns"></div>
|
||||
|
||||
@@ -1,55 +1,6 @@
|
||||
<!--{
|
||||
"Title": "The Go Project",
|
||||
"Path": "/project/"
|
||||
}-->
|
||||
|
||||
<img class="gopher" src="/doc/gopher/project.png" />
|
||||
|
||||
<div id="manual-nav"></div>
|
||||
|
||||
<p>
|
||||
Go is an open source project developed by a team at
|
||||
<a href="http://google.com/">Google</a> and many
|
||||
<a href="/CONTRIBUTORS">contributors</a> from the open source community.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Go is distributed under a <a href="/LICENSE">BSD-style license</a>.
|
||||
</p>
|
||||
|
||||
<h3 id="announce"><a href="http://groups.google.com/group/golang-announce">Announcements Mailing List</a></h3>
|
||||
<p>
|
||||
A low traffic mailing list for important announcements, such as new releases.
|
||||
</p>
|
||||
<p>
|
||||
We encourage all Go users to subscribe to
|
||||
<a href="http://groups.google.com/group/golang-announce">golang-announce</a>.
|
||||
</p>
|
||||
|
||||
<h2 id="resources">Developer Resources</h2>
|
||||
|
||||
<h3 id="source"><a href="https://code.google.com/p/go/source">Source Code</a></h3>
|
||||
<p>Check out the Go source code.</p>
|
||||
|
||||
<h3 id="release"><a href="/doc/devel/release.html">Release History</a></h3>
|
||||
<p>A summary of the changes between Go releases.</p>
|
||||
|
||||
<h3 id="weekly"><a href="/doc/devel/weekly.html">Weekly Snapshot History</a></h3>
|
||||
<p>A summary of the changes between weekly snapshots of Go.</p>
|
||||
|
||||
<h3 id="golang-dev"><a href="http://groups.google.com/group/golang-dev">Developer Mailing List</a></h3>
|
||||
<p>The <a href="http://groups.google.com/group/golang-dev">golang-dev</a>
|
||||
mailing list is for discussing and reviewing code for the Go project.</p>
|
||||
<p>For general discussion of Go programming, see <a
|
||||
href="http://groups.google.com/group/golang-nuts">golang-nuts</a>.</p>
|
||||
|
||||
<h3 id="golang-checkins"><a href="http://groups.google.com/group/golang-checkins">Checkins Mailing List</a></h3>
|
||||
<p>A mailing list that receives a message summarizing each checkin to the Go repository.</p>
|
||||
|
||||
<h3 id="build_status"><a href="http://build.golang.org/">Build Status</a></h3>
|
||||
<p>View the status of Go builds across the supported operating
|
||||
systems and architectures.</p>
|
||||
<!-- title Contributing -->
|
||||
|
||||
<div class="left-column">
|
||||
|
||||
<h2 id="howto">How you can help</h2>
|
||||
|
||||
@@ -68,13 +19,13 @@ a new one.)
|
||||
We pride ourselves on being meticulous; no issue is too small.
|
||||
</p>
|
||||
|
||||
<h3><a href="/doc/contribute.html">Contributing code</a></h3>
|
||||
<h3><a href="contribute.html">Contributing code</a></h3>
|
||||
|
||||
<p>
|
||||
Go is an open source project and we welcome contributions from the community.
|
||||
</p>
|
||||
<p>
|
||||
To get started, read these <a href="/doc/contribute.html">contribution
|
||||
To get started, read these <a href="contribute.html">contribution
|
||||
guidelines</a> for information on design, testing, and our code review process.
|
||||
</p>
|
||||
<p>
|
||||
@@ -84,25 +35,35 @@ open issues that interest you. Those labeled
|
||||
are particularly in need of outside help.
|
||||
</p>
|
||||
|
||||
</div>
|
||||
|
||||
<h2 id="community">The Go Community</h2>
|
||||
<div class="right-column">
|
||||
|
||||
<h3 id="mailinglist"><a href="http://groups.google.com/group/golang-nuts">Go Nuts Mailing List</a></h3>
|
||||
<p>The <a href="http://groups.google.com/group/golang-nuts">golang-nuts</a>
|
||||
mailing list is for general Go discussion.</p>
|
||||
<h2 id="the_go_project">The Go Project</h2>
|
||||
|
||||
<h3 id="projects"><a href="http://godashboard.appspot.com/project">Go Project Dashboard</a></h3>
|
||||
<p>A list of external Go projects including programs and libraries.</p>
|
||||
<h3 id="build_status"><a href="http://godashboard.appspot.com/">Build Status</a></h3>
|
||||
<p>View the status of Go builds across the supported operating
|
||||
systems and architectures.</p>
|
||||
|
||||
<h3 id="irc"><a href="irc:irc.freenode.net/go-nuts">Go IRC Channel</a></h3>
|
||||
<p><b>#go-nuts</b> on <b>irc.freenode.net</b> is the official Go IRC channel.</p>
|
||||
<h3 id="roadmap"><a href="devel/roadmap.html">Roadmap</a></h3>
|
||||
<p>Features and ideas being developed or discussed by the Go team.</p>
|
||||
|
||||
<h3 id="plus"><a href="https://plus.google.com/101406623878176903605/posts">The Go Programming Language at Google+</a></h3>
|
||||
<p>The Go project's Google+ page.</p>
|
||||
<h3 id="release"><a href="devel/release.html">Release History</a></h3>
|
||||
<p>A summary of the changes between Go releases.</p>
|
||||
|
||||
<h3 id="twitter"><a href="http://twitter.com/go_nuts">@go_nuts at Twitter</a></h3>
|
||||
<p>The Go project's official Twitter account.</p>
|
||||
<h3 id="release"><a href="devel/weekly.html">Weekly Snapshot History</a></h3>
|
||||
<p>A summary of the changes between weekly snapshots of Go.</p>
|
||||
|
||||
<h3 id="golang-dev"><a href="http://groups.google.com/group/golang-dev">Developer Mailing List</a></h3>
|
||||
<p>The <a href="http://groups.google.com/group/golang-dev">golang-dev</a>
|
||||
mailing list is for discussing and reviewing code for the Go project.</p>
|
||||
<p>For general discussion of Go programming, see <a
|
||||
href="http://groups.google.com/group/golang-nuts">golang-nuts</a>.</p>
|
||||
|
||||
<h3 id="golang-checkins"><a href="http://groups.google.com/group/golang-checkins">Checkins Mailing List</a></h3>
|
||||
<p>A mailing list that receives a message summarizing each checkin to the Go repository.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="end-columns"></div>
|
||||
|
||||
<h3 id="blog"><a href="http://blog.golang.org/">The Go Blog</a></h3>
|
||||
<p>The official blog of the Go project, featuring news and in-depth articles by
|
||||
the Go team and guests.</p>
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
<!--{
|
||||
"Title": "Contribution Guidelines"
|
||||
}-->
|
||||
<!-- Contribution Guidelines -->
|
||||
|
||||
<h2 id="Introduction">Introduction</h2>
|
||||
|
||||
<p>
|
||||
This document explains how to contribute changes to the Go project.
|
||||
It assumes you have installed Go using the
|
||||
<a href="/doc/install">installation instructions</a> and
|
||||
<a href="install.html">installation instructions</a> and
|
||||
have <a href="code.html">written and tested your code</a>.
|
||||
(Note that the <code>gccgo</code> frontend lives elsewhere;
|
||||
see <a href="gccgo_contribute.html">Contributing to gccgo</a>.)
|
||||
@@ -212,10 +210,10 @@ to this change, and the <code>CC</code> line lists people to
|
||||
notify about the change.
|
||||
These can be code review nicknames or arbitrary email addresses.
|
||||
Unless explicitly told otherwise, such as in the discussion leading
|
||||
up to sending in the change list, leave the reviewer field blank.
|
||||
This means that the
|
||||
up to sending in the change list, set the
|
||||
reviewer field to the
|
||||
<a href="http://groups.google.com/group/golang-dev">golang-dev@googlegroups.com</a>
|
||||
mailing list will be used as the reviewer.
|
||||
mailing list.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
@@ -404,7 +402,7 @@ $ hg mail -r golang-dev@googlegroups.com --cc math-nuts@swtch.com 99999
|
||||
|
||||
<p>
|
||||
Running <code>hg mail</code> will send an email to you and the reviewers
|
||||
asking them to visit the issue's URL and make comments on the change.
|
||||
asking them to visit the issue's URL and make coments on the change.
|
||||
When done, the reviewer clicks “Publish and Mail comments”
|
||||
to send comments back.
|
||||
</p>
|
||||
@@ -525,7 +523,7 @@ This rigmarole needs to be done only for your first submission.
|
||||
<p>Code that you contribute should use the standard copyright header:</p>
|
||||
|
||||
<pre>
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Copyright 2011 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
</pre>
|
||||
|
||||
@@ -1,483 +0,0 @@
|
||||
<!--{
|
||||
"Title": "Debugging Go Code with GDB",
|
||||
"Path": "/doc/gdb"
|
||||
}-->
|
||||
|
||||
<p><i>
|
||||
This applies to the <code>gc</code> toolchain. Gccgo has native gdb support.
|
||||
Besides this overview you might want to consult the
|
||||
<a href="http://sourceware.org/gdb/current/onlinedocs/gdb/">GDB manual</a>.
|
||||
</i></p>
|
||||
|
||||
<h2 id="Introduction">Introduction</h2>
|
||||
|
||||
<p>
|
||||
When you compile and link your Go programs with the <code>gc</code> toolchain
|
||||
on Linux, Mac OS X or FreeBSD, the resulting binaries contain DWARFv3
|
||||
debugging information that recent versions (>7.1) of the GDB debugger can
|
||||
use to inspect a live process or a core dump.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Pass the <code>'-s'</code> flag to the linker to omit the debug information
|
||||
(for example, <code>go build -ldflags "-s" prog.go</code>).
|
||||
</p>
|
||||
|
||||
|
||||
<h3 id="Common_Operations">Common Operations</h3>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
Show file and line number for code
|
||||
, set breakpoints and disassemble:
|
||||
<pre>(gdb) <b>list</b>
|
||||
(gdb) <b>list <i>line</i></b>
|
||||
(gdb) <b>list <i>file.go</i>:<i>line</i></b>
|
||||
(gdb) <b>break <i>line</i></b>
|
||||
(gdb) <b>break <i>file.go</i>:<i>line</i></b>
|
||||
(gdb) <b>disas</b></pre>
|
||||
</li>
|
||||
<li>
|
||||
Show backtraces and unwind stack frames:
|
||||
<pre>(gdb) <b>bt</b>
|
||||
(gdb) <b>frame <i>n</i></b></pre>
|
||||
</li>
|
||||
<li>
|
||||
Show the name, type and location on the stack frame of local variables,
|
||||
arguments and return values:
|
||||
<pre>(gdb) <b>info locals</b>
|
||||
(gdb) <b>info args</b>
|
||||
(gdb) <b>p variable</b>
|
||||
(gdb) <b>whatis variable</b></pre>
|
||||
</li>
|
||||
<li>
|
||||
Show the name, type and location of global variables:
|
||||
<pre>(gdb) <b>info variables <i>regexp</i></b></pre>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h3 id="Go_Extensions">Go Extensions</h3>
|
||||
|
||||
<p>
|
||||
A recent extension mechanism to GDB allows it to load extension scripts for a
|
||||
given binary. The tool chain uses this to extend GDB with a handful of
|
||||
commands to inspect internals of the runtime code (such as goroutines) and to
|
||||
pretty print the built-in map, slice and channel types.
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
Pretty printing a string, slice, map, channel or interface:
|
||||
<pre>(gdb) <b>p <i>var</i></b></pre>
|
||||
</li>
|
||||
<li>
|
||||
A $len() and $cap() function for strings, slices and maps:
|
||||
<pre>(gdb) <b>p $len(<i>var</i>)</b></pre>
|
||||
</li>
|
||||
<li>
|
||||
A function to cast interfaces to their dynamic types:
|
||||
<pre>(gdb) <b>p $dtype(<i>var</i>)</b>
|
||||
(gdb) <b>iface <i>var</i></b></pre>
|
||||
<p class="detail"><b>Known issue:</b> GDB can’t automatically find the dynamic
|
||||
type of an interface value if its long name differs from its short name
|
||||
(annoying when printing stacktraces, the pretty printer falls back to printing
|
||||
the short type name and a pointer).</p>
|
||||
</li>
|
||||
<li>
|
||||
Inspecting goroutines:
|
||||
<pre>(gdb) <b>info goroutines</b>
|
||||
(gdb) <b>goroutine <i>n</i> <i>cmd</i></b>
|
||||
(gdb) <b>help goroutine</b></pre>
|
||||
For example:
|
||||
<pre>(gdb) <b>goroutine 12 bt</b></pre>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
If you'd like to see how this works, or want to extend it, take a look at <a
|
||||
href="/src/pkg/runtime/runtime-gdb.py">src/pkg/runtime/runtime-gdb.py</a> in
|
||||
the Go source distribution. It depends on some special magic types
|
||||
(<code>hash<T,U></code>) and variables (<code>runtime.m</code> and
|
||||
<code>runtime.g</code>) that the linker
|
||||
(<a href="/src/cmd/ld/dwarf.c">src/cmd/ld/dwarf.c</a>) ensures are described in
|
||||
the DWARF code.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
If you're interested in what the debugging information looks like, run
|
||||
'<code>objdump -W 6.out</code>' and browse through the <code>.debug_*</code>
|
||||
sections.
|
||||
</p>
|
||||
|
||||
|
||||
<h3 id="Known_Issues">Known Issues</h3>
|
||||
|
||||
<ol>
|
||||
<li>String pretty printing only triggers for type string, not for types derived
|
||||
from it.</li>
|
||||
<li>Type information is missing for the C parts of the runtime library.</li>
|
||||
<li>GDB does not understand Go’s name qualifications and treats
|
||||
<code>"fmt.Print"</code> as an unstructured literal with a <code>"."</code>
|
||||
that needs to be quoted. It objects even more strongly to method names of
|
||||
the form <code>pkg.(*MyType).Meth</code>.
|
||||
<li>All global variables are lumped into package <code>"main"</code>.</li>
|
||||
</ol>
|
||||
|
||||
<h2 id="Tutorial">Tutorial</h2>
|
||||
|
||||
<p>
|
||||
In this tutorial we will inspect the binary of the
|
||||
<a href="/pkg/regexp/">regexp</a> package's unit tests. To build the binary,
|
||||
change to <code>$GOROOT/src/pkg/regexp</code> and run <code>go test -c</code>.
|
||||
This should produce an executable file named <code>regexp.test</code>.
|
||||
</p>
|
||||
|
||||
|
||||
<h3 id="Getting_Started">Getting Started</h3>
|
||||
|
||||
<p>
|
||||
Launch GDB, debugging <code>regexp.test</code>:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
$ <b>gdb regexp.test</b>
|
||||
GNU gdb (GDB) 7.2-gg8
|
||||
Copyright (C) 2010 Free Software Foundation, Inc.
|
||||
License GPLv 3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
|
||||
Type "show copying" and "show warranty" for licensing/warranty details.
|
||||
This GDB was configured as "x86_64-linux".
|
||||
|
||||
Reading symbols from /home/user/go/src/pkg/regexp/regexp.test...
|
||||
done.
|
||||
Loading Go Runtime support.
|
||||
(gdb)
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
The message <code>"Loading Go Runtime support"</code> means that GDB loaded the
|
||||
extension from <code>$GOROOT/src/pkg/runtime/runtime-gdb.py</code>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
To help GDB find the Go runtime sources and the accompanying support script,
|
||||
pass your <code>$GOROOT</code> with the <code>'-d'</code> flag:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
$ <b>gdb regexp.test -d $GOROOT</b>
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
If for some reason GDB still can't find that directory or that script, you can load
|
||||
it by hand by telling gdb (assuming you have the go sources in
|
||||
<code>~/go/</code>):
|
||||
<p>
|
||||
|
||||
<pre>
|
||||
(gdb) <b>source ~/go/src/pkg/runtime/runtime-gdb.py</b>
|
||||
Loading Go Runtime support.
|
||||
</pre>
|
||||
|
||||
<h3 id="Inspecting_the_source">Inspecting the source</h3>
|
||||
|
||||
<p>
|
||||
Use the <code>"l"</code> or <code>"list"</code> command to inspect source code.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
(gdb) <b>l</b>
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
List a specific part of the source parametrizing <code>"list"</code> with a
|
||||
function name (it must be qualified with its package name).
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
(gdb) <b>l main.main</b>
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
List a specific file and line number:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
(gdb) <b>l regexp.go:1</b>
|
||||
(gdb) <i># Hit enter to repeat last command. Here, this lists next 10 lines.</i>
|
||||
</pre>
|
||||
|
||||
|
||||
<h3 id="Naming">Naming</h3>
|
||||
|
||||
<p>
|
||||
Variable and function names must be qualified with the name of the packages
|
||||
they belong to. The <code>Compile</code> function from the <code>regexp</code>
|
||||
package is known to GDB as <code>'regexp.Compile'</code>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Methods must be qualified with the name of their receiver types. For example,
|
||||
the <code>*Regexp</code> type’s <code>String</code> method is known as
|
||||
<code>'regexp.(*Regexp).String'</code>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Variables that shadow other variables are magically suffixed with a number in the debug info.
|
||||
Variables referenced by closures will appear as pointers magically prefixed with '&'.
|
||||
</p>
|
||||
|
||||
<h3 id="Setting_breakpoints">Setting breakpoints</h3>
|
||||
|
||||
<p>
|
||||
Set a breakpoint at the <code>TestFind</code> function:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
(gdb) <b>b 'regexp.TestFind'</b>
|
||||
Breakpoint 1 at 0x424908: file /home/user/go/src/pkg/regexp/find_test.go, line 148.
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Run the program:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
(gdb) <b>run</b>
|
||||
Starting program: /home/user/go/src/pkg/regexp/regexp.test
|
||||
|
||||
Breakpoint 1, regexp.TestFind (t=0xf8404a89c0) at /home/user/go/src/pkg/regexp/find_test.go:148
|
||||
148 func TestFind(t *testing.T) {
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Execution has paused at the breakpoint.
|
||||
See which goroutines are running, and what they're doing:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
(gdb) <b>info goroutines</b>
|
||||
1 waiting runtime.gosched
|
||||
* 13 running runtime.goexit
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
the one marked with the <code>*</code> is the current goroutine.
|
||||
</p>
|
||||
|
||||
<h3 id="Inspecting_the_stack">Inspecting the stack</h3>
|
||||
|
||||
<p>
|
||||
Look at the stack trace for where we’ve paused the program:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
(gdb) <b>bt</b> <i># backtrace</i>
|
||||
#0 regexp.TestFind (t=0xf8404a89c0) at /home/user/go/src/pkg/regexp/find_test.go:148
|
||||
#1 0x000000000042f60b in testing.tRunner (t=0xf8404a89c0, test=0x573720) at /home/user/go/src/pkg/testing/testing.go:156
|
||||
#2 0x000000000040df64 in runtime.initdone () at /home/user/go/src/pkg/runtime/proc.c:242
|
||||
#3 0x000000f8404a89c0 in ?? ()
|
||||
#4 0x0000000000573720 in ?? ()
|
||||
#5 0x0000000000000000 in ?? ()
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
The other goroutine, number 1, is stuck in <code>runtime.gosched</code>, blocked on a channel receive:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
(gdb) <b>goroutine 1 bt</b>
|
||||
#0 0x000000000040facb in runtime.gosched () at /home/user/go/src/pkg/runtime/proc.c:873
|
||||
#1 0x00000000004031c9 in runtime.chanrecv (c=void, ep=void, selected=void, received=void)
|
||||
at /home/user/go/src/pkg/runtime/chan.c:342
|
||||
#2 0x0000000000403299 in runtime.chanrecv1 (t=void, c=void) at/home/user/go/src/pkg/runtime/chan.c:423
|
||||
#3 0x000000000043075b in testing.RunTests (matchString={void (struct string, struct string, bool *, error *)}
|
||||
0x7ffff7f9ef60, tests= []testing.InternalTest = {...}) at /home/user/go/src/pkg/testing/testing.go:201
|
||||
#4 0x00000000004302b1 in testing.Main (matchString={void (struct string, struct string, bool *, error *)}
|
||||
0x7ffff7f9ef80, tests= []testing.InternalTest = {...}, benchmarks= []testing.InternalBenchmark = {...})
|
||||
at /home/user/go/src/pkg/testing/testing.go:168
|
||||
#5 0x0000000000400dc1 in main.main () at /home/user/go/src/pkg/regexp/_testmain.go:98
|
||||
#6 0x00000000004022e7 in runtime.mainstart () at /home/user/go/src/pkg/runtime/amd64/asm.s:78
|
||||
#7 0x000000000040ea6f in runtime.initdone () at /home/user/go/src/pkg/runtime/proc.c:243
|
||||
#8 0x0000000000000000 in ?? ()
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
The stack frame shows we’re currently executing the <code>regexp.TestFind</code> function, as expected.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
(gdb) <b>info frame</b>
|
||||
Stack level 0, frame at 0x7ffff7f9ff88:
|
||||
rip = 0x425530 in regexp.TestFind (/home/user/go/src/pkg/regexp/find_test.go:148);
|
||||
saved rip 0x430233
|
||||
called by frame at 0x7ffff7f9ffa8
|
||||
source language minimal.
|
||||
Arglist at 0x7ffff7f9ff78, args: t=0xf840688b60
|
||||
Locals at 0x7ffff7f9ff78, Previous frame's sp is 0x7ffff7f9ff88
|
||||
Saved registers:
|
||||
rip at 0x7ffff7f9ff80
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
The command <code>info locals</code> lists all variables local to the function and their values, but is a bit
|
||||
dangerous to use, since it will also try to print uninitialized variables. Uninitialized slices may cause gdb to try
|
||||
to print arbitrary large arrays.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The function’s arguments:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
(gdb) <b>info args</b>
|
||||
t = 0xf840688b60
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
When printing the argument, notice that it’s a pointer to a
|
||||
<code>Regexp</code> value. Note that GDB has incorrectly put the <code>*</code>
|
||||
on the right-hand side of the type name and made up a 'struct' keyword, in traditional C style.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
(gdb) <b>p re</b>
|
||||
(gdb) p t
|
||||
$1 = (struct testing.T *) 0xf840688b60
|
||||
(gdb) p t
|
||||
$1 = (struct testing.T *) 0xf840688b60
|
||||
(gdb) p *t
|
||||
$2 = {errors = "", failed = false, ch = 0xf8406f5690}
|
||||
(gdb) p *t->ch
|
||||
$3 = struct hchan<*testing.T>
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
That <code>struct hchan<*testing.T></code> is the runtime-internal representation of a channel. It is currently empty, or gdb would have pretty-printed it's contents.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Stepping forward:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
(gdb) <b>n</b> <i># execute next line</i>
|
||||
149 for _, test := range findTests {
|
||||
(gdb) <i># enter is repeat</i>
|
||||
150 re := MustCompile(test.pat)
|
||||
(gdb) <b>p test.pat</b>
|
||||
$4 = ""
|
||||
(gdb) <b>p re</b>
|
||||
$5 = (struct regexp.Regexp *) 0xf84068d070
|
||||
(gdb) <b>p *re</b>
|
||||
$6 = {expr = "", prog = 0xf840688b80, prefix = "", prefixBytes = []uint8, prefixComplete = true,
|
||||
prefixRune = 0, cond = 0 '\000', numSubexp = 0, longest = false, mu = {state = 0, sema = 0},
|
||||
machine = []*regexp.machine}
|
||||
(gdb) <b>p *re->prog</b>
|
||||
$7 = {Inst = []regexp/syntax.Inst = {{Op = 5 '\005', Out = 0, Arg = 0, Rune = []int}, {Op =
|
||||
6 '\006', Out = 2, Arg = 0, Rune = []int}, {Op = 4 '\004', Out = 0, Arg = 0, Rune = []int}},
|
||||
Start = 1, NumCap = 2}
|
||||
</pre>
|
||||
|
||||
|
||||
<p>
|
||||
We can step into the <code>String</code>function call with <code>"s"</code>:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
(gdb) <b>s</b>
|
||||
regexp.(*Regexp).String (re=0xf84068d070, noname=void) at /home/user/go/src/pkg/regexp/regexp.go:97
|
||||
97 func (re *Regexp) String() string {
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Get a stack trace to see where we are:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
(gdb) <b>bt</b>
|
||||
#0 regexp.(*Regexp).String (re=0xf84068d070, noname=void)
|
||||
at /home/user/go/src/pkg/regexp/regexp.go:97
|
||||
#1 0x0000000000425615 in regexp.TestFind (t=0xf840688b60)
|
||||
at /home/user/go/src/pkg/regexp/find_test.go:151
|
||||
#2 0x0000000000430233 in testing.tRunner (t=0xf840688b60, test=0x5747b8)
|
||||
at /home/user/go/src/pkg/testing/testing.go:156
|
||||
#3 0x000000000040ea6f in runtime.initdone () at /home/user/go/src/pkg/runtime/proc.c:243
|
||||
....
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Look at the source code:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
(gdb) <b>l</b>
|
||||
92 mu sync.Mutex
|
||||
93 machine []*machine
|
||||
94 }
|
||||
95
|
||||
96 // String returns the source text used to compile the regular expression.
|
||||
97 func (re *Regexp) String() string {
|
||||
98 return re.expr
|
||||
99 }
|
||||
100
|
||||
101 // Compile parses a regular expression and returns, if successful,
|
||||
</pre>
|
||||
|
||||
<h3 id="Pretty_Printing">Pretty Printing</h3>
|
||||
|
||||
<p>
|
||||
GDB's pretty printing mechanism is triggered by regexp matches on type names. An example for slices:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
(gdb) <b>p utf</b>
|
||||
$22 = []uint8 = {0 '\000', 0 '\000', 0 '\000', 0 '\000'}
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Since slices, arrays and strings are not C pointers, GDB can't interpret the subscripting operation for you, but
|
||||
you can look inside the runtime representation to do that (tab completion helps here):
|
||||
</p>
|
||||
<pre>
|
||||
|
||||
(gdb) <b>p slc</b>
|
||||
$11 = []int = {0, 0}
|
||||
(gdb) <b>p slc-></b><i><TAB></i>
|
||||
array slc len
|
||||
(gdb) <b>p slc->array</b>
|
||||
$12 = (int *) 0xf84057af00
|
||||
(gdb) <b>p slc->array[1]</b>
|
||||
$13 = 0</pre>
|
||||
|
||||
|
||||
|
||||
<p>
|
||||
The extension functions $len and $cap work on strings, arrays and slices:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
(gdb) <b>p $len(utf)</b>
|
||||
$23 = 4
|
||||
(gdb) <b>p $cap(utf)</b>
|
||||
$24 = 4
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Channels and maps are 'reference' types, which gdb shows as pointers to C++-like types <code>hash<int,string>*</code>. Dereferencing will trigger prettyprinting
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Interfaces are represented in the runtime as a pointer to a type descriptor and a pointer to a value. The Go GDB runtime extension decodes this and automatically triggers pretty printing for the runtime type. The extension function <code>$dtype</code> decodes the dynamic type for you (examples are taken from a breakpoint at <code>regexp.go</code> line 293.)
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
(gdb) <b>p i</b>
|
||||
$4 = {str = "cbb"}
|
||||
(gdb) <b>whatis i</b>
|
||||
type = regexp.input
|
||||
(gdb) <b>p $dtype(i)</b>
|
||||
$26 = (struct regexp.inputBytes *) 0xf8400b4930
|
||||
(gdb) <b>iface i</b>
|
||||
regexp.input: struct regexp.inputBytes *
|
||||
</pre>
|
||||
11
doc/devel/index.html
Normal file
@@ -0,0 +1,11 @@
|
||||
<!-- The Go project -->
|
||||
|
||||
<ul>
|
||||
<li><a href="roadmap.html">Roadmap</a></li>
|
||||
<li><a href="release.html">Release history</a></li>
|
||||
<li><a href="weekly.html">Weekly snapshot history</a></li>
|
||||
<li><a href="http://godashboard.appspot.com">Build and benchmark status</a></li>
|
||||
</ul>
|
||||
<ul>
|
||||
<li><a href="../contribute.html">Contributing code</a></li>
|
||||
</ul>
|
||||
@@ -1,6 +1,4 @@
|
||||
<!--{
|
||||
"Title": "Release History"
|
||||
}-->
|
||||
<!-- Release History -->
|
||||
|
||||
<p>This page summarizes the changes between official stable releases of Go.
|
||||
Between releases we issue less stable
|
||||
@@ -13,129 +11,9 @@ has full details.</p>
|
||||
|
||||
<pre>
|
||||
hg pull
|
||||
hg update <i>tag</i>
|
||||
hg update release.r<i>NN</i>
|
||||
</pre>
|
||||
|
||||
<h2 id="go1">go1 (released 2012/03/28)</h2>
|
||||
|
||||
<p>
|
||||
Go 1 is a major release of Go that will be stable in the long term.
|
||||
Read the <a href="/doc/go1.html">Go 1 Release Notes</a> for more information.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
It is intended that programs written for Go 1 will continue to compile and run
|
||||
correctly, unchanged, under future versions of Go 1.
|
||||
Read the <a href="/doc/go1compat.html">Go 1 compatibility document</a> for more
|
||||
about the future of Go 1.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The go1 release corresponds to
|
||||
<code><a href="weekly.html#2012-03-27">weekly.2012-03-27</a></code>.
|
||||
</p>
|
||||
|
||||
<h2 id="r60">r60 (released 2011/09/07)</h2>
|
||||
|
||||
<p>
|
||||
The r60 release corresponds to
|
||||
<code><a href="weekly.html#2011-08-17">weekly.2011-08-17</a></code>.
|
||||
This section highlights the most significant changes in this release.
|
||||
For a more detailed summary, see the
|
||||
<a href="weekly.html#2011-08-17">weekly release notes</a>.
|
||||
For complete information, see the
|
||||
<a href="http://code.google.com/p/go/source/list?r=release-branch.r60">Mercurial change list</a>.
|
||||
</p>
|
||||
|
||||
<h3 id="r60.lang">Language</h3>
|
||||
|
||||
<p>
|
||||
An "else" block is now required to have braces except if the body of the "else"
|
||||
is another "if". Since gofmt always puts those braces in anyway,
|
||||
gofmt-formatted programs will not be affected.
|
||||
To fix other programs, run gofmt.
|
||||
</p>
|
||||
|
||||
<h3 id="r60.pkg">Packages</h3>
|
||||
|
||||
<p>
|
||||
<a href="/pkg/http/">Package http</a>'s URL parsing and query escaping code
|
||||
(such as <code>ParseURL</code> and <code>URLEscape</code>) has been moved to
|
||||
the new <a href="/pkg/url/">url package</a>, with several simplifications to
|
||||
the names. Client code can be updated automatically with gofix.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<a href="/pkg/image/">Package image</a> has had significant changes made to the
|
||||
<code>Pix</code> field of struct types such as
|
||||
<a href="/pkg/image/#RGBA">image.RGBA</a> and
|
||||
<a href="/pkg/image/#NRGBA">image.NRGBA</a>.
|
||||
The <a href="/pkg/image/#Image">image.Image</a> interface type has not changed,
|
||||
though, and you should not need to change your code if you don't explicitly
|
||||
refer to <code>Pix</code> fields. For example, if you decode a number of images
|
||||
using the <a href="/pkg/image/jpeg/">image/jpeg</a> package, compose them using
|
||||
<a href="/pkg/image/draw/">image/draw</a>, and then encode the result using
|
||||
<a href="/pkg/img/png">image/png</a>, then your code should still work as
|
||||
before.
|
||||
If your code <i>does</i> refer to <code>Pix</code> fields see the
|
||||
<a href="/doc/devel/weekly.html#2011-07-19">weekly.2011-07-19</a>
|
||||
snapshot notes for how to update your code.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<a href="/pkg/template/">Package template</a> has been replaced with a new
|
||||
templating package (formerly <code>exp/template</code>). The original template
|
||||
package is still available as <a href="/pkg/old/template/">old/template</a>.
|
||||
The <code>old/template</code> package is deprecated and will be removed.
|
||||
The Go tree has been updated to use the new template package. We encourage
|
||||
users of the old template package to switch to the new one. Code that uses
|
||||
<code>template</code> or <code>exp/template</code> will need to change its
|
||||
import lines to <code>"old/template"</code> or <code>"template"</code>,
|
||||
respectively.
|
||||
</p>
|
||||
|
||||
<h3 id="r60.cmd">Tools</h3>
|
||||
|
||||
<p>
|
||||
<a href="/cmd/goinstall/">Goinstall</a> now uses a new tag selection scheme.
|
||||
When downloading or updating, goinstall looks for a tag or branch with the
|
||||
<code>"go."</code> prefix that corresponds to the local Go version. For Go
|
||||
<code>release.r58</code> it looks for <code>go.r58</code>. For
|
||||
<code>weekly.2011-06-03</code> it looks for <code>go.weekly.2011-06-03</code>.
|
||||
If the specific <code>go.X</code> tag or branch is not found, it chooses the
|
||||
closest earlier version. If an appropriate tag or branch is found, goinstall
|
||||
uses that version of the code. Otherwise it uses the default version selected
|
||||
by the version control system. Library authors are encouraged to use the
|
||||
appropriate tag or branch names in their repositories to make their libraries
|
||||
more accessible.
|
||||
</p>
|
||||
|
||||
<h3 id="r60.minor">Minor revisions</h3>
|
||||
|
||||
<p>
|
||||
r60.1 includes a
|
||||
<a href="http://code.google.com/p/go/source/detail?r=1824581bf62d">linker
|
||||
fix</a>, a pair of
|
||||
<a href="http://code.google.com/p/go/source/detail?r=9ef4429c2c64">goplay</a>
|
||||
<a href="http://code.google.com/p/go/source/detail?r=d42ed8c3098e">fixes</a>,
|
||||
and a <code>json</code> package
|
||||
<a href="http://code.google.com/p/go/source/detail?r=d5e97874fe84">fix</a> and
|
||||
a new
|
||||
<a href="http://code.google.com/p/go/source/detail?r=4f0e6269213f">struct tag
|
||||
option</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
r60.2
|
||||
<a href="http://code.google.com/p/go/source/detail?r=ff19536042ac">fixes</a>
|
||||
a memory leak involving maps.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
r60.3 fixes a
|
||||
<a href="http://code.google.com/p/go/source/detail?r=01fa62f5e4e5">reflect bug</a>.
|
||||
</p>
|
||||
|
||||
<h2 id="r59">r59 (released 2011/08/01)</h2>
|
||||
|
||||
<p>
|
||||
@@ -445,7 +323,7 @@ Remember that gofix will handle the bulk of the rewrites
|
||||
necessary for these changes to package APIs.
|
||||
</p>
|
||||
|
||||
<h3 id="r57.cmd">Tools</h3>
|
||||
<h3 id="r57.tool">Tools</h3>
|
||||
|
||||
<p><a href="/cmd/gofix/">Gofix</a>, a new command, is described above.</p>
|
||||
|
||||
|
||||
135
doc/devel/roadmap.html
Normal file
@@ -0,0 +1,135 @@
|
||||
<!-- Roadmap -->
|
||||
|
||||
<h2 id="Roadmap">Go Roadmap</h2>
|
||||
|
||||
<p>
|
||||
This page lists features and ideas being developed or discussed by the
|
||||
Go team. This list will be updated as work continues.
|
||||
|
||||
<p>
|
||||
The roadmap should be discussed on
|
||||
the <a href="http://groups.google.com/group/golang-nuts">golang-nuts
|
||||
mailing list</a>.
|
||||
|
||||
<h3 id="Language_roadmap">
|
||||
Language roadmap</h3>
|
||||
|
||||
<p>
|
||||
This is a list of language changes that are being considered.
|
||||
Appearance on this list is no guarantee that the change will be
|
||||
accepted.
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
Possibly rewrite restriction on goto across variable declarations.
|
||||
<li>
|
||||
Variant types. A way to define a type as being the union of some set
|
||||
of types.
|
||||
<li>
|
||||
Generics. An active topic of discussion.
|
||||
<li>
|
||||
Methods for operators, to allow a type to use arithmetic notation for
|
||||
expressions.
|
||||
<li>
|
||||
Possibly allow top-level packages to be given names other than main.
|
||||
</ul>
|
||||
|
||||
<h3 id="Implementation_roadmap">
|
||||
Implementation roadmap</h3>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
Improved garbage collector.
|
||||
<li>
|
||||
Debugger.
|
||||
<li>
|
||||
Improved implementation documentation.
|
||||
</ul>
|
||||
|
||||
<h4 id="Gc_roadmap">
|
||||
Gc compiler roadmap</h4>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
Implement goto restrictions.
|
||||
<li>
|
||||
Improved optimization.
|
||||
<li>
|
||||
Use escape analysis to keep more data on stack.
|
||||
</ul>
|
||||
|
||||
<h4 id="Gccgo_roadmap">
|
||||
Gccgo compiler roadmap</h4>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
Implement goto restrictions.
|
||||
<li>
|
||||
Use goroutines rather than threads.
|
||||
<li>
|
||||
Separate gcc interface from frontend proper.
|
||||
<li>
|
||||
Use escape analysis to keep more data on stack.
|
||||
</ul>
|
||||
|
||||
<h4 id="Tools_roadmap">
|
||||
Tools roadmap</h4>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
Strengthen goinstall until it can displace make for most builds.
|
||||
</ul>
|
||||
|
||||
<h4 id="Packages_roadmap">
|
||||
Packages roadmap</h4>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
Faster, RE2-like regular expressions.
|
||||
<li>
|
||||
Comprehensive support for international text.
|
||||
<li>
|
||||
Support for international dates, times, etc.
|
||||
<li>
|
||||
Support for multilingual messages.
|
||||
</ul>
|
||||
|
||||
|
||||
<h3 id="done">Done</h3>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
gc: Generate DWARF debug info.
|
||||
<li>
|
||||
gc: Provide gdb support for runtime facilities.
|
||||
<li>
|
||||
Safe compilation mode: generate code that is guaranteed not to obtain an invalid memory address other than via <code>import "unsafe"</code>.
|
||||
<li>
|
||||
Gccgo: garbage collection.
|
||||
<li>
|
||||
SWIG support.
|
||||
<li>
|
||||
Simpler semicolon rules.
|
||||
<li>
|
||||
A more general definition of <code>...</code> in parameter lists.
|
||||
<li>
|
||||
Explicit conversions from <code>string</code>
|
||||
to <code>[]byte</code> and <code>[]int</code>.
|
||||
<li>
|
||||
A function that will be run by the garbage collector when an item is freed
|
||||
(runtime.SetFinalizer).
|
||||
<li>
|
||||
Public continuous build and benchmark infrastructure (gobuilder).
|
||||
<li>
|
||||
Package manager (goinstall).
|
||||
<li>
|
||||
A means of recovering from a panic (recover).
|
||||
<li>
|
||||
5g: Better floating point support.
|
||||
<li>
|
||||
Improved CGO including some mechanism for calling back from C to Go.
|
||||
<li>
|
||||
Faster, allocation-light reflection.
|
||||
<li>
|
||||
App Engine support.
|
||||
</ul>
|
||||
314
doc/docs.html
@@ -1,145 +1,148 @@
|
||||
<!--{
|
||||
"Title": "Documentation",
|
||||
"Path": "/doc/"
|
||||
}-->
|
||||
|
||||
<p>
|
||||
The Go programming language is an open source project to make programmers more
|
||||
productive.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Go is expressive, concise, clean, and efficient. Its concurrency
|
||||
mechanisms make it easy to write programs that get the most out of multicore
|
||||
and networked machines, while its novel type system enables flexible and
|
||||
modular program construction. Go compiles quickly to machine code yet has the
|
||||
convenience of garbage collection and the power of run-time reflection. It's a
|
||||
fast, statically typed, compiled language that feels like a dynamically typed,
|
||||
interpreted language.
|
||||
</p>
|
||||
|
||||
<div id="manual-nav"></div>
|
||||
|
||||
<h2>Installing Go</h2>
|
||||
|
||||
<h3><a href="/doc/install">Getting Started</a></h3>
|
||||
<p>
|
||||
Instructions for downloading and installing the Go compilers, tools, and
|
||||
libraries.
|
||||
</p>
|
||||
<!-- title Documentation -->
|
||||
|
||||
<div class="left-column">
|
||||
|
||||
<h2 id="learning">Learning Go</h2>
|
||||
|
||||
<img class="gopher" src="/doc/gopher/doc.png"/>
|
||||
|
||||
<h3 id="go_tour"><a href="http://tour.golang.org/">A Tour of Go</a></h3>
|
||||
<p>
|
||||
An interactive introduction to Go in three sections.
|
||||
The first section covers basic syntax and data structures; the second discusses
|
||||
methods and interfaces; and the third introduces Go's concurrency primitives.
|
||||
Each section concludes with a few exercises so you can practice what you've
|
||||
learned. You can <a href="http://tour.golang.org/">take the tour online</a> or
|
||||
<a href="http://code.google.com/p/go-tour/">install it locally</a>.
|
||||
If you're new to Go, we recommend you work through the
|
||||
<a href="go_tutorial.html">tutorial</a>. The
|
||||
<a href="go_spec.html">language specification</a> has all the details should
|
||||
you want to explore.
|
||||
</p>
|
||||
<p>
|
||||
Once you've learned a little about the language,
|
||||
<a href="effective_go.html">Effective Go</a> will help you learn the style and
|
||||
idioms of programming in Go.
|
||||
</p>
|
||||
|
||||
<h3 id="code"><a href="code.html">How to write Go code</a></h3>
|
||||
<h3 id="orig_tutorial"><a href="go_tutorial.html">A Tutorial for the Go Programming Language</a></h3>
|
||||
<p>
|
||||
How to use the <a href="/cmd/go/">go command</a> to fetch, build, and install
|
||||
packages, commands, and run tests.
|
||||
The first tutorial. An introductory text that touches upon several core
|
||||
concepts: syntax, types, allocation, constants, I/O, sorting, printing,
|
||||
goroutines, and channels.
|
||||
</p>
|
||||
|
||||
<h3 id="course_notes">Course Notes</h3>
|
||||
<p>
|
||||
Slides from a 3-day course about the Go programming language.
|
||||
A more thorough introduction than the tutorial.
|
||||
</p>
|
||||
<ul>
|
||||
<li><a href="GoCourseDay1.pdf">Day 1: Basics</a> <small>[270KB PDF]</small>
|
||||
<li><a href="GoCourseDay2.pdf">Day 2: Types, Methods, Interfaces</a> <small>[270KB PDF]</small>
|
||||
<li><a href="GoCourseDay3.pdf">Day 3: Concurrency and Communication</a> <small>[180KB PDF]</small>
|
||||
</ul>
|
||||
|
||||
<h3 id="effective_go"><a href="effective_go.html">Effective Go</a></h3>
|
||||
<p>
|
||||
A document that gives tips for writing clear, idiomatic Go code.
|
||||
A must read for any new Go programmer. It augments the tour and
|
||||
A must read for any new Go programmer. It augments the tutorial and
|
||||
the language specification, both of which should be read first.
|
||||
</p>
|
||||
|
||||
<h3 id="appengine"><a href="http://code.google.com/appengine/docs/go/gettingstarted/">Getting Started with Go on App Engine</a></h3>
|
||||
<p>
|
||||
How to develop and deploy a simple Go project with
|
||||
<a href="http://code.google.com/appengine/">Google App Engine</a>.
|
||||
</p>
|
||||
|
||||
<h3 id="go_faq"><a href="go_faq.html">Frequently Asked Questions (FAQ)</a></h3>
|
||||
<p>
|
||||
Answers to common questions about Go.
|
||||
</p>
|
||||
|
||||
<h3 id="wiki"><a href="http://code.google.com/p/go-wiki/wiki">Go Language Community Wiki</a></h3>
|
||||
<p>A wiki maintained by the Go community.</p>
|
||||
|
||||
<h2 id="go1">Go version 1</h2>
|
||||
|
||||
<h3 id="go1notes"><a href="/doc/go1.html">Go 1 Release Notes</a></h3>
|
||||
<h3 id="code"><a href="code.html">How to write Go code</a></h3>
|
||||
<p>
|
||||
A guide for updating your code to work with Go 1.
|
||||
How to write a new package and how to test code.
|
||||
</p>
|
||||
|
||||
<h3 id="go1compat"><a href="/doc/go1compat.html">Go 1 and the Future of Go Programs</a></h3>
|
||||
<h3 id="codelab_wiki"><a href="codelab/wiki/">Codelab: Writing Web Applications</a></h3>
|
||||
<p>
|
||||
What Go 1 defines and the backwards-compatibility guarantees one can expect as
|
||||
Go 1 matures.
|
||||
This codelab takes the reader through the creation of a simple wiki web
|
||||
application. It touches on structs, methods, file I/O, http, regular expressions,
|
||||
and closures.
|
||||
</p>
|
||||
|
||||
<h2 id="articles">Go Articles</h2>
|
||||
|
||||
<h3 id="blog"><a href="http://blog.golang.org/">The Go Blog</a></h3>
|
||||
<p>The official blog of the Go project, featuring news and in-depth articles by
|
||||
the Go team and guests.</p>
|
||||
|
||||
<h4>Codewalks</h4>
|
||||
<h3 id="codewalks"><a href="codewalk/">Codewalks</a></h3>
|
||||
<p>
|
||||
Guided tours of Go programs.
|
||||
</p>
|
||||
<ul>
|
||||
<li><a href="/doc/codewalk/functions">First-Class Functions in Go</a></li>
|
||||
<li><a href="/doc/codewalk/markov">Generating arbitrary text: a Markov chain algorithm</a></li>
|
||||
<li><a href="/doc/codewalk/sharemem">Share Memory by Communicating</a></li>
|
||||
<li><a href="/doc/articles/wiki/">Writing Web Applications</a> - building a simple web application.</li>
|
||||
</ul>
|
||||
|
||||
<h4>Language</h4>
|
||||
<ul>
|
||||
<li><a href="/doc/articles/json_rpc_tale_of_interfaces.html">JSON-RPC: a tale of interfaces</a></li>
|
||||
<li><a href="/doc/articles/gos_declaration_syntax.html">Go's Declaration Syntax</a></li>
|
||||
<li><a href="/doc/articles/defer_panic_recover.html">Defer, Panic, and Recover</a></li>
|
||||
<li><a href="/doc/articles/concurrency_patterns.html">Go Concurrency Patterns: Timing out, moving on</a></li>
|
||||
<li><a href="/doc/articles/slices_usage_and_internals.html">Go Slices: usage and internals</a></li>
|
||||
<li><a href="http://blog.golang.org/2011/05/gif-decoder-exercise-in-go-interfaces.html">A GIF decoder: an exercise in Go interfaces</a></li>
|
||||
<li><a href="/doc/articles/error_handling.html">Error Handling and Go</a></li>
|
||||
</ul>
|
||||
|
||||
<h4>Packages</h4>
|
||||
<ul>
|
||||
<li><a href="/doc/articles/json_and_go.html">JSON and Go</a> - using the <a href="/pkg/encoding/json/">json</a> package.</li>
|
||||
<li><a href="/doc/articles/gobs_of_data.html">Gobs of data</a> - the design and use of the <a href="/pkg/encoding/gob/">gob</a> package.</li>
|
||||
<li><a href="/doc/articles/laws_of_reflection.html">The Laws of Reflection</a> - the fundamentals of the <a href="/pkg/reflect/">reflect</a> package.</li>
|
||||
<li><a href="/doc/articles/image_package.html">The Go image package</a> - the fundamentals of the <a href="/pkg/image/">image</a> package.</li>
|
||||
<li><a href="/doc/articles/image_draw.html">The Go image/draw package</a> - the fundamentals of the <a href="/pkg/image/draw/">image/draw</a> package.</li>
|
||||
</ul>
|
||||
|
||||
<h4>Tools</h4>
|
||||
<ul>
|
||||
<li><a href="/doc/articles/go_command.html">About the Go command</a> - why we wrote it, what it is, what it's not, and how to use it.</li>
|
||||
<li><a href="/doc/articles/c_go_cgo.html">C? Go? Cgo!</a> - linking against C code with <a href="/cmd/cgo/">cgo</a>.</li>
|
||||
<li><a href="/doc/gdb">Debugging Go Code with GDB</a></li>
|
||||
<li><a href="/doc/articles/godoc_documenting_go_code.html">Godoc: documenting Go code</a> - writing good documentation for <a href="/cmd/godoc/">godoc</a>.</li>
|
||||
<li><a href="http://blog.golang.org/2011/06/profiling-go-programs.html">Profiling Go Programs</a></li>
|
||||
</ul>
|
||||
|
||||
<h2 id="talks">Talks</h2>
|
||||
|
||||
<img class="gopher" src="/doc/gopher/talks.png"/>
|
||||
|
||||
<p>
|
||||
The talks marked with a red asterisk (<font color="red">*</font>) were written
|
||||
before Go 1 and contain some examples that are no longer correct, but they are
|
||||
still of value.
|
||||
Guided tours of Go programs.
|
||||
</p>
|
||||
|
||||
<h3 id="writing_web_apps"><a href="http://www.youtube.com/watch?v=-i0hat7pdpk">Writing Web Apps in Go</a><font color="red">*</font></h3>
|
||||
<h3 id="go_for_cpp_programmers"><a href="go_for_cpp_programmers.html">Go for C++ Programmers</a></h3>
|
||||
<p>
|
||||
An introduction to Go for C++ programmers.
|
||||
</p>
|
||||
|
||||
<h2 id="tutorials_nonenglish">Non-English Documentation</h2>
|
||||
|
||||
<h3 id="docs_be">Belarusian — Беларуская</h3>
|
||||
|
||||
<ul>
|
||||
<li><a href="http://www.designcontest.com/show/faq-be">faq-be</a> - Frequently Asked Questions.</li>
|
||||
</ul>
|
||||
|
||||
<h3 id="docs_cn">Chinese — 中文</h3>
|
||||
|
||||
<ul>
|
||||
<li><a href="http://code.google.com/p/golang-china/">golang-china</a> - a broad range of Go documentation.</li>
|
||||
<li><a href="http://code.google.com/p/ac-me/downloads/detail?name=fango.pdf">Effective Go and Tutorial</a></li>
|
||||
</ul>
|
||||
|
||||
<h3 id="docs_de">German — Deutsch</h3>
|
||||
|
||||
<ul>
|
||||
<li><a href="http://bitloeffel.de/DOC/golang/go_tutorial_de.html">Eine Anleitung zum Programmieren in Go</a> - the Go Tutorial.</li>
|
||||
<li><a href="http://bitloeffel.de/DOC/golang/effective_go_de.html">Wirkungsvoll Go programmieren</a> - Effective Go.</li>
|
||||
<li><a href="http://bitloeffel.de/DOC/golang/code_de.html">Wie man Go-Kode schreibt</a> - How to Write Go Code.</li>
|
||||
</ul>
|
||||
|
||||
<h3 id="docs_jp">Japanese — 日本語</h3>
|
||||
<ul>
|
||||
<li><a href="http://golang.jp/">golang.jp</a> - Go documentation and news.
|
||||
</ul>
|
||||
|
||||
<h3 id="docs_kr">Korean — 한국어</h3>
|
||||
<ul>
|
||||
<li><a href="http://code.google.com/p/golang-korea">golang-korea</a> - Go documentation and news.
|
||||
</ul>
|
||||
|
||||
<h3 id="docs_ru">Russian — Русский</h3>
|
||||
<ul>
|
||||
<li><a href="http://golanguage.ru/">golanguage.ru</a> - Go documentation.
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div class="right-column">
|
||||
|
||||
<h2 id="References">References</h2>
|
||||
|
||||
<p>Keep these under your pillow.</p>
|
||||
|
||||
<h3 id="pkg"><a href="/pkg/">Package Documentation</a></h3>
|
||||
<p>
|
||||
The built-in documentation for the Go standard library.
|
||||
</p>
|
||||
|
||||
<h3 id="cmd"><a href="/cmd/">Command Documentation</a></h3>
|
||||
<p>
|
||||
The built-in documentation for the Go tools.
|
||||
</p>
|
||||
|
||||
<h3 id="spec"><a href="go_spec.html">Language Specification</a></h3>
|
||||
<p>
|
||||
The official Go Language specification.
|
||||
</p>
|
||||
|
||||
<h3 id="release"><a href="devel/release.html">Release History</a></h3>
|
||||
<p>A summary of the changes between Go releases.</p>
|
||||
|
||||
<h3 id="go_mem"><a href="go_mem.html">The Go Memory Model</a></h3>
|
||||
<p>
|
||||
A document that specifies the conditions under which reads of a variable in
|
||||
one goroutine can be guaranteed to observe values produced by writes to the
|
||||
same variable in a different goroutine.
|
||||
</p>
|
||||
|
||||
<h2 id="videos_talks">Videos and Talks</h2>
|
||||
|
||||
<h3 id="writing_web_apps"><a href="http://www.youtube.com/watch?v=-i0hat7pdpk">Writing Web Apps in Go</a></h3>
|
||||
<p>
|
||||
A talk by Rob Pike and Andrew Gerrand presented at Google I/O 2011.
|
||||
It walks through the construction and deployment of a simple web application
|
||||
@@ -147,7 +150,7 @@ and unveils the <a href="http://blog.golang.org/2011/05/go-and-google-app-engine
|
||||
See the <a href="/doc/talks/io2011/Writing_Web_Apps_in_Go.pdf">presentation slides</a>.
|
||||
</p>
|
||||
|
||||
<h3 id="real_world_go"><a href="http://www.youtube.com/watch?v=7QDVRowyUQA">Real World Go</a><font color="red">*</font></h3>
|
||||
<h3 id="real_world_go"><a href="http://www.youtube.com/watch?v=7QDVRowyUQA">Real World Go</a></h3>
|
||||
<p>
|
||||
A talk by Andrew Gerrand presented at Google I/O Bootcamp 2011.
|
||||
It gives a broad overview of Go's type system and concurrency model
|
||||
@@ -155,22 +158,15 @@ and provides four examples of Go programs that solve real problems.
|
||||
See the <a href="/doc/talks/io2011/Real_World_Go.pdf">presentation slides</a>.
|
||||
</p>
|
||||
|
||||
<h3 id="integrated_apps"><a href="http://www.youtube.com/watch?v=Mo1YKpIF1PQ">Building Integrated Apps on Google's Cloud Platform</a></h3>
|
||||
<p>
|
||||
A talk by Andrew Gerrand presented at Google Developer Day Japan 2011.
|
||||
It discusses the development of a web application that runs on Google
|
||||
App Engine and renders images that it stores on Google Cloud Storage.
|
||||
</p>
|
||||
|
||||
<h3 id="go_programming"><a href="http://www.youtube.com/watch?v=jgVhBThJdXc">Go Programming</a><font color="red">*</font></h3>
|
||||
<h3 id="go_programming"><a href="http://www.youtube.com/watch?v=jgVhBThJdXc">Go Programming</a></h3>
|
||||
<p>
|
||||
A presentation delivered by Rob Pike and Russ Cox at Google I/O 2010. It
|
||||
illustrates how programming in Go differs from other languages through a set of
|
||||
examples demonstrating features particular to Go. These include concurrency,
|
||||
embedded types, methods on any type, and program construction using interfaces.
|
||||
embedded types, methods on any type, and program construction using interfaces.
|
||||
</p>
|
||||
|
||||
<h3 id="practical_go_programming"><a href="http://www.youtube.com/watch?v=2-pPAvqyluI">Practical Go Programming</a><font color="red">*</font></h3>
|
||||
<h3 id="practical_go_programming"><a href="http://osdc.blip.tv/file/4432146/">Practical Go Programming</a></h3>
|
||||
<p>
|
||||
This talk presents the development of a complete web application in Go.
|
||||
It looks at design, storage, concurrency, and scaling issues in detail, using
|
||||
@@ -178,37 +174,63 @@ the simple example of an URL shortening service.
|
||||
See the <a href="http://wh3rd.net/practical-go/">presentation slides</a>.
|
||||
</p>
|
||||
|
||||
<h4 id="talks_more">More</h4>
|
||||
<h3 id="techtalk"><a href="http://www.youtube.com/watch?v=rKnDgT73v8s">The Go Tech Talk</a></h3>
|
||||
<p>
|
||||
See the <a href="http://code.google.com/p/go-wiki/wiki/GoTalks">GoTalks
|
||||
page</a> at the <a href="http://code.google.com/p/go-wiki/wiki">Go Wiki</a> for
|
||||
more Go talks.
|
||||
An hour-long talk delivered by Rob Pike at Google in October 2009.
|
||||
The language's first public introduction. (See the <a href="talks/go_talk-20091030.pdf">slides in PDF format</a>.) The language has changed since it was made,
|
||||
but it's still a good introduction.
|
||||
</p>
|
||||
|
||||
<h2 id="nonenglish">Non-English Documentation</h2>
|
||||
|
||||
<h3 id="gocoding_channel"><a href="http://www.youtube.com/gocoding">gocoding YouTube Channel</a></h3>
|
||||
<p>
|
||||
See the <a href="http://code.google.com/p/go-wiki/wiki/NonEnglish">NonEnglish</a> page
|
||||
at the <a href="http://code.google.com/p/go-wiki/wiki">Go Wiki</a> for localized
|
||||
documentation.
|
||||
A YouTube channel that includes screencasts and other Go-related videos:
|
||||
</p>
|
||||
<ul>
|
||||
<li><a href="http://www.youtube.com/gocoding#p/u/0/jDWBJOXs_iI">Screencast: Writing Go Packages</a> - writing, building, and distributing Go packages.</li>
|
||||
<li><a href="http://www.youtube.com/watch?v=3brH0zOqm0w">Screencast: Testing Go Packages</a> - writing unit tests and benchmarking Go packages.</li>
|
||||
</ul>
|
||||
|
||||
<h3 id="jaoo_go"><a href="/doc/ExpressivenessOfGo.pdf">The Expressiveness Of Go</a></h3>
|
||||
<p>
|
||||
A discussion of the qualities that make Go an expressive and comprehensible
|
||||
language. The talk was presented by Rob Pike at JAOO 2010.
|
||||
The recording of the event was lost due to a hardware error.
|
||||
</p>
|
||||
|
||||
<h2 id="community">The Go Community</h2>
|
||||
<h3 id="oscon_go"><a href="http://www.oscon.com/oscon2010/public/schedule/detail/14760">Another Go at Language Design</a></h3>
|
||||
<p>
|
||||
A tour, with some background, of the major features of Go, intended for
|
||||
an audience new to the language. The talk was presented at OSCON 2010.
|
||||
See the <a href="http://assets.en.oreilly.com/1/event/45/Another%20Go%20at%20Language%20Design%20Presentation.pdf">presentation slides</a>.
|
||||
</p>
|
||||
<p>
|
||||
This talk was also delivered at Sydney University in September 2010. A video
|
||||
of the lecture is available
|
||||
<a href="http://sydney.edu.au/engineering/it/videos/seminar_pike">here</a>.
|
||||
</p>
|
||||
|
||||
<img class="gopher" src="/doc/gopher/project.png"/>
|
||||
<h3 id="emerging_go"><a href="http://www.oscon.com/oscon2010/public/schedule/detail/15464">Go Emerging Languages Conference Talk</a></h3>
|
||||
<p>
|
||||
Rob Pike's Emerging Languages Conference presentation delivered in July 2010. See the <a href="http://assets.en.oreilly.com/1/event/45/Go%20Presentation.pdf">presentation slides</a>. Abstract:
|
||||
</p>
|
||||
<p><i>
|
||||
Go’s approach to concurrency differs from that of many languages, even those
|
||||
(such as Erlang) that make concurrency central, yet it has deep roots. The path
|
||||
from Hoare’s 1978 paper to Go provides insight into how and why Go works as it
|
||||
does.
|
||||
</i></p>
|
||||
|
||||
<h3 id="mailinglist"><a href="http://groups.google.com/group/golang-nuts">Go Nuts Mailing List</a></h3>
|
||||
<p>The <a href="http://groups.google.com/group/golang-nuts">golang-nuts</a>
|
||||
mailing list is for general Go discussion.</p>
|
||||
<h3 id="go_frontend_gcc"><a href="talks/gofrontend-gcc-summit-2010.pdf">The Go frontend for GCC</a></h3>
|
||||
<p>
|
||||
A description of the Go language frontend for gcc.
|
||||
Ian Lance Taylor's paper delivered at the GCC Summit 2010.
|
||||
</p>
|
||||
|
||||
<h3 id="projects"><a href="http://godashboard.appspot.com/project">Go Project Dashboard</a></h3>
|
||||
<p>A list of external Go projects including programs and libraries.</p>
|
||||
<h3 id="promo_video"><a href="http://www.youtube.com/watch?v=wwoWei-GAPo">The Go Promo Video</a></h3>
|
||||
<p>
|
||||
A short promotional video featuring Russ Cox demonstrating Go's fast compiler.
|
||||
</p>
|
||||
|
||||
<h3 id="irc"><a href="irc:irc.freenode.net/go-nuts">Go IRC Channel</a></h3>
|
||||
<p><b>#go-nuts</b> on <b>irc.freenode.net</b> is the official Go IRC channel.</p>
|
||||
</div>
|
||||
|
||||
<h3 id="plus"><a href="https://plus.google.com/101406623878176903605/posts">The Go Programming Language at Google+</a></h3>
|
||||
<p>The Go project's Google+ page.</p>
|
||||
|
||||
<h3 id="twitter"><a href="http://twitter.com/go_nuts">@go_nuts at Twitter</a></h3>
|
||||
<p>The Go project's official Twitter account.</p>
|
||||
<div class="end-columns"></div>
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
<!--{
|
||||
"Title": "Effective Go",
|
||||
"Template": true
|
||||
}-->
|
||||
<!-- Effective Go -->
|
||||
|
||||
<h2 id="introduction">Introduction</h2>
|
||||
|
||||
@@ -27,10 +24,8 @@ will be easy for other Go programmers to understand.
|
||||
|
||||
<p>
|
||||
This document gives tips for writing clear, idiomatic Go code.
|
||||
It augments the <a href="/ref/spec">language specification</a>,
|
||||
the <a href="http://tour.golang.org/">Tour of Go</a>,
|
||||
and <a href="/doc/code.html">How to Write Go Code</a>,
|
||||
all of which you
|
||||
It augments the <a href="go_spec.html">language specification</a>
|
||||
and the <a href="go_tutorial.html">tutorial</a>, both of which you
|
||||
should read first.
|
||||
</p>
|
||||
|
||||
@@ -64,10 +59,7 @@ prescriptive style guide.
|
||||
With Go we take an unusual
|
||||
approach and let the machine
|
||||
take care of most formatting issues.
|
||||
The <code>gofmt</code> program
|
||||
(also available as <code>go fmt</code>, which
|
||||
operates at the package level rather than source file level)
|
||||
reads a Go program
|
||||
The <code>gofmt</code> tool reads a Go program
|
||||
and emits the source in a standard style of indentation
|
||||
and vertical alignment, retaining and if necessary
|
||||
reformatting comments.
|
||||
@@ -124,7 +116,7 @@ Some formatting details remain. Very briefly,
|
||||
<dt>Parentheses</dt>
|
||||
<dd>
|
||||
Go needs fewer parentheses: control structures (<code>if</code>,
|
||||
<code>for</code>, <code>switch</code>) do not have parentheses in
|
||||
<code>for</code>, <code>switch</code>) do not require parentheses in
|
||||
their syntax.
|
||||
Also, the operator precedence hierarchy is shorter and clearer, so
|
||||
<pre>
|
||||
@@ -229,7 +221,7 @@ starts with the name being declared.
|
||||
<pre>
|
||||
// Compile parses a regular expression and returns, if successful, a Regexp
|
||||
// object that can be used to match against text.
|
||||
func Compile(str string) (regexp *Regexp, err error) {
|
||||
func Compile(str string) (regexp *Regexp, error os.Error) {
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
@@ -241,9 +233,9 @@ Since the whole declaration is presented, such a comment can often be perfunctor
|
||||
<pre>
|
||||
// Error codes returned by failures to parse an expression.
|
||||
var (
|
||||
ErrInternal = errors.New("regexp: internal error")
|
||||
ErrUnmatchedLpar = errors.New("regexp: unmatched '('")
|
||||
ErrUnmatchedRpar = errors.New("regexp: unmatched ')'")
|
||||
ErrInternal = os.NewError("regexp: internal error")
|
||||
ErrUnmatchedLpar = os.NewError("regexp: unmatched '('")
|
||||
ErrUnmatchedRpar = os.NewError("regexp: unmatched ')'")
|
||||
...
|
||||
)
|
||||
</pre>
|
||||
@@ -413,7 +405,7 @@ break continue fallthrough return ++ -- ) }
|
||||
<p>
|
||||
the lexer always inserts a semicolon after the token.
|
||||
This could be summarized as, “if the newline comes
|
||||
after a token that could end a statement, insert a semicolon”.
|
||||
after a token that could end a statement, add a semicolon”.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
@@ -469,7 +461,7 @@ initialization statement like that of <code>for</code>;
|
||||
and there are new control structures including a type switch and a
|
||||
multiway communications multiplexer, <code>select</code>.
|
||||
The syntax is also slightly different:
|
||||
there are no parentheses
|
||||
parentheses are not required
|
||||
and the bodies must always be brace-delimited.
|
||||
</p>
|
||||
|
||||
@@ -534,62 +526,12 @@ if err != nil {
|
||||
}
|
||||
d, err := f.Stat()
|
||||
if err != nil {
|
||||
f.Close()
|
||||
return err
|
||||
}
|
||||
codeUsing(f, d)
|
||||
</pre>
|
||||
|
||||
|
||||
<h3 id="redeclaration">Redeclaration</h3>
|
||||
|
||||
<p>
|
||||
An aside: The last example in the previous section demonstrates a detail of how the
|
||||
<code>:=</code> short declaration form works.
|
||||
The declaration that calls <code>os.Open</code> reads,
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
f, err := os.Open(name)
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
This statement declares two variables, <code>f</code> and <code>err</code>.
|
||||
A few lines later, the call to <code>f.Stat</code> reads,
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
d, err := f.Stat()
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
which looks as if it declares <code>d</code> and <code>err</code>.
|
||||
Notice, though, that <code>err</code> appears in both statements.
|
||||
This duplication is legal: <code>err</code> is declared by the first statement,
|
||||
but only <em>re-assigned</em> in the second.
|
||||
This means that the call to <code>f.Stat</code> uses the existing
|
||||
<code>err</code> variable declared above, and just gives it a new value.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
In a <code>:=</code> declaration a variable <code>v</code> may appear even
|
||||
if it has already been declared, provided:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>this declaration is in the same scope as the existing declaration of <code>v</code>
|
||||
(if <code>v</code> is already declared in an outer scope, the declaration will create a new variable),</li>
|
||||
<li>the corresponding value in the initialization is assignable to <code>v</code>, and</li>
|
||||
<li>there is at least one other variable in the declaration that is being declared anew.</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
This unusual property is pure pragmatism,
|
||||
making it easy to use a single <code>err</code> value, for example,
|
||||
in a long <code>if-else</code> chain.
|
||||
You'll see it used often.
|
||||
</p>
|
||||
|
||||
<h3 id="for">For</h3>
|
||||
|
||||
<p>
|
||||
@@ -622,31 +564,12 @@ for i := 0; i < 10; i++ {
|
||||
<p>
|
||||
If you're looping over an array, slice, string, or map,
|
||||
or reading from a channel, a <code>range</code> clause can
|
||||
manage the loop.
|
||||
</p>
|
||||
<pre>
|
||||
for key, value := range oldMap {
|
||||
newMap[key] = value
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
If you only need the first item in the range (the key or index), drop the second:
|
||||
</p>
|
||||
<pre>
|
||||
for key := range m {
|
||||
if expired(key) {
|
||||
delete(m, key)
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
If you only need the second item in the range (the value), use the <em>blank identifier</em>, an underscore, to discard the first:
|
||||
manage the loop for you.
|
||||
</p>
|
||||
<pre>
|
||||
var m map[string]int
|
||||
sum := 0
|
||||
for _, value := range array {
|
||||
for _, value := range m { // key is unused
|
||||
sum += value
|
||||
}
|
||||
</pre>
|
||||
@@ -728,7 +651,7 @@ func shouldEscape(c byte) bool {
|
||||
Here's a comparison routine for byte arrays that uses two
|
||||
<code>switch</code> statements:
|
||||
<pre>
|
||||
// Compare returns an integer comparing the two byte arrays,
|
||||
// Compare returns an integer comparing the two byte arrays
|
||||
// lexicographically.
|
||||
// The result will be 0 if a == b, -1 if a < b, and +1 if a > b
|
||||
func Compare(a, b []byte) int {
|
||||
@@ -790,16 +713,16 @@ error code secreted away in a volatile location.
|
||||
In Go, <code>Write</code>
|
||||
can return a count <i>and</i> an error: “Yes, you wrote some
|
||||
bytes but not all of them because you filled the device”.
|
||||
The signature of <code>File.Write</code> in package <code>os</code> is:
|
||||
The signature of <code>*File.Write</code> in package <code>os</code> is:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
func (file *File) Write(b []byte) (n int, err error)
|
||||
func (file *File) Write(b []byte) (n int, err Error)
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
and as the documentation says, it returns the number of bytes
|
||||
written and a non-nil <code>error</code> when <code>n</code>
|
||||
written and a non-nil <code>Error</code> when <code>n</code>
|
||||
<code>!=</code> <code>len(b)</code>.
|
||||
This is a common style; see the section on error handling for more examples.
|
||||
</p>
|
||||
@@ -865,12 +788,12 @@ of <code>io.ReadFull</code> that uses them well:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
func ReadFull(r Reader, buf []byte) (n int, err error) {
|
||||
func ReadFull(r Reader, buf []byte) (n int, err os.Error) {
|
||||
for len(buf) > 0 && err == nil {
|
||||
var nr int
|
||||
nr, err = r.Read(buf)
|
||||
n += nr
|
||||
buf = buf[nr:]
|
||||
buf = buf[nr:len(buf)]
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -889,7 +812,7 @@ canonical examples are unlocking a mutex or closing a file.
|
||||
|
||||
<pre>
|
||||
// Contents returns the file's contents as a string.
|
||||
func Contents(filename string) (string, error) {
|
||||
func Contents(filename string) (string, os.Error) {
|
||||
f, err := os.Open(filename)
|
||||
if err != nil {
|
||||
return "", err
|
||||
@@ -902,7 +825,7 @@ func Contents(filename string) (string, error) {
|
||||
n, err := f.Read(buf[0:])
|
||||
result = append(result, buf[0:n]...) // append is discussed later.
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
if err == os.EOF {
|
||||
break
|
||||
}
|
||||
return "", err // f will be closed if we return here.
|
||||
@@ -1020,20 +943,16 @@ Go has two allocation primitives, the built-in functions
|
||||
They do different things and apply to different types, which can be confusing,
|
||||
but the rules are simple.
|
||||
Let's talk about <code>new</code> first.
|
||||
It's a built-in function that allocates memory, but unlike its namesakes
|
||||
in some other languages it does not <em>initialize</em> the memory,
|
||||
it only <em>zeros</em> it.
|
||||
That is,
|
||||
<code>new(T)</code> allocates zeroed storage for a new item of type
|
||||
It's a built-in function essentially the same as its namesakes
|
||||
in other languages: <code>new(T)</code> allocates zeroed storage for a new item of type
|
||||
<code>T</code> and returns its address, a value of type <code>*T</code>.
|
||||
In Go terminology, it returns a pointer to a newly allocated zero value of type
|
||||
<code>T</code>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Since the memory returned by <code>new</code> is zeroed, it's helpful to arrange
|
||||
when designing your data structures that the
|
||||
zero value of each type can be used without further initialization. This means a user of
|
||||
Since the memory returned by <code>new</code> is zeroed, it's helpful to arrange that the
|
||||
zeroed object can be used without further initialization. This means a user of
|
||||
the data structure can create one with <code>new</code> and get right to
|
||||
work.
|
||||
For example, the documentation for <code>bytes.Buffer</code> states that
|
||||
@@ -1153,9 +1072,8 @@ m := map[int]string{Enone: "no error", Eio: "Eio", Einval: "invalid argument"}
|
||||
Back to allocation.
|
||||
The built-in function <code>make(T, </code><i>args</i><code>)</code> serves
|
||||
a purpose different from <code>new(T)</code>.
|
||||
It creates slices, maps, and channels only, and it returns an <em>initialized</em>
|
||||
(not <em>zeroed</em>)
|
||||
value of type <code>T</code> (not <code>*T</code>).
|
||||
It creates slices, maps, and channels only, and it returns an initialized (not zero)
|
||||
value of type <code>T</code>, not <code>*T</code>.
|
||||
The reason for the distinction
|
||||
is that these three types are, under the covers, references to data structures that
|
||||
must be initialized before use.
|
||||
@@ -1272,7 +1190,7 @@ limit of how much data to read. Here is the signature of the
|
||||
<code>os</code>:
|
||||
</p>
|
||||
<pre>
|
||||
func (file *File) Read(buf []byte) (n int, err error)
|
||||
func (file *File) Read(buf []byte) (n int, err os.Error)
|
||||
</pre>
|
||||
<p>
|
||||
The method returns the number of bytes read and an error value, if
|
||||
@@ -1284,11 +1202,11 @@ any. To read into the first 32 bytes of a larger buffer
|
||||
</pre>
|
||||
<p>
|
||||
Such slicing is common and efficient. In fact, leaving efficiency aside for
|
||||
the moment, the following snippet would also read the first 32 bytes of the buffer.
|
||||
the moment, this snippet would also read the first 32 bytes of the buffer.
|
||||
</p>
|
||||
<pre>
|
||||
var n int
|
||||
var err error
|
||||
var err os.Error
|
||||
for i := 0; i < 32; i++ {
|
||||
nbytes, e := f.Read(buf[i:i+1]) // Read one byte.
|
||||
if nbytes == 0 || e != nil {
|
||||
@@ -1346,9 +1264,9 @@ values of different types.
|
||||
The key can be of any type for which the equality operator is defined,
|
||||
such as integers,
|
||||
floating point and complex numbers,
|
||||
strings, pointers, interfaces (as long as the dynamic type
|
||||
supports equality), structs and arrays. Slices cannot be used as map keys,
|
||||
because equality is not defined on them.
|
||||
strings, pointers, and interfaces (as long as the dynamic type
|
||||
supports equality). Structs, arrays and slices cannot be used as map keys,
|
||||
because equality is not defined on those types.
|
||||
Like slices, maps are a reference type. If you pass a map to a function
|
||||
that changes the contents of the map, the changes will be visible
|
||||
in the caller.
|
||||
@@ -1426,7 +1344,7 @@ func offset(tz string) int {
|
||||
</pre>
|
||||
<p>
|
||||
To test for presence in the map without worrying about the actual value,
|
||||
you can use the blank identifier (<code>_</code>).
|
||||
you can use the <em>blank identifier</em>, a simple underscore (<code>_</code>).
|
||||
The blank identifier can be assigned or declared with any value of any type, with the
|
||||
value discarded harmlessly. For testing just presence in a map, use the blank
|
||||
identifier in place of the usual variable for the value.
|
||||
@@ -1435,13 +1353,13 @@ identifier in place of the usual variable for the value.
|
||||
_, present := timeZone[tz]
|
||||
</pre>
|
||||
<p>
|
||||
To delete a map entry, use the <code>delete</code>
|
||||
built-in function, whose arguments are the map and the key to be deleted.
|
||||
It's safe to do this this even if the key is already absent
|
||||
To delete a map entry, turn the multiple assignment around by placing
|
||||
an extra boolean on the right; if the boolean is false, the entry
|
||||
is deleted. It's safe to do this even if the key is already absent
|
||||
from the map.
|
||||
</p>
|
||||
<pre>
|
||||
delete(timeZone, "PDT") // Now on Standard Time
|
||||
timeZone["PDT"] = 0, false // Now on Standard Time
|
||||
</pre>
|
||||
|
||||
<h3 id="printing">Printing</h3>
|
||||
@@ -1471,7 +1389,7 @@ fmt.Println(fmt.Sprint("Hello ", 23))
|
||||
</pre>
|
||||
<p>
|
||||
As mentioned in
|
||||
the <a href="http://tour.golang.org">Tour</a>, <code>fmt.Fprint</code>
|
||||
the <a href="go_tutorial.html">tutorial</a>, <code>fmt.Fprint</code>
|
||||
and friends take as a first argument any object
|
||||
that implements the <code>io.Writer</code> interface; the variables <code>os.Stdout</code>
|
||||
and <code>os.Stderr</code> are familiar instances.
|
||||
@@ -1516,7 +1434,7 @@ format <code>%#v</code> prints the value in full Go syntax.
|
||||
<pre>
|
||||
type T struct {
|
||||
a int
|
||||
b float64
|
||||
b float
|
||||
c string
|
||||
}
|
||||
t := &T{ 7, -2.35, "abc\tdef" }
|
||||
@@ -1586,7 +1504,7 @@ for its final argument to specify that an arbitrary number of parameters (of arb
|
||||
can appear after the format.
|
||||
</p>
|
||||
<pre>
|
||||
func Printf(format string, v ...interface{}) (n int, err error) {
|
||||
func Printf(format string, v ...interface{}) (n int, errno os.Error) {
|
||||
</pre>
|
||||
<p>
|
||||
Within the function <code>Printf</code>, <code>v</code> acts like a variable of type
|
||||
@@ -1632,49 +1550,40 @@ Now we have the missing piece we needed to explain the design of
|
||||
the <code>append</code> built-in function. The signature of <code>append</code>
|
||||
is different from our custom <code>Append</code> function above.
|
||||
Schematically, it's like this:
|
||||
</p>
|
||||
<pre>
|
||||
func append(slice []<i>T</i>, elements...T) []<i>T</i>
|
||||
</pre>
|
||||
<p>
|
||||
where <i>T</i> is a placeholder for any given type. You can't
|
||||
actually write a function in Go where the type <code>T</code>
|
||||
is determined by the caller.
|
||||
That's why <code>append</code> is built in: it needs support from the
|
||||
compiler.
|
||||
</p>
|
||||
<p>
|
||||
What <code>append</code> does is append the elements to the end of
|
||||
the slice and return the result. The result needs to be returned
|
||||
because, as with our hand-written <code>Append</code>, the underlying
|
||||
array may change. This simple example
|
||||
</p>
|
||||
<pre>
|
||||
x := []int{1,2,3}
|
||||
x = append(x, 4, 5, 6)
|
||||
fmt.Println(x)
|
||||
</pre>
|
||||
<p>
|
||||
prints <code>[1 2 3 4 5 6]</code>. So <code>append</code> works a
|
||||
little like <code>Printf</code>, collecting an arbitrary number of
|
||||
arguments.
|
||||
</p>
|
||||
<p>
|
||||
But what if we wanted to do what our <code>Append</code> does and
|
||||
append a slice to a slice? Easy: use <code>...</code> at the call
|
||||
site, just as we did in the call to <code>Output</code> above. This
|
||||
snippet produces identical output to the one above.
|
||||
</p>
|
||||
<pre>
|
||||
x := []int{1,2,3}
|
||||
y := []int{4,5,6}
|
||||
x = append(x, y...)
|
||||
fmt.Println(x)
|
||||
</pre>
|
||||
<p>
|
||||
Without that <code>...</code>, it wouldn't compile because the types
|
||||
would be wrong; <code>y</code> is not of type <code>int</code>.
|
||||
</p>
|
||||
|
||||
<h2 id="initialization">Initialization</h2>
|
||||
|
||||
@@ -1708,28 +1617,56 @@ enumerator. Since <code>iota</code> can be part of an expression and
|
||||
expressions can be implicitly repeated, it is easy to build intricate
|
||||
sets of values.
|
||||
</p>
|
||||
{{code "/doc/progs/eff_bytesize.go" `/^type ByteSize/` `/^\)/`}}
|
||||
<pre>
|
||||
type ByteSize float64
|
||||
const (
|
||||
_ = iota // ignore first value by assigning to blank identifier
|
||||
KB ByteSize = 1<<(10*iota)
|
||||
MB
|
||||
GB
|
||||
TB
|
||||
PB
|
||||
EB
|
||||
ZB
|
||||
YB
|
||||
)
|
||||
</pre>
|
||||
<p>
|
||||
The ability to attach a method such as <code>String</code> to a
|
||||
type makes it possible for such values to format themselves
|
||||
automatically for printing, even as part of a general type.
|
||||
</p>
|
||||
{{code "/doc/progs/eff_bytesize.go" `/^func.*ByteSize.*String/` `/^}/`}}
|
||||
<pre>
|
||||
func (b ByteSize) String() string {
|
||||
switch {
|
||||
case b >= YB:
|
||||
return fmt.Sprintf("%.2fYB", float64(b/YB))
|
||||
case b >= ZB:
|
||||
return fmt.Sprintf("%.2fZB", float64(b/ZB))
|
||||
case b >= EB:
|
||||
return fmt.Sprintf("%.2fEB", float64(b/EB))
|
||||
case b >= PB:
|
||||
return fmt.Sprintf("%.2fPB", float64(b/PB))
|
||||
case b >= TB:
|
||||
return fmt.Sprintf("%.2fTB", float64(b/TB))
|
||||
case b >= GB:
|
||||
return fmt.Sprintf("%.2fGB", float64(b/GB))
|
||||
case b >= MB:
|
||||
return fmt.Sprintf("%.2fMB", float64(b/MB))
|
||||
case b >= KB:
|
||||
return fmt.Sprintf("%.2fKB", float64(b/KB))
|
||||
}
|
||||
return fmt.Sprintf("%.2fB", float64(b))
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
(The <code>float64</code> conversions prevent <code>Sprintf</code>
|
||||
from recurring back through the <code>String</code> method for
|
||||
<code>ByteSize</code>.)
|
||||
The expression <code>YB</code> prints as <code>1.00YB</code>,
|
||||
while <code>ByteSize(1e13)</code> prints as <code>9.09TB</code>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Note that it's fine to call <code>Sprintf</code> and friends in the
|
||||
implementation of <code>String</code> methods, but beware of
|
||||
recurring into the <code>String</code> method through the nested
|
||||
<code>Sprintf</code> call using a string format
|
||||
(<code>%s</code>, <code>%q</code>, <code>%v</code>, <code>%x</code> or <code>%X</code>).
|
||||
The <code>ByteSize</code> implementation of <code>String</code> is safe
|
||||
because it calls <code>Sprintf</code> with <code>%f</code>.
|
||||
</p>
|
||||
|
||||
<h3 id="variables">Variables</h3>
|
||||
|
||||
<p>
|
||||
@@ -1749,7 +1686,10 @@ var (
|
||||
<p>
|
||||
Finally, each source file can define its own niladic <code>init</code> function to
|
||||
set up whatever state is required. (Actually each file can have multiple
|
||||
<code>init</code> functions.)
|
||||
<code>init</code> functions.) The only restriction is that, although
|
||||
goroutines can be launched during initialization, they will not begin
|
||||
execution until it completes; initialization always runs as a single thread
|
||||
of execution.
|
||||
And finally means finally: <code>init</code> is called after all the
|
||||
variable declarations in the package have evaluated their initializers,
|
||||
and those are evaluated only after all the imported packages have been
|
||||
@@ -1814,7 +1754,7 @@ In fact, we can do even better. If we modify our function so it looks
|
||||
like a standard <code>Write</code> method, like this,
|
||||
</p>
|
||||
<pre>
|
||||
func (p *ByteSlice) Write(data []byte) (n int, err error) {
|
||||
func (p *ByteSlice) Write(data []byte) (n int, err os.Error) {
|
||||
slice := *p
|
||||
// Again as above.
|
||||
*p = slice
|
||||
@@ -1867,7 +1807,33 @@ by the routines in package <code>sort</code> if it implements
|
||||
and it could also have a custom formatter.
|
||||
In this contrived example <code>Sequence</code> satisfies both.
|
||||
</p>
|
||||
{{code "/doc/progs/eff_sequence.go" `/^type/` "$"}}
|
||||
<pre>
|
||||
type Sequence []int
|
||||
|
||||
// Methods required by sort.Interface.
|
||||
func (s Sequence) Len() int {
|
||||
return len(s)
|
||||
}
|
||||
func (s Sequence) Less(i, j int) bool {
|
||||
return s[i] < s[j]
|
||||
}
|
||||
func (s Sequence) Swap(i, j int) {
|
||||
s[i], s[j] = s[j], s[i]
|
||||
}
|
||||
|
||||
// Method for printing - sorts the elements before printing.
|
||||
func (s Sequence) String() string {
|
||||
sort.Sort(s)
|
||||
str := "["
|
||||
for i, elem := range s {
|
||||
if i > 0 {
|
||||
str += " "
|
||||
}
|
||||
str += fmt.Sprint(elem)
|
||||
}
|
||||
return str + "]"
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h3 id="conversions">Conversions</h3>
|
||||
|
||||
@@ -1899,7 +1865,7 @@ do create a new value.)
|
||||
It's an idiom in Go programs to convert the
|
||||
type of an expression to access a different
|
||||
set of methods. As an example, we could use the existing
|
||||
type <code>sort.IntSlice</code> to reduce the entire example
|
||||
type <code>sort.IntArray</code> to reduce the entire example
|
||||
to this:
|
||||
</p>
|
||||
<pre>
|
||||
@@ -1907,14 +1873,14 @@ type Sequence []int
|
||||
|
||||
// Method for printing - sorts the elements before printing
|
||||
func (s Sequence) String() string {
|
||||
sort.IntSlice(s).Sort()
|
||||
sort.IntArray(s).Sort()
|
||||
return fmt.Sprint([]int(s))
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
Now, instead of having <code>Sequence</code> implement multiple
|
||||
interfaces (sorting and printing), we're using the ability of a data item to be
|
||||
converted to multiple types (<code>Sequence</code>, <code>sort.IntSlice</code>
|
||||
converted to multiple types (<code>Sequence</code>, <code>sort.IntArray</code>
|
||||
and <code>[]int</code>), each of which does some part of the job.
|
||||
That's more unusual in practice but can be effective.
|
||||
</p>
|
||||
@@ -1943,53 +1909,42 @@ the rest of the code is unaffected by the change of algorithm.
|
||||
</p>
|
||||
<p>
|
||||
A similar approach allows the streaming cipher algorithms
|
||||
in the various <code>crypto</code> packages to be
|
||||
in the <code>crypto/block</code> package to be
|
||||
separated from the block ciphers they chain together.
|
||||
The <code>Block</code> interface
|
||||
in the <code>crypto/cipher</code> package specifies the
|
||||
behavior of a block cipher, which provides encryption
|
||||
of a single block of data.
|
||||
Then, by analogy with the <code>bufio</code> package,
|
||||
cipher packages that implement this interface
|
||||
can be used to construct streaming ciphers, represented
|
||||
by the <code>Stream</code> interface, without
|
||||
knowing the details of the block encryption.
|
||||
By analogy with the <code>bufio</code> package,
|
||||
they wrap a <code>Cipher</code> interface
|
||||
and return <code>hash.Hash</code>,
|
||||
<code>io.Reader</code>, or <code>io.Writer</code>
|
||||
interface values, not specific implementations.
|
||||
</p>
|
||||
<p>
|
||||
The <code>crypto/cipher</code> interfaces look like this:
|
||||
The interface to <code>crypto/block</code> includes:
|
||||
</p>
|
||||
<pre>
|
||||
type Block interface {
|
||||
type Cipher interface {
|
||||
BlockSize() int
|
||||
Encrypt(src, dst []byte)
|
||||
Decrypt(src, dst []byte)
|
||||
}
|
||||
|
||||
type Stream interface {
|
||||
XORKeyStream(dst, src []byte)
|
||||
}
|
||||
</pre>
|
||||
// NewECBDecrypter returns a reader that reads data
|
||||
// from r and decrypts it using c in electronic codebook (ECB) mode.
|
||||
func NewECBDecrypter(c Cipher, r io.Reader) io.Reader
|
||||
|
||||
<p>
|
||||
Here's the definition of the counter mode (CTR) stream,
|
||||
which turns a block cipher into a streaming cipher; notice
|
||||
that the block cipher's details are abstracted away:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
// NewCTR returns a Stream that encrypts/decrypts using the given Block in
|
||||
// counter mode. The length of iv must be the same as the Block's block size.
|
||||
func NewCTR(block Block, iv []byte) Stream
|
||||
// NewCBCDecrypter returns a reader that reads data
|
||||
// from r and decrypts it using c in cipher block chaining (CBC) mode
|
||||
// with the initialization vector iv.
|
||||
func NewCBCDecrypter(c Cipher, iv []byte, r io.Reader) io.Reader
|
||||
</pre>
|
||||
<p>
|
||||
<code>NewCTR</code> applies not
|
||||
<code>NewECBDecrypter</code> and <code>NewCBCReader</code> apply not
|
||||
just to one specific encryption algorithm and data source but to any
|
||||
implementation of the <code>Block</code> interface and any
|
||||
<code>Stream</code>. Because they return
|
||||
interface values, replacing CTR
|
||||
encryption with other encryption modes is a localized change. The constructor
|
||||
implementation of the <code>Cipher</code> interface and any
|
||||
<code>io.Reader</code>. Because they return <code>io.Reader</code>
|
||||
interface values, replacing ECB
|
||||
encryption with CBC encryption is a localized change. The constructor
|
||||
calls must be edited, but because the surrounding code must treat the result only
|
||||
as a <code>Stream</code>, it won't notice the difference.
|
||||
as an <code>io.Reader</code>, it won't notice the difference.
|
||||
</p>
|
||||
|
||||
<h3 id="interface_methods">Interfaces and methods</h3>
|
||||
@@ -2035,7 +1990,7 @@ func (ctr *Counter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
<code>http.ResponseWriter</code>.)
|
||||
For reference, here's how to attach such a server to a node on the URL tree.
|
||||
<pre>
|
||||
import "net/http"
|
||||
import "http"
|
||||
...
|
||||
ctr := new(Counter)
|
||||
http.Handle("/counter", ctr)
|
||||
@@ -2074,7 +2029,7 @@ It's easy to write a function to print the arguments.
|
||||
</p>
|
||||
<pre>
|
||||
func ArgServer() {
|
||||
for _, s := range os.Args {
|
||||
for i, s := range os.Args {
|
||||
fmt.Println(s)
|
||||
}
|
||||
}
|
||||
@@ -2112,7 +2067,7 @@ to have the right signature.
|
||||
<pre>
|
||||
// Argument server.
|
||||
func ArgServer(w http.ResponseWriter, req *http.Request) {
|
||||
for _, s := range os.Args {
|
||||
for i, s := range os.Args {
|
||||
fmt.Fprintln(w, s)
|
||||
}
|
||||
}
|
||||
@@ -2120,8 +2075,8 @@ func ArgServer(w http.ResponseWriter, req *http.Request) {
|
||||
<p>
|
||||
<code>ArgServer</code> now has same signature as <code>HandlerFunc</code>,
|
||||
so it can be converted to that type to access its methods,
|
||||
just as we converted <code>Sequence</code> to <code>IntSlice</code>
|
||||
to access <code>IntSlice.Sort</code>.
|
||||
just as we converted <code>Sequence</code> to <code>IntArray</code>
|
||||
to access <code>IntArray.Sort</code>.
|
||||
The code to set it up is concise:
|
||||
</p>
|
||||
<pre>
|
||||
@@ -2158,11 +2113,11 @@ here are their definitions.
|
||||
</p>
|
||||
<pre>
|
||||
type Reader interface {
|
||||
Read(p []byte) (n int, err error)
|
||||
Read(p []byte) (n int, err os.Error)
|
||||
}
|
||||
|
||||
type Writer interface {
|
||||
Write(p []byte) (n int, err error)
|
||||
Write(p []byte) (n int, err os.Error)
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
@@ -2224,7 +2179,7 @@ satisfy the <code>io</code> interfaces, we would also need
|
||||
to provide forwarding methods, like this:
|
||||
</p>
|
||||
<pre>
|
||||
func (rw *ReadWriter) Read(p []byte) (n int, err error) {
|
||||
func (rw *ReadWriter) Read(p []byte) (n int, err os.Error) {
|
||||
return rw.reader.Read(p)
|
||||
}
|
||||
</pre>
|
||||
@@ -2357,7 +2312,7 @@ it can also be seen as a type-safe generalization of Unix pipes.
|
||||
They're called <em>goroutines</em> because the existing
|
||||
terms—threads, coroutines, processes, and so on—convey
|
||||
inaccurate connotations. A goroutine has a simple model: it is a
|
||||
function executing concurrently with other goroutines in the same
|
||||
function executing in parallel with other goroutines in the same
|
||||
address space. It is lightweight, costing little more than the
|
||||
allocation of stack space.
|
||||
And the stacks start small, so they are cheap, and grow
|
||||
@@ -2378,12 +2333,12 @@ exits, silently. (The effect is similar to the Unix shell's
|
||||
background.)
|
||||
</p>
|
||||
<pre>
|
||||
go list.Sort() // run list.Sort concurrently; don't wait for it.
|
||||
go list.Sort() // run list.Sort in parallel; don't wait for it.
|
||||
</pre>
|
||||
<p>
|
||||
A function literal can be handy in a goroutine invocation.
|
||||
<pre>
|
||||
func Announce(message string, delay time.Duration) {
|
||||
func Announce(message string, delay int64) {
|
||||
go func() {
|
||||
time.Sleep(delay)
|
||||
fmt.Println(message)
|
||||
@@ -2546,8 +2501,8 @@ system, and there's not a mutex in sight.
|
||||
<p>
|
||||
Another application of these ideas is to parallelize a calculation
|
||||
across multiple CPU cores. If the calculation can be broken into
|
||||
separate pieces that can execute independently, it can be parallelized,
|
||||
with a channel to signal when each piece completes.
|
||||
separate pieces, it can be parallelized, with a channel to signal
|
||||
when each piece completes.
|
||||
</p>
|
||||
<p>
|
||||
Let's say we have an expensive operation to perform on a vector of items,
|
||||
@@ -2589,7 +2544,7 @@ func (v Vector) DoAll(u Vector) {
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
The current implementation of the Go runtime
|
||||
The current implementation of <code>gc</code> (<code>6g</code>, etc.)
|
||||
will not parallelize this code by default.
|
||||
It dedicates only a single core to user-level processing. An
|
||||
arbitrary number of goroutines can be blocked in system calls, but
|
||||
@@ -2599,10 +2554,8 @@ is if you want CPU parallelism you must tell the run-time
|
||||
how many goroutines you want executing code simultaneously. There
|
||||
are two related ways to do this. Either run your job with environment
|
||||
variable <code>GOMAXPROCS</code> set to the number of cores to use
|
||||
or import the <code>runtime</code> package and call
|
||||
(default 1); or import the <code>runtime</code> package and call
|
||||
<code>runtime.GOMAXPROCS(NCPU)</code>.
|
||||
A helpful value might be <code>runtime.NumCPU()</code>, which reports the number
|
||||
of logical CPUs on the local machine.
|
||||
Again, this requirement is expected to be retired as the scheduling and run-time improve.
|
||||
</p>
|
||||
|
||||
@@ -2678,12 +2631,12 @@ the garbage collector for bookkeeping.
|
||||
Library routines must often return some sort of error indication to
|
||||
the caller. As mentioned earlier, Go's multivalue return makes it
|
||||
easy to return a detailed error description alongside the normal
|
||||
return value. By convention, errors have type <code>error</code>,
|
||||
a simple built-in interface.
|
||||
return value. By convention, errors have type <code>os.Error</code>,
|
||||
a simple interface.
|
||||
</p>
|
||||
<pre>
|
||||
type error interface {
|
||||
Error() string
|
||||
type Error interface {
|
||||
String() string
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
@@ -2698,15 +2651,15 @@ For example, <code>os.Open</code> returns an <code>os.PathError</code>.
|
||||
type PathError struct {
|
||||
Op string // "open", "unlink", etc.
|
||||
Path string // The associated file.
|
||||
Err error // Returned by the system call.
|
||||
Error Error // Returned by the system call.
|
||||
}
|
||||
|
||||
func (e *PathError) Error() string {
|
||||
return e.Op + " " + e.Path + ": " + e.Err.Error()
|
||||
func (e *PathError) String() string {
|
||||
return e.Op + " " + e.Path + ": " + e.Error.String()
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
<code>PathError</code>'s <code>Error</code> generates
|
||||
<code>PathError</code>'s <code>String</code> generates
|
||||
a string like this:
|
||||
</p>
|
||||
<pre>
|
||||
@@ -2723,25 +2676,25 @@ it is much more informative than the plain
|
||||
<p>
|
||||
When feasible, error strings should identify their origin, such as by having
|
||||
a prefix naming the package that generated the error. For example, in package
|
||||
<code>image</code>, the string representation for a decoding error due to an
|
||||
unknown format is "image: unknown format".
|
||||
image, the string representation for a decoding error due to an unknown format
|
||||
is "image: unknown format".
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Callers that care about the precise error details can
|
||||
use a type switch or a type assertion to look for specific
|
||||
errors and extract details. For <code>PathErrors</code>
|
||||
this might include examining the internal <code>Err</code>
|
||||
this might include examining the internal <code>Error</code>
|
||||
field for recoverable failures.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
for try := 0; try < 2; try++ {
|
||||
file, err = os.Create(filename)
|
||||
file, err = os.Open(filename)
|
||||
if err == nil {
|
||||
return
|
||||
}
|
||||
if e, ok := err.(*os.PathError); ok && e.Err == syscall.ENOSPC {
|
||||
if e, ok := err.(*os.PathError); ok && e.Error == os.ENOSPC {
|
||||
deleteTempFiles() // Recover some space.
|
||||
continue
|
||||
}
|
||||
@@ -2749,25 +2702,13 @@ for try := 0; try < 2; try++ {
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
The second <code>if</code> statement here is idiomatic Go.
|
||||
The type assertion <code>err.(*os.PathError)</code> is
|
||||
checked with the "comma ok" idiom (mentioned <a href="#maps">earlier</a>
|
||||
in the context of examining maps).
|
||||
If the type assertion fails, <code>ok</code> will be false, and <code>e</code>
|
||||
will be <code>nil</code>.
|
||||
If it succeeds, <code>ok</code> will be true, which means the
|
||||
error was of type <code>*os.PathError</code>, and then so is <code>e</code>,
|
||||
which we can examine for more information about the error.
|
||||
</p>
|
||||
|
||||
<h3 id="panic">Panic</h3>
|
||||
|
||||
<p>
|
||||
The usual way to report an error to a caller is to return an
|
||||
<code>error</code> as an extra return value. The canonical
|
||||
<code>os.Error</code> as an extra return value. The canonical
|
||||
<code>Read</code> method is a well-known instance; it returns a byte
|
||||
count and an <code>error</code>. But what if the error is
|
||||
count and an <code>os.Error</code>. But what if the error is
|
||||
unrecoverable? Sometimes the program simply cannot continue.
|
||||
</p>
|
||||
|
||||
@@ -2786,7 +2727,7 @@ suppresses the usual check for a <code>return</code> statement.
|
||||
<pre>
|
||||
// A toy implementation of cube root using Newton's method.
|
||||
func CubeRoot(x float64) float64 {
|
||||
z := x/3 // Arbitrary initial value
|
||||
z := x/3 // Arbitrary intitial value
|
||||
for i := 0; i < 1e6; i++ {
|
||||
prevz := z
|
||||
z -= (z*z*z-x) / (3*z*z)
|
||||
@@ -2883,14 +2824,14 @@ cleanly by calling <code>panic</code>. We can use that idea to
|
||||
simplify error handling in complex software. Let's look at an
|
||||
idealized excerpt from the <code>regexp</code> package, which reports
|
||||
parsing errors by calling <code>panic</code> with a local
|
||||
error type. Here's the definition of <code>Error</code>,
|
||||
<code>Error</code> type. Here's the definition of <code>Error</code>,
|
||||
an <code>error</code> method, and the <code>Compile</code> function.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
// Error is the type of a parse error; it satisfies the error interface.
|
||||
// Error is the type of a parse error; it satisfies os.Error.
|
||||
type Error string
|
||||
func (e Error) Error() string {
|
||||
func (e Error) String() string {
|
||||
return string(e)
|
||||
}
|
||||
|
||||
@@ -2901,7 +2842,7 @@ func (regexp *Regexp) error(err string) {
|
||||
}
|
||||
|
||||
// Compile returns a parsed representation of the regular expression.
|
||||
func Compile(str string) (regexp *Regexp, err error) {
|
||||
func Compile(str string) (regexp *Regexp, err os.Error) {
|
||||
regexp = new(Regexp)
|
||||
// doParse will panic if there is a parse error.
|
||||
defer func() {
|
||||
@@ -2919,7 +2860,7 @@ If <code>doParse</code> panics, the recovery block will set the
|
||||
return value to <code>nil</code>—deferred functions can modify
|
||||
named return values. It then will then check, in the assignment
|
||||
to <code>err</code>, that the problem was a parse error by asserting
|
||||
that it has the local type <code>Error</code>.
|
||||
that it has type <code>Error</code>.
|
||||
If it does not, the type assertion will fail, causing a run-time error
|
||||
that continues the stack unwinding as though nothing had interrupted
|
||||
it. This check means that if something unexpected happens, such
|
||||
@@ -2937,7 +2878,7 @@ the parse stack by hand.
|
||||
<p>
|
||||
Useful though this pattern is, it should be used only within a package.
|
||||
<code>Parse</code> turns its internal <code>panic</code> calls into
|
||||
<code>error</code> values; it does not expose <code>panics</code>
|
||||
<code>os.Error</code> values; it does not expose <code>panics</code>
|
||||
to its client. That is a good rule to follow.
|
||||
</p>
|
||||
|
||||
@@ -2973,7 +2914,66 @@ for instance, a URL, saving you typing the URL into the phone's tiny keyboard.
|
||||
Here's the complete program.
|
||||
An explanation follows.
|
||||
</p>
|
||||
{{code "/doc/progs/eff_qr.go"}}
|
||||
|
||||
<pre>
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"http"
|
||||
"io"
|
||||
"log"
|
||||
"template"
|
||||
)
|
||||
|
||||
var addr = flag.String("addr", ":1718", "http service address") // Q=17, R=18
|
||||
var fmap = template.FormatterMap{
|
||||
"html": template.HTMLFormatter,
|
||||
"url+html": UrlHtmlFormatter,
|
||||
}
|
||||
var templ = template.MustParse(templateStr, fmap)
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
http.Handle("/", http.HandlerFunc(QR))
|
||||
err := http.ListenAndServe(*addr, nil)
|
||||
if err != nil {
|
||||
log.Fatal("ListenAndServe:", err)
|
||||
}
|
||||
}
|
||||
|
||||
func QR(w http.ResponseWriter, req *http.Request) {
|
||||
templ.Execute(w, req.FormValue("s"))
|
||||
}
|
||||
|
||||
func UrlHtmlFormatter(w io.Writer, fmt string, v ...interface{}) {
|
||||
template.HTMLEscape(w, []byte(http.URLEscape(v[0].(string))))
|
||||
}
|
||||
|
||||
|
||||
const templateStr = `
|
||||
<html>
|
||||
<head>
|
||||
<title>QR Link Generator</title>
|
||||
</head>
|
||||
<body>
|
||||
{.section @}
|
||||
<img src="http://chart.apis.google.com/chart?chs=300x300&cht=qr&choe=UTF-8&chl={@|url+html}"
|
||||
/>
|
||||
<br>
|
||||
{@|html}
|
||||
<br>
|
||||
<br>
|
||||
{.end}
|
||||
<form action="/" name=f method="GET"><input maxLength=1024 size=70
|
||||
name=s value="" title="Text to QR Encode"><input type=submit
|
||||
value="Show QR" name=qr>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
`
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
The pieces up to <code>main</code> should be easy to follow.
|
||||
The one flag sets a default HTTP port for our server. The template
|
||||
@@ -2992,30 +2992,34 @@ server; it blocks while the server runs.
|
||||
executes the template on the data in the form value named <code>s</code>.
|
||||
</p>
|
||||
<p>
|
||||
The template package is powerful;
|
||||
The template package, inspired by <a
|
||||
href="http://code.google.com/p/json-template">json-template</a>, is
|
||||
powerful;
|
||||
this program just touches on its capabilities.
|
||||
In essence, it rewrites a piece of text on the fly by substituting elements derived
|
||||
from data items passed to <code>templ.Execute</code>, in this case the
|
||||
form value.
|
||||
Within the template text (<code>templateStr</code>),
|
||||
double-brace-delimited pieces denote template actions.
|
||||
The piece from <code>{{html "{{if .}}"}}</code>
|
||||
to <code>{{html "{{end}}"}}</code> executes only if the value of the current data item, called <code>.</code> (dot),
|
||||
is non-empty.
|
||||
That is, when the string is empty, this piece of the template is suppressed.
|
||||
brace-delimited pieces denote template actions.
|
||||
The piece from the <code>{.section @}</code>
|
||||
to <code>{.end}</code> executes with the value of the data item <code>@</code>,
|
||||
which is a shorthand for “the current item”, which is the form value.
|
||||
(When the string is empty, this piece of the template is suppressed.)
|
||||
</p>
|
||||
<p>
|
||||
The snippet <code>{{html "{{urlquery .}}"}}</code> says to process the data with the function
|
||||
<code>urlquery</code>, which sanitizes the query string
|
||||
The snippet <code>{@|url+html}</code> says to run the data through the formatter
|
||||
installed in the formatter map (<code>fmap</code>)
|
||||
under the name <code>"url+html"</code>.
|
||||
That is the function <code>UrlHtmlFormatter</code>, which sanitizes the string
|
||||
for safe display on the web page.
|
||||
</p>
|
||||
<p>
|
||||
The rest of the template string is just the HTML to show when the page loads.
|
||||
If this is too quick an explanation, see the <a href="/pkg/text/template/">documentation</a>
|
||||
If this is too quick an explanation, see the <a href="/pkg/template/">documentation</a>
|
||||
for the template package for a more thorough discussion.
|
||||
</p>
|
||||
<p>
|
||||
And there you have it: a useful web server in a few lines of code plus some
|
||||
And there you have it: a useful webserver in a few lines of code plus some
|
||||
data-driven HTML text.
|
||||
Go is powerful enough to make a lot happen in a few lines.
|
||||
</p>
|
||||
|
||||
143
doc/frontpage.css
Normal file
@@ -0,0 +1,143 @@
|
||||
/* Overloads to all.css */
|
||||
#container { width: 76em }
|
||||
.left-column { width: 48%; }
|
||||
.right-column { width: 48%; }
|
||||
|
||||
/* Frontpage styles */
|
||||
#content-introductory code {
|
||||
font-family: "Bitstream Vera Sans Mono", "Andale Mono", monospace;
|
||||
}
|
||||
#content-introductory input, select, textarea {
|
||||
font-family: "Bitstream Vera Sans", Verdana, sans-serif;
|
||||
font-size: 1em;
|
||||
}
|
||||
span.keyword {
|
||||
font-family: Cambria, Georgia, Times, "Times New Roman", serif;
|
||||
font-size: 1.15em;
|
||||
font-style: italic;
|
||||
}
|
||||
#content h3, #content h2 {
|
||||
margin: 0;
|
||||
font-size: 1em;
|
||||
background: none;
|
||||
border: none;
|
||||
padding: 0;
|
||||
}
|
||||
#content .more {
|
||||
color: #999;
|
||||
font-weight: normal;
|
||||
}
|
||||
#frontpage h2#branding-tagline {
|
||||
font-weight: normal;
|
||||
font-style: italic;
|
||||
}
|
||||
#resources {
|
||||
position: relative;
|
||||
margin-top: 1em;
|
||||
}
|
||||
#resources h3 {
|
||||
margin-top: 0;
|
||||
margin-bottom: -.5em;
|
||||
font-size: 1em;
|
||||
font-weight: normal;
|
||||
}
|
||||
#resources-users {
|
||||
float: left;
|
||||
width: 48%;
|
||||
}
|
||||
#resources-contributors {
|
||||
float: right;
|
||||
width: 50%;
|
||||
}
|
||||
#resources ul {
|
||||
padding-left: 2em;
|
||||
}
|
||||
#resources li {
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
#content-rotating {
|
||||
height: 200px;
|
||||
}
|
||||
#content-videos {
|
||||
float: left;
|
||||
width: 170px;
|
||||
}
|
||||
#content-videos .thumbnail {
|
||||
width: 150px;
|
||||
height: 103px;
|
||||
background-repeat: no-repeat;
|
||||
border: none;
|
||||
}
|
||||
#content-videos .thumbnail._001 {
|
||||
background: url(/doc/video-001.png);
|
||||
}
|
||||
#content-videos .thumbnail._002 {
|
||||
background: url(/doc/video-002.png);
|
||||
}
|
||||
#content-videos .thumbnail._003 {
|
||||
background: url(/doc/video-003.png);
|
||||
}
|
||||
#content-videos .thumbnail._004 {
|
||||
background: url(/doc/video-004.png);
|
||||
}
|
||||
#content-videos .thumbnail._005 {
|
||||
background: url(/doc/video-005.jpg);
|
||||
}
|
||||
#content-videos a.video {
|
||||
display: inline-block;
|
||||
width: 150px;
|
||||
margin-right: .30em;
|
||||
margin-top: 1.2em;
|
||||
}
|
||||
#content-videos a.video .caption {
|
||||
display: block;
|
||||
text-align: center;
|
||||
}
|
||||
#content-videos a.video .caption.title {
|
||||
margin-top: .31em;
|
||||
font-weight: bold;
|
||||
}
|
||||
#content-blog ul {
|
||||
margin-top: 1em;
|
||||
margin-left: 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
#content-blog li {
|
||||
list-style: none;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
#content-blog li a {
|
||||
color: #999;
|
||||
text-decoration: none;
|
||||
}
|
||||
#content-blog .date {
|
||||
color: #999;
|
||||
font-size: 0.8em;
|
||||
display: inline-block;
|
||||
margin-left: 0.5em;
|
||||
}
|
||||
#content-blog li a:link .title {
|
||||
color: #04a;
|
||||
}
|
||||
#content-blog li a:visited .title {
|
||||
color: #04a;
|
||||
}
|
||||
#content-blog li a:hover .title {
|
||||
color: #a40;
|
||||
text-decoration: underline;
|
||||
}
|
||||
#content-blog li a:active .title {
|
||||
color: #c00;
|
||||
}
|
||||
.navtop {
|
||||
display: none !important;
|
||||
}
|
||||
.how {
|
||||
float: right;
|
||||
font-size: 75%;
|
||||
}
|
||||
.unsupported {
|
||||
font-weight: bold;
|
||||
color: red;
|
||||
}
|
||||
|
||||
@@ -1,99 +1,92 @@
|
||||
<!--{
|
||||
"Title": "Contributing to the gccgo frontend"
|
||||
}-->
|
||||
<!-- Contributing to the gccgo frontend -->
|
||||
|
||||
<h2>Introduction</h2>
|
||||
|
||||
<p>
|
||||
These are some notes on contributing to the gccgo frontend for GCC.
|
||||
For information on contributing to parts of Go other than gccgo,
|
||||
see <a href="/doc/contribute.html">Contributing to the Go project</a>. For
|
||||
information on building gccgo for yourself,
|
||||
see <a href="/doc/gccgo_install.html">Setting up and using gccgo</a>.
|
||||
These are some notes on contributing to the <code>gccgo</code>
|
||||
frontend for GCC. For information on contributing to parts of Go other
|
||||
than <code>gccgo</code>, see <a href="contribute.html">Contributing to
|
||||
the Go project</a>. For information on building <code>gccgo</code>
|
||||
for yourself, see <a href="gccgo_install.html">Setting up and using
|
||||
gccgo</a>.
|
||||
</p>
|
||||
|
||||
<h2>Legal Prerequisites</h2>
|
||||
|
||||
<p>
|
||||
You must follow the <a href="/doc/contribute.html#copyright">Go copyright
|
||||
rules</a> for all changes to the gccgo frontend and the associated
|
||||
libgo library. Code that is part of GCC rather than gccgo must follow
|
||||
the general <a href="http://gcc.gnu.org/contribute.html">GCC
|
||||
contribution rules</a>.
|
||||
You must follow the <a href="contribute.html#copyright">Go copyright
|
||||
rules.</a>
|
||||
</p>
|
||||
|
||||
<h2>Code</h2>
|
||||
|
||||
<p>
|
||||
The master sources for the gccgo frontend may be found at
|
||||
The source code for the <code>gccgo</code> frontend may be found at
|
||||
<a href="http://code.google.com/p/gofrontend">http://code.google.com/p/gofrontend</a>.
|
||||
The master sources are not buildable by themselves, but only in
|
||||
conjunction with GCC (in the future, other compilers may be
|
||||
supported). Changes made to the gccgo frontend are also applied to
|
||||
the GCC source code repository hosted at <code>gcc.gnu.org</code>. In
|
||||
the <code>gofrontend</code> repository, the <code>go</code> directory
|
||||
is mirrored to the <code>gcc/go/gofrontend</code> directory in the GCC
|
||||
repository, and the <code>gofrontend</code> <code>libgo</code>
|
||||
directory is mirrored to the GCC <code>libgo</code> directory. In
|
||||
addition, the <code>test</code> directory
|
||||
from <a href="http://code.google.com/p/go">the main Go repository</a>
|
||||
is mirrored to the <code>gcc/testsuite/go.test/test</code> directory
|
||||
in the GCC repository.
|
||||
Changes made to that project are routinely merged into the source code
|
||||
hosted at <code>gcc.gnu.org</code>. The <code>gofrontend</code>
|
||||
project includes only the Go frontend proper. These are the files
|
||||
which in the <code>gcc</code> sources may be found in the
|
||||
directories <code>gcc/go</code> and <code>libgo</code>.
|
||||
The <code>gcc</code> sources also include a copy of
|
||||
the <code>test</code> directory
|
||||
from <a href="http://code.google.com/p/go">the main Go repository</a>.
|
||||
|
||||
<p>
|
||||
The frontend is written in C++ and as such the GNU coding standards do
|
||||
not entirely apply; in writing code for the frontend, follow the
|
||||
formatting of the surrounding code. Although the frontend is
|
||||
currently closely tied to the rest of the <code>gcc</code> codebase,
|
||||
we plan to make it more independent. Any new code that uses other
|
||||
parts of <code>gcc</code> should be placed in an appropriate file,
|
||||
such as <code>gogo-tree.cc</code>. Eventually
|
||||
all <code>gcc</code>-specific code should migrate to
|
||||
a <code>gcc-interface</code> subdirectory.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Changes to these directories always flow from the master sources to
|
||||
the GCC repository. The files should never be changed in the GCC
|
||||
repository except by changing them in the master sources and mirroring
|
||||
them.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The gccgo frontend is written in C++. It follows the GNU coding
|
||||
standards to the extent that they apply to C++. In writing code for
|
||||
the frontend, follow the formatting of the surrounding code. Although
|
||||
the frontend is currently tied to the rest of the GCC codebase, we
|
||||
plan to make it more independent. Eventually all GCC-specific code
|
||||
will migrate out of the frontend proper and into GCC proper. In the
|
||||
GCC sources this will generally mean moving code
|
||||
from <code>gcc/go/gofrontend</code> to <code>gcc/go</code>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The run-time library for gccgo is mostly the same as the library
|
||||
in <a href="http://code.google.com/p/go">the main Go repository</a>.
|
||||
The library code in the Go repository is periodically merged into
|
||||
the <code>libgo/go</code> directory of the <code>gofrontend</code> and
|
||||
then the GCC repositories, using the shell
|
||||
script <code>libgo/merge.sh</code>. Accordingly, most library changes
|
||||
should be made in the main Go repository. The files outside
|
||||
of <code>libgo/go</code> are gccgo-specific; that said, some of the
|
||||
files in <code>libgo/runtime</code> are based on files
|
||||
in <code>src/pkg/runtime</code> in the main Go repository.
|
||||
The run-time library for <code>gccgo</code> is mostly the same as the
|
||||
library in <a href="http://code.google.com/p/go">the main Go
|
||||
repository</a>. The library code in the Go repository is periodically
|
||||
copied into the <code>gofrontend</code> and the <code>gcc</code>
|
||||
repositories. Accordingly, most library changes should be made in the
|
||||
main Go repository. Changes to the few <code>gccgo</code>-specific
|
||||
parts of the library should follow the process described here.
|
||||
The <code>gccgo</code>-specific parts of the library are everything in
|
||||
the <code>libgo</code> directory except for the <code>libgo/go</code>
|
||||
subdirectory.
|
||||
</p>
|
||||
|
||||
<h2>Testing</h2>
|
||||
|
||||
<p>
|
||||
All patches must be tested. A patch that introduces new failures is
|
||||
not acceptable.
|
||||
All patches must be tested. There are two test suites. A patch that
|
||||
introduces new failures is not acceptable.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
To run the gccgo test suite, run <code>make check-go</code> in your
|
||||
build directory. This will run various tests
|
||||
under <code>gcc/testsuite/go.*</code> and will also run
|
||||
the <code>libgo</code> testsuite. This copy of the tests from the
|
||||
main Go repository is run using the DejaGNU script found in
|
||||
in <code>gcc/testsuite/go.test/go-test.exp</code>.
|
||||
To run the compiler test suite, run <code>make check-go</code> in the
|
||||
<code>gcc</code> subdirectory of your build directory. This will run
|
||||
various tests underneath <code>gcc/testsuite/go.*</code>. This
|
||||
includes a copy of the tests in the main Go repository, which are run
|
||||
using the DejaGNU script found in
|
||||
in <code>gcc/testsuite/go.test/go-test.exp</code>. Many of the
|
||||
compiler tests may be run without the Go library, but some do require
|
||||
the library to built first.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Most new tests should be submitted to the main Go repository for later
|
||||
mirroring into the GCC repository. If there is a need for specific
|
||||
tests for gccgo, they should go in
|
||||
To run the library test suite, run <code>make
|
||||
check-target-libgo</code> in the top level of your build directory.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Most new tests should be submitted to the main Go repository for
|
||||
copying into the <code>gccgo</code> repository. If there is a need
|
||||
for specific tests for <code>gccgo</code>, they should go in
|
||||
the <code>gcc/testsuite/go.go-torture</code>
|
||||
or <code>gcc/testsuite/go.dg</code> directories in the GCC repository.
|
||||
or <code>gcc/testsuite/go.dg</code> directories in
|
||||
the <code>gcc.gnu.org</code> repository.
|
||||
</p>
|
||||
|
||||
<h2>Submitting Changes</h2>
|
||||
@@ -102,5 +95,5 @@ or <code>gcc/testsuite/go.dg</code> directories in the GCC repository.
|
||||
Changes to the Go frontend should follow the same process as for the
|
||||
main Go repository, only for the <code>gofrontend</code> project
|
||||
rather than the <code>go</code> project. Those changes will then be
|
||||
merged into the GCC sources.
|
||||
merged into the <code>gcc</code> sources.
|
||||
</p>
|
||||
|
||||
@@ -1,63 +1,37 @@
|
||||
<!--{
|
||||
"Title": "Setting up and using gccgo",
|
||||
"Path": "/doc/install/gccgo"
|
||||
}-->
|
||||
<!-- Setting up and using gccgo -->
|
||||
|
||||
<p>
|
||||
This document explains how to use gccgo, a compiler for
|
||||
the Go language. The gccgo compiler is a new frontend
|
||||
for GCC, the widely used GNU compiler. Although the
|
||||
frontend itself is under a BSD-style license, gccgo is
|
||||
normally used as part of GCC and is then covered by
|
||||
This document explains how to use <code>gccgo</code>, a compiler for
|
||||
the Go language. The <code>gccgo</code> compiler is a new frontend
|
||||
for <code>gcc</code>, the widely used GNU compiler. Although the
|
||||
frontend itself is under a BSD-style license, <code>gccgo</code> is
|
||||
normally used as part of <code>gcc</code> and is then covered by
|
||||
the <a href="http://www.gnu.org/licenses/gpl.html">GNU General Public
|
||||
License</a> (the license covers gccgo itself as part of GCC; it
|
||||
does not cover code generated by gccgo).
|
||||
License</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Note that gccgo is not the <code>gc</code> compiler; see
|
||||
the <a href="/doc/install.html">Installing Go</a> instructions for that
|
||||
Note that <code>gccgo</code> is not the <code>6g</code> compiler; see
|
||||
the <a href="install.html">Installing Go</a> instructions for that
|
||||
compiler.
|
||||
</p>
|
||||
|
||||
<h2 id="Releases">Releases</h2>
|
||||
|
||||
<p>
|
||||
The simplest way to install gccgo is to install a GCC binary release
|
||||
built to include Go support. GCC binary releases are available from
|
||||
<a href="http://gcc.gnu.org/install/binaries.html">various
|
||||
websites</a> and are typically included as part of GNU/Linux
|
||||
distributions. We expect that most people who build these binaries
|
||||
will include Go support.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The GCC 4.7.0 release includes Go support that is very close to
|
||||
<a href="/doc/go1.html">Go 1</a>. Due to release timing it will not
|
||||
include the last few changes to the Go 1 libraries. The GCC 4.7.1
|
||||
release should include a complete Go 1 compiler and libraries.
|
||||
</p>
|
||||
|
||||
<h2 id="Source_code">Source code</h2>
|
||||
|
||||
<p>
|
||||
If you cannot use a release, or prefer to build gccgo for
|
||||
yourself,
|
||||
the gccgo source code is accessible via Subversion. The
|
||||
GCC web site
|
||||
The <code>gccgo</code> source code is accessible via Subversion. The
|
||||
<code>gcc</code> web site
|
||||
has <a href="http://gcc.gnu.org/svn.html">instructions for getting the
|
||||
GCC source code</a>. The gccgo source code is included. As a
|
||||
convenience, a stable version of the Go support is available in
|
||||
a branch of the main GCC code
|
||||
<code>gcc</code> source code</a>. The <code>gccgo</code> source code
|
||||
is a branch of the main <code>gcc</code> code
|
||||
repository: <code>svn://gcc.gnu.org/svn/gcc/branches/gccgo</code>.
|
||||
This branch is periodically updated with stable Go compiler sources.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Note that although <code>gcc.gnu.org</code> is the most convenient way
|
||||
to get the source code for the Go frontend, it is not where the master
|
||||
sources live. If you want to contribute changes to the Go frontend
|
||||
compiler, see <a href="/doc/gccgo_contribute.html">Contributing to
|
||||
to get the source code for the compiler, that is not where the master
|
||||
sources live. If you want to contribute changes to the gccgo
|
||||
compiler, see <a href="gccgo_contribute.html">Contributing to
|
||||
gccgo</a>.
|
||||
</p>
|
||||
|
||||
@@ -65,37 +39,29 @@ gccgo</a>.
|
||||
<h2 id="Building">Building</h2>
|
||||
|
||||
<p>
|
||||
Building gccgo is just like building GCC
|
||||
Building <code>gccgo</code> is just like building <code>gcc</code>
|
||||
with one or two additional options. See
|
||||
the <a href="http://gcc.gnu.org/install/">instructions on the gcc web
|
||||
site</a>. When you run <code>configure</code>, add the
|
||||
option <code>--enable-languages=c,c++,go</code> (along with other
|
||||
languages you may want to build). If you are targeting a 32-bit x86,
|
||||
then you will want to build gccgo to default to
|
||||
then you will want to build <code>gccgo</code> to default to
|
||||
supporting locked compare and exchange instructions; do this by also
|
||||
using the <code>configure</code> option <code>--with-arch=i586</code>
|
||||
(or a newer architecture, depending on where you need your programs to
|
||||
run). If you are targeting a 64-bit x86, but sometimes want to use
|
||||
the <code>-m32</code> option, then use the <code>configure</code>
|
||||
option <code>--with-arch-32=i586</code>.
|
||||
run).
|
||||
</p>
|
||||
|
||||
<h3 id="Gold">Gold</h3>
|
||||
|
||||
<p>
|
||||
On x86 GNU/Linux systems the gccgo compiler is able to
|
||||
On x86 GNU/Linux systems the <code>gccgo</code> compiler is able to
|
||||
use a small discontiguous stack for goroutines. This permits programs
|
||||
to run many more goroutines, since each goroutine can use a relatively
|
||||
small stack. Doing this requires using the gold linker version 2.22
|
||||
or later. You can either install GNU binutils 2.22 or later, or you
|
||||
can build gold yourself.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
To build gold yourself, build the GNU binutils,
|
||||
using <code>--enable-gold=default</code> when you run
|
||||
the <code>configure</code> script. Before building, you must install
|
||||
the flex and bison packages. A typical sequence would look like
|
||||
small stack. Doing this requires using a development version of
|
||||
the <code>gold</code> linker. The easiest way to do this is to build
|
||||
the GNU binutils, using <code>--enable-gold</code> when you run
|
||||
the <code>configure</code> script, and to
|
||||
use <code>--with-ld=GOLD_BINARY</code> when you
|
||||
configure <code>gccgo</code>. A typical sequence would look like
|
||||
this (you can replace <code>/opt/gold</code> with any directory to
|
||||
which you have write access):
|
||||
</p>
|
||||
@@ -103,79 +69,38 @@ which you have write access):
|
||||
<pre>
|
||||
cvs -z 9 -d :pserver:anoncvs@sourceware.org:/cvs/src login
|
||||
[password is "anoncvs"]
|
||||
[The next command will create a directory named src, not binutils]
|
||||
cvs -z 9 -d :pserver:anoncvs@sourceware.org:/cvs/src co binutils
|
||||
mkdir binutils-objdir
|
||||
cd binutils-objdir
|
||||
../src/configure --enable-gold=default --prefix=/opt/gold
|
||||
../src/configure --enable-gold --prefix=/opt/gold
|
||||
make
|
||||
make install
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
However you install gold, when you configure gccgo, use the
|
||||
option <code>--with-ld=<var>GOLD_BINARY</var></code>.
|
||||
</p>
|
||||
|
||||
<h3 id="Prerequisites">Prerequisites</h3>
|
||||
|
||||
<p>
|
||||
A number of prerequisites are required to build GCC, as
|
||||
described on
|
||||
the <a href="http://gcc.gnu.org/install/prerequisites.html">gcc web
|
||||
site</a>. It is important to install all the prerequisites before
|
||||
running the gcc <code>configure</code> script.
|
||||
|
||||
<h3 id="Build_commands">Build commands</h3>
|
||||
|
||||
<p>
|
||||
Once all the prerequisites are installed, then a typical build and
|
||||
install sequence would look like this (only use
|
||||
the <code>--with-ld</code> option if you are using the gold linker as
|
||||
described above):
|
||||
A number of prerequisites are required to build <code>gcc</code>, as
|
||||
described on the <a href="http://gcc.gnu.org/">gcc web site</a>. If
|
||||
those are all available, then a typical build and install sequence
|
||||
would look like this (only use the <code>--with-ld</code> option if
|
||||
you built and installed the gold linker as described above):
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
svn checkout svn://gcc.gnu.org/svn/gcc/branches/gccgo gccgo
|
||||
mkdir objdir
|
||||
cd objdir
|
||||
../gccgo/configure --prefix=/opt/gccgo --enable-languages=c,c++,go --with-ld=/opt/gold/bin/ld
|
||||
../gccgo/configure --enable-languages=c,c++,go --with-ld=/opt/gold/bin/ld
|
||||
make
|
||||
make install
|
||||
</pre>
|
||||
|
||||
<h3 id="Ubuntu">A note on Ubuntu</h3>
|
||||
|
||||
<p>
|
||||
Current versions of Ubuntu and current versions of gcc disagree on
|
||||
where system libraries and header files are found. This is not a
|
||||
gccgo issue, and we hope this will be resolved soon. Until it is,
|
||||
setting these environment variables while configuring and building
|
||||
gccgo may fix the problem.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
LIBRARY_PATH=/usr/lib/x86_64-linux-gnu
|
||||
C_INCLUDE_PATH=/usr/include/x86_64-linux-gnu
|
||||
CPLUS_INCLUDE_PATH=/usr/include/x86_64-linux-gnu
|
||||
export LIBRARY_PATH C_INCLUDE_PATH CPLUS_INCLUDE_PATH
|
||||
</pre>
|
||||
|
||||
<h2 id="Using_gccgo">Using gccgo</h2>
|
||||
|
||||
<p>
|
||||
The gccgo compiler works like other gcc frontends. The gccgo
|
||||
installation does not currently include a version of
|
||||
the <code>go</code> command. However if you have the <code>go</code>
|
||||
command from an installation of the <code>gc</code> compiler, you can
|
||||
use it with gccgo by passing the option <code>-compiler gccgo</code>
|
||||
to <code>go build</code> or <code>go install</code> or <code>go
|
||||
test</code>.
|
||||
</p>
|
||||
The <code>gccgo</code> compiler works like other gcc frontends.
|
||||
|
||||
<p>
|
||||
To compile a file without using the <code>go</code> command:
|
||||
</p>
|
||||
To compile a file:
|
||||
|
||||
<pre>
|
||||
gccgo -c file.go
|
||||
@@ -184,7 +109,6 @@ gccgo -c file.go
|
||||
<p>
|
||||
That produces <code>file.o</code>. To link files together to form an
|
||||
executable:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
gccgo -o file file.o
|
||||
@@ -192,68 +116,44 @@ gccgo -o file file.o
|
||||
|
||||
<p>
|
||||
To run the resulting file, you will need to tell the program where to
|
||||
find the compiled Go packages. There are a few ways to do this:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<p>
|
||||
Set the <code>LD_LIBRARY_PATH</code> environment variable:
|
||||
</p>
|
||||
find the compiled Go packages. This can be done either by setting
|
||||
<code>LD_LIBRARY_PATH</code> in your environment:
|
||||
|
||||
<pre>
|
||||
LD_LIBRARY_PATH=${prefix}/lib/gcc/MACHINE/VERSION
|
||||
[or]
|
||||
LD_LIBRARY_PATH=${prefix}/lib64/gcc/MACHINE/VERSION
|
||||
export LD_LIBRARY_PATH
|
||||
LD_LIBRARY_PATH=/usr/lib/gcc/MACHINE/VERSION
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Here <code>${prefix}</code> is the <code>--prefix</code> option used
|
||||
when building gccgo. For a binary install this is
|
||||
normally <code>/usr</code>. Whether to use <code>lib</code>
|
||||
or <code>lib64</code> depends on the target.
|
||||
Typically <code>lib64</code> is correct for x86_64 systems,
|
||||
and <code>lib</code> is correct for other systems. The idea is to
|
||||
name the directory where <code>libgo.so</code> is found.
|
||||
</p>
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<p>
|
||||
Passing a <code>-Wl,-R</code> option when you link:
|
||||
</p>
|
||||
or by passing a <code>-Wl,-R</code> option when you link:
|
||||
|
||||
<pre>
|
||||
gccgo -o file file.o -Wl,-R,${prefix}/lib/gcc/MACHINE/VERSION
|
||||
[or]
|
||||
gccgo -o file file.o -Wl,-R,${prefix}/lib64/gcc/MACHINE/VERSION
|
||||
gccgo -o file file.o -Wl,-R,/usr/lib/gcc/MACHINE/VERSION
|
||||
</pre>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<p>
|
||||
Use the <code>-static-libgo</code> option to link statically against
|
||||
the compiled packages.
|
||||
</p>
|
||||
</li>
|
||||
or you can use the <code>-static-libgo</code> link-time option to link
|
||||
statically against libgo, or you can do a fully static link (static
|
||||
linking is the default for the <code>6l</code> Go linker). On most
|
||||
systems, a static link will look something like:
|
||||
|
||||
<pre>
|
||||
gccgo -o file file.o -static -L /usr/lib/nptl -lgobegin -lgo -lpthread
|
||||
</pre>
|
||||
|
||||
<li>
|
||||
<p>
|
||||
Use the <code>-static</code> option to do a fully static link (the
|
||||
default for the <code>gc</code> compiler).
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
You may get a warning about not creating an <code>.eh_frame_hdr</code>
|
||||
section; this has nothing to do with Go, and may be ignored. In the
|
||||
future the requirement of explicitly specifying
|
||||
<code>-L /usr/lib/nptl -lgobegin -lgo -lpthread</code>
|
||||
may be removed.
|
||||
|
||||
|
||||
<h2 id="Options">Options</h2>
|
||||
|
||||
<p>
|
||||
The gccgo compiler supports all GCC options
|
||||
The <code>gccgo</code> compiler supports all <code>gcc</code> options
|
||||
that are language independent, notably the <code>-O</code>
|
||||
and <code>-g</code> options.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The <code>-fgo-prefix=PREFIX</code> option may be used to set a unique
|
||||
@@ -262,24 +162,28 @@ use with large programs that contain many packages, in order to allow
|
||||
multiple packages to use the same identifier as the package name.
|
||||
The <code>PREFIX</code> may be any string; a good choice for the
|
||||
string is the directory where the package will be installed.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The <code>-fno-require-return-statement</code> option may be used to
|
||||
disable the compiler error about functions missing return statements.
|
||||
Note that there is no way to disable this error in <code>6g</code>.
|
||||
|
||||
<p>
|
||||
The <code>-I</code> and <code>-L</code> options, which are synonyms
|
||||
for the compiler, may be used to set the search path for finding
|
||||
imports.
|
||||
</p>
|
||||
|
||||
|
||||
<h2 id="Imports">Imports</h2>
|
||||
|
||||
<p>
|
||||
When you compile a file that exports something, the export
|
||||
information will be stored directly in the object file. When
|
||||
you import a package, you must tell gccgo how to
|
||||
When you compile a file which exports something, the export
|
||||
information will be stored directly in the object file. When
|
||||
you import a package, you must tell <code>gccgo</code> how to
|
||||
find the file.
|
||||
|
||||
<p>
|
||||
When you import the package <var>FILE</var> with gccgo,
|
||||
When you import the package <var>FILE</var> with <code>gccgo</code>,
|
||||
it will look for the import data in the following files, and use the
|
||||
first one that it finds.
|
||||
|
||||
@@ -294,25 +198,21 @@ first one that it finds.
|
||||
<code><var>FILE</var>.gox</code>, when used, will typically contain
|
||||
nothing but export data. This can be generated from
|
||||
<code><var>FILE</var>.o</code> via
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
objcopy -j .go_export FILE.o FILE.gox
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
The gccgo compiler will look in the current
|
||||
directory for import files. In more complex scenarios you
|
||||
The <code>gccgo</code> compiler will look in the current
|
||||
directory for import files. In more complex scenarios you
|
||||
may pass the <code>-I</code> or <code>-L</code> option to
|
||||
gccgo. Both options take directories to search. The
|
||||
<code>gccgo</code>. Both options take directories to search. The
|
||||
<code>-L</code> option is also passed to the linker.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The gccgo compiler does not currently (2012-03-20) record
|
||||
The <code>gccgo</code> compiler does not currently (2009-11-06) record
|
||||
the file name of imported packages in the object file. You must
|
||||
arrange for the imported data to be linked into the program.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
gccgo -c mypackage.go # Exports mypackage
|
||||
@@ -320,41 +220,48 @@ gccgo -c main.go # Imports mypackage
|
||||
gccgo -o main main.o mypackage.o # Explicitly links with mypackage.o
|
||||
</pre>
|
||||
|
||||
<h2 id="Unimplemented">Unimplemented</h2>
|
||||
|
||||
<p>
|
||||
Some Go features are not yet implemented in <code>gccgo</code>. As of
|
||||
2010-08-23, the following are not implemented:
|
||||
|
||||
<ul>
|
||||
<li>goroutines are implemented as NPTL threads. If you can not use
|
||||
the gold linker as described above, they are created with a fixed
|
||||
stack size, and the number of goroutines that may be created at
|
||||
one time is limited.
|
||||
</ul>
|
||||
|
||||
<h2 id="Debugging">Debugging</h2>
|
||||
|
||||
<p>
|
||||
If you use the <code>-g</code> option when you compile, you can run
|
||||
<code>gdb</code> on your executable. The debugger has only limited
|
||||
knowledge about Go. You can set breakpoints, single-step,
|
||||
<code>gdb</code> on your executable. The debugger doesn't (yet)
|
||||
know anything about Go. However, you can set breakpoints, single-step,
|
||||
etc. You can print variables, but they will be printed as though they
|
||||
had C/C++ types. For numeric types this doesn't matter. Go strings
|
||||
and interfaces will show up as two-element structures. Go
|
||||
maps and channels are always represented as C pointers to run-time
|
||||
structures.
|
||||
</p>
|
||||
had C/C++ types. For numeric types this doesn't matter. Go strings
|
||||
will show up as pointers to structures; to see the value
|
||||
<code>print *stringvar</code>. In general Go strings, maps, channels
|
||||
and interfaces are always represented as C pointers.
|
||||
|
||||
<h2 id="C_Interoperability">C Interoperability</h2>
|
||||
|
||||
<p>
|
||||
When using gccgo there is limited interoperability with C,
|
||||
When using <code>gccgo</code> there is limited interoperability with C,
|
||||
or with C++ code compiled using <code>extern "C"</code>.
|
||||
</p>
|
||||
|
||||
<h3 id="Types">Types</h3>
|
||||
|
||||
<p>
|
||||
Basic types map directly: an <code>int</code> in Go is an <code>int</code>
|
||||
in C, an <code>int32</code> is an <code>int32_t</code>,
|
||||
etc. Go <code>byte</code> is equivalent to C <code>unsigned
|
||||
char</code>.
|
||||
in C, etc. Go <code>byte</code> is equivalent to C <code>unsigned char</code>.
|
||||
Pointers in Go are pointers in C. A Go <code>struct</code> is the same as C
|
||||
<code>struct</code> with the same fields and types.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The Go <code>string</code> type is currently defined as a two-element
|
||||
structure (this is <b style="color: red;">subject to change</b>):
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
struct __go_string {
|
||||
@@ -369,12 +276,10 @@ array in Go is equivalent to a C pointer to the
|
||||
equivalent of the element type.
|
||||
For example, Go <code>*[10]int</code> is equivalent to C <code>int*</code>,
|
||||
assuming that the C pointer does point to 10 elements.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
A slice in Go is a structure. The current definition is
|
||||
(this is <b style="color: red;">subject to change</b>):
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
struct __go_slice {
|
||||
@@ -386,10 +291,9 @@ struct __go_slice {
|
||||
|
||||
<p>
|
||||
The type of a Go function with no receiver is equivalent to a C function
|
||||
whose parameter types are equivalent. When a Go function returns more
|
||||
than one value, the C function returns a struct. For example, these
|
||||
whose parameter types are equivalent. When a Go function returns more
|
||||
than one value, the C function returns a struct. For example, these
|
||||
functions have equivalent types:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
func GoFunction(int) (int, float64)
|
||||
@@ -398,9 +302,7 @@ struct { int i; float64 f; } CFunction(int)
|
||||
|
||||
<p>
|
||||
A pointer to a Go function is equivalent to a pointer to a C function
|
||||
when the functions have equivalent types (this is
|
||||
<b style="color: red;">subject to change</b>).
|
||||
</p>
|
||||
when the functions have equivalent types.
|
||||
|
||||
<p>
|
||||
Go <code>interface</code>, <code>channel</code>, and <code>map</code>
|
||||
@@ -412,7 +314,6 @@ which one is difficult to predict in general; use a cast. C <code>union</code>
|
||||
types have no corresponding Go type. C <code>struct</code> types containing
|
||||
bitfields have no corresponding Go type. C++ <code>class</code> types have
|
||||
no corresponding Go type.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Memory allocation is completely different between C and Go, as Go uses
|
||||
@@ -424,48 +325,43 @@ while the Go side still has a copy the program will fail. When passing a
|
||||
pointer from Go to C, the Go function must retain a visible copy of it in
|
||||
some Go variable. Otherwise the Go garbage collector may delete the
|
||||
pointer while the C function is still using it.
|
||||
</p>
|
||||
|
||||
<h3 id="Function_names">Function names</h3>
|
||||
|
||||
<p>
|
||||
Go code can call C functions directly using a Go extension implemented
|
||||
in gccgo: a function declaration may be preceded by
|
||||
<code>//extern NAME</code>. For example, here is how the C function
|
||||
in <code>gccgo</code>: a function declaration may be followed by
|
||||
<code>__asm__("NAME")</code>. For example, here is how the C function
|
||||
<code>open</code> can be declared in Go:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
//extern open
|
||||
func c_open(name *byte, mode int, perm int) int
|
||||
func c_open(name *byte, mode int, perm int) int __asm__ ("open");
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
The C function naturally expects a NUL-terminated string, which in
|
||||
The C function naturally expects a nul terminated string, which in
|
||||
Go is equivalent to a pointer to an array (not a slice!) of
|
||||
<code>byte</code> with a terminating zero byte. So a sample call
|
||||
from Go would look like (after importing the <code>syscall</code> package):
|
||||
</p>
|
||||
from Go would look like (after importing the <code>os</code> package):
|
||||
|
||||
<pre>
|
||||
var name = [4]byte{'f', 'o', 'o', 0};
|
||||
i := c_open(&name[0], syscall.O_RDONLY, 0);
|
||||
i := c_open(&name[0], os.O_RDONLY, 0);
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
(this serves as an example only, to open a file in Go please use Go's
|
||||
<code>os.Open</code> function instead).
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The name of Go functions accessed from C is subject to change. At present
|
||||
the name of a Go function that does not have a receiver is
|
||||
<code>prefix.package.Functionname</code>. The prefix is set by
|
||||
the <code>-fgo-prefix</code> option used when the package is compiled;
|
||||
if the option is not used, the default is <code>go</code>.
|
||||
if the option is not used, the default is simply <code>go</code>.
|
||||
To call the function from C you must set the name using
|
||||
a GCC extension.
|
||||
</p>
|
||||
a <code>gcc</code> extension similar to the <code>gccgo</code>
|
||||
extension.
|
||||
|
||||
<pre>
|
||||
extern int go_function(int) __asm__ ("myprefix.mypackage.Function");
|
||||
@@ -475,35 +371,37 @@ extern int go_function(int) __asm__ ("myprefix.mypackage.Function");
|
||||
Automatic generation of Go declarations from C source code</h3>
|
||||
|
||||
<p>
|
||||
The Go version of GCC supports automatically generating
|
||||
Go declarations from C code. The facility is rather awkward, and most
|
||||
users should use the <a href="/cmd/cgo">cgo</a> program with
|
||||
the <code>-gccgo</code> option instead.
|
||||
</p>
|
||||
The Go version of <code>gcc</code> supports automatically generating
|
||||
Go declarations from C code. The facility is rather awkward at present,
|
||||
and a better mechanism is under development.
|
||||
|
||||
<p>
|
||||
Compile your C code as usual, and add the option
|
||||
<code>-fdump-go-spec=<var>FILENAME</var></code>. This will create the
|
||||
file <code><var>FILENAME</var></code> as a side effect of the
|
||||
compilation. This file will contain Go declarations for the types,
|
||||
variables and functions declared in the C code. C types that can not
|
||||
be represented in Go will be recorded as comments in the Go code. The
|
||||
generated file will not have a <code>package</code> declaration, but
|
||||
can otherwise be compiled directly by gccgo.
|
||||
</p>
|
||||
Compile your C code as usual, but replace <code>-c</code> with
|
||||
<code>-S -ggo</code>. The result will be an assembler file
|
||||
with a <code>.s</code> extension. This assembler file will contain
|
||||
comments beginning with #GO. Those comments are declarations in the Go
|
||||
language for the C types, variables and functions declared in the C code.
|
||||
C types which can not be represented in Go will contain the string INVALID.
|
||||
Unsupported macro definitions will be recorded as <code>unknowndefine</code>,
|
||||
and uses of <code>#undef</code> will be recorded as <code>undef</code>.
|
||||
So it is very approximately possible to get Go code by running
|
||||
|
||||
<pre>
|
||||
gcc -S -ggo foo.c
|
||||
grep '#GO' foo.s | grep -v INVALID | grep -v unknowndefine | grep -v undef > foo.go
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
This procedure is full of unstated caveats and restrictions and we make no
|
||||
guarantee that it will not change in the future. It is more useful as a
|
||||
starting point for real Go code than as a regular procedure.
|
||||
</p>
|
||||
|
||||
<h2 id="RTEMS_Port">RTEMS Port</h2>
|
||||
<p>
|
||||
The gccgo compiler has been ported to <a href="http://www.rtems.com/">
|
||||
The <code>gccgo</code> compiler has been ported to <a href="http://www.rtems.com/">
|
||||
<code>RTEMS</code></a>. <code>RTEMS</code> is a real-time executive
|
||||
that provides a high performance environment for embedded applications
|
||||
on a range of processors and embedded hardware. The current gccgo
|
||||
on a range of processors and embedded hardware. The current <code>gccgo</code>
|
||||
port is for x86. The goal is to extend the port to most of the
|
||||
<a href="http://www.rtems.org/wiki/index.php/SupportedCPUs">
|
||||
architectures supported by <code>RTEMS</code></a>. For more information on the port,
|
||||
|
||||
|
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 8.6 KiB |
|
Before Width: | Height: | Size: 9.1 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 25 KiB |
2038
doc/go1.html
@@ -1,166 +0,0 @@
|
||||
<!--{
|
||||
"Title": "Go 1 and the Future of Go Programs"
|
||||
}-->
|
||||
|
||||
<h2 id="introduction">Introduction</h2>
|
||||
<p>
|
||||
The release of Go version 1, Go 1 for short, is a major milestone
|
||||
in the development of the language. Go 1 is a stable platform for
|
||||
the growth of programs and projects written in Go.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Go 1 defines two things: first, the specification of the language;
|
||||
and second, the specification of a set of core APIs, the "standard
|
||||
packages" of the Go library. The Go 1 release includes their
|
||||
implementation in the form of two compiler suites (gc and gccgo),
|
||||
and the core libraries themselves.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
It is intended that programs written to the Go 1 specification will
|
||||
continue to compile and run correctly, unchanged, over the lifetime
|
||||
of that specification. At some indefinite point, a Go 2 specification
|
||||
may arise, but until that time, Go programs that work today should
|
||||
continue to work even as future "point" releases of Go 1 arise (Go
|
||||
1.1, Go 1.2, etc.).
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Compatibility is at the source level. Binary compatibility for
|
||||
compiled packages is not guaranteed between releases. After a point
|
||||
release, Go source will need to be recompiled to link against the
|
||||
new release.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The APIs may grow, acquiring new packages and features, but not in
|
||||
a way that breaks existing Go 1 code.
|
||||
</p>
|
||||
|
||||
<h2 id="expectations">Expectations</h2>
|
||||
|
||||
<p>
|
||||
Although we expect that the vast majority of programs will maintain
|
||||
this compatibility over time, it is impossible to guarantee that
|
||||
no future change will break any program. This document is an attempt
|
||||
to set expectations for the compatibility of Go 1 software in the
|
||||
future. There are a number of ways in which a program that compiles
|
||||
and runs today may fail to do so after a future point release. They
|
||||
are all unlikely but worth recording.
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
Security. A security issue in the specification or implementation
|
||||
may come to light whose resolution requires breaking compatibility.
|
||||
We reserve the right to address such security issues.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
Unspecified behavior. The Go specification tries to be explicit
|
||||
about most properties of the language, but there are some aspects
|
||||
that are undefined. Programs that depend on such unspecified behavior
|
||||
may break in future releases.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
Specification errors. If it becomes necessary to address an
|
||||
inconsistency or incompleteness in the specification, resolving the
|
||||
issue could affect the meaning or legality of existing programs.
|
||||
We reserve the right to address such issues, including updating the
|
||||
implementations. Except for security issues, no incompatible changes
|
||||
to the specification would be made.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
Bugs. If a compiler or library has a bug that violates the
|
||||
specification, a program that depends on the buggy behavior may
|
||||
break if the bug is fixed. We reserve the right to fix such bugs.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
Struct literals. For the addition of features in later point
|
||||
releases, it may be necessary to add fields to exported structs in
|
||||
the API. Code that uses untagged struct literals (such as pkg.T{3,
|
||||
"x"}) to create values of these types would fail to compile after
|
||||
such a change. However, code that uses tagged literals (pkg.T{A:
|
||||
3, B: "x"}) will continue to compile after such a change. We will
|
||||
update such data structures in a way that allows tagged struct
|
||||
literals to remain compatible, although untagged literals may fail
|
||||
to compile. (There are also more intricate cases involving nested
|
||||
data structures or interfaces, but they have the same resolution.)
|
||||
We therefore recommend that composite literals whose type is defined
|
||||
in a separate package should use the tagged notation.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
Dot imports. If a program imports a standard package
|
||||
using <code>import . "path"</code>, additional names defined in the
|
||||
imported package in future releases may conflict with other names
|
||||
defined in the program. We do not recommend the use of <code>import .</code>
|
||||
outside of tests, and using it may cause a program to fail
|
||||
to compile in future releases.
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
Of course, for all of these possibilities, should they arise, we
|
||||
would endeavor whenever feasible to update the specification,
|
||||
compilers, or libraries without affecting existing code.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
These same considerations apply to successive point releases. For
|
||||
instance, code that runs under Go 1.2 should be compatible with Go
|
||||
1.2.1, Go 1.3, Go 1.4, etc., although not necessarily with Go 1.1
|
||||
since it may use features added only in Go 1.2
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Features added between releases, available in the source repository
|
||||
but not part of the numbered binary releases, are under active
|
||||
development. No promise of compatibility is made for software using
|
||||
such features until they have been released.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Finally, although it is not a correctness issue, it is possible
|
||||
that the performance of a program may be affected by
|
||||
changes in the implementation of the compilers or libraries upon
|
||||
which it depends.
|
||||
No guarantee can be made about the performance of a
|
||||
given program between releases.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Although these expectations apply to Go 1 itself, we hope similar
|
||||
considerations would be made for the development of externally
|
||||
developed software based on Go 1.
|
||||
</p>
|
||||
|
||||
<h2 id="subrepos">Sub-repositories</h2>
|
||||
|
||||
<p>
|
||||
Code in sub-repositories of the main go tree, such as
|
||||
<a href="http://code.google.com/p/go.net">code.google.com/p/go.net</a>,
|
||||
may be developed under
|
||||
looser compatibility requirements. However, the sub-repositories
|
||||
will be tagged as appropriate to identify versions that are compatible
|
||||
with the Go 1 point releases.
|
||||
</p>
|
||||
|
||||
<h2 id="tools">Tools</h2>
|
||||
|
||||
<p>
|
||||
Finally, the Go tool chain (compilers, linkers, build tools, and so
|
||||
on) are under active development and may change behavior. This
|
||||
means, for instance, that scripts that depend on the location and
|
||||
properties of the tools may be broken by a point release.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
These caveats aside, we believe that Go 1 will be a firm foundation
|
||||
for the development of Go and its ecosystem.
|
||||
</p>
|
||||
677
doc/go_faq.html
707
doc/go_for_cpp_programmers.html
Normal file
@@ -0,0 +1,707 @@
|
||||
<!-- Go For C++ Programmers -->
|
||||
|
||||
<p>
|
||||
Go is a systems programming language intended to be a general-purpose
|
||||
systems language, like C++.
|
||||
These are some notes on Go for experienced C++ programmers. This
|
||||
document discusses the differences between Go and C++, and says little
|
||||
to nothing about the similarities.
|
||||
|
||||
<p>
|
||||
For a more general introduction to Go, see the
|
||||
<a href="go_tutorial.html">Go tutorial</a> and
|
||||
<a href="effective_go.html">Effective Go</a>.
|
||||
|
||||
<p>
|
||||
For a detailed description of the Go language, see the
|
||||
<a href="go_spec.html">Go spec</a>.
|
||||
|
||||
<h2 id="Conceptual_Differences">Conceptual Differences</h2>
|
||||
|
||||
<ul>
|
||||
<li>Go does not have classes with constructors or destructors.
|
||||
Instead of class methods, a class inheritance hierarchy,
|
||||
and virtual functions, Go provides <em>interfaces</em>, which are
|
||||
<a href="#Interfaces">discussed in more detail below</a>.
|
||||
Interfaces are also used where C++ uses templates.
|
||||
|
||||
<li>Go uses garbage collection. It is not necessary (or possible)
|
||||
to release memory explicitly. The garbage collection is (intended to be)
|
||||
incremental and highly efficient on modern processors.
|
||||
|
||||
<li>Go has pointers but not pointer arithmetic. You cannot
|
||||
use a pointer variable to walk through the bytes of a string.
|
||||
|
||||
<li>Arrays in Go are first class values. When an array is used as a
|
||||
function parameter, the function receives a copy of the array, not
|
||||
a pointer to it. However, in practice functions often use slices
|
||||
for parameters; slices hold pointers to underlying arrays. Slices
|
||||
are <a href="#Slices">discussed further below</a>.
|
||||
|
||||
<li>Strings are provided by the language. They may not be changed once they
|
||||
have been created.
|
||||
|
||||
<li>Hash tables are provided by the language. They are called maps.
|
||||
|
||||
<li>Separate threads of execution, and communication channels between
|
||||
them, are provided by the language. This
|
||||
is <a href="#Goroutines">discussed further below</a>.
|
||||
|
||||
<li>Certain types (maps and channels, described further below)
|
||||
are passed by reference, not by value. That is, passing a map to a
|
||||
function does not copy the map, and if the function changes the map
|
||||
the change will be seen by the caller. In C++ terms, one can
|
||||
think of these as being reference types.
|
||||
|
||||
<li>Go does not use header files. Instead, each source file is part of a
|
||||
defined <em>package</em>. When a package defines an object
|
||||
(type, constant, variable, function) with a name starting with an
|
||||
upper case letter, that object is visible to any other file which
|
||||
imports that package.
|
||||
|
||||
<li>Go does not support implicit type conversion. Operations that mix
|
||||
different types require casts (called conversions in Go).
|
||||
|
||||
<li>Go does not support function overloading and does not support user
|
||||
defined operators.
|
||||
|
||||
<li>Go does not support <code>const</code> or <code>volatile</code> qualifiers.
|
||||
|
||||
<li>Go uses <code>nil</code> for invalid pointers, where C++ uses
|
||||
<code>NULL</code> or simply <code>0</code>.
|
||||
</ul>
|
||||
|
||||
<h2 id="Syntax">Syntax</h2>
|
||||
|
||||
<p>
|
||||
The declaration syntax is reversed compared to C++. You write the name
|
||||
followed by the type. Unlike in C++, the syntax for a type does not match
|
||||
the way in which the variable is used. Type declarations may be read
|
||||
easily from left to right.
|
||||
|
||||
<pre>
|
||||
<b>Go C++</b>
|
||||
var v1 int // int v1;
|
||||
var v2 string // const std::string v2; (approximately)
|
||||
var v3 [10]int // int v3[10];
|
||||
var v4 []int // int* v4; (approximately)
|
||||
var v5 struct { f int } // struct { int f; } v5;
|
||||
var v6 *int // int* v6; (but no pointer arithmetic)
|
||||
var v7 map[string]int // unordered_map<string, int>* v7; (approximately)
|
||||
var v8 func(a int) int // int (*v8)(int a);
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Declarations generally take the form of a keyword followed by the name
|
||||
of the object being declared. The keyword is one of <code>var</code>,
|
||||
<code>func</code>,
|
||||
<code>const</code>, or <code>type</code>. Method declarations are a minor
|
||||
exception in that
|
||||
the receiver appears before the name of the object being declared; see
|
||||
the <a href="#Interfaces">discussion of interfaces</a>.
|
||||
|
||||
<p>
|
||||
You can also use a keyword followed by a series of declarations in
|
||||
parentheses.
|
||||
|
||||
<pre>
|
||||
var (
|
||||
i int
|
||||
m float64
|
||||
)
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
When declaring a function, you must either provide a name for each parameter
|
||||
or not provide a name for any parameter; you can't omit some names
|
||||
and provide others. You may group several names with the same type:
|
||||
|
||||
<pre>
|
||||
func f(i, j, k int, s, t string)
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
A variable may be initialized when it is declared. When this is done,
|
||||
specifying the type is permitted but not required. When the type is
|
||||
not specified, the type of the variable is the type of the
|
||||
initialization expression.
|
||||
|
||||
<pre>
|
||||
var v = *p
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
See also the <a href="#Constants">discussion of constants, below</a>.
|
||||
If a variable is not initialized explicitly, the type must be specified.
|
||||
In that case it will be
|
||||
implicitly initialized to the type's zero value (0, nil, etc.). There are no
|
||||
uninitialized variables in Go.
|
||||
|
||||
<p>
|
||||
Within a function, a short declaration syntax is available with
|
||||
<code>:=</code> .
|
||||
|
||||
<pre>
|
||||
v1 := v2
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
This is equivalent to
|
||||
|
||||
<pre>
|
||||
var v1 = v2
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Go permits multiple assignments, which are done in parallel.
|
||||
|
||||
<pre>
|
||||
i, j = j, i // Swap i and j.
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Functions may have multiple return values, indicated by a list in
|
||||
parentheses. The returned values can be stored by assignment
|
||||
to a list of variables.
|
||||
|
||||
<pre>
|
||||
func f() (i int, j int) { ... }
|
||||
v1, v2 = f()
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Go code uses very few semicolons in practice. Technically, all Go
|
||||
statements are terminated by a semicolon. However, Go treats the end
|
||||
of a non-blank line as a semicolon unless the line is clearly
|
||||
incomplete (the exact rules are
|
||||
in <a href="go_spec.html#Semicolons">the language specification</a>).
|
||||
A consequence of this is that in some cases Go does not permit you to
|
||||
use a line break. For example, you may not write
|
||||
<pre>
|
||||
func g()
|
||||
{ // INVALID
|
||||
}
|
||||
</pre>
|
||||
A semicolon will be inserted after <code>g()</code>, causing it to be
|
||||
a function declaration rather than a function definition. Similarly,
|
||||
you may not write
|
||||
<pre>
|
||||
if x {
|
||||
}
|
||||
else { // INVALID
|
||||
}
|
||||
</pre>
|
||||
A semicolon will be inserted after the <code>}</code> preceding
|
||||
the <code>else</code>, causing a syntax error.
|
||||
|
||||
<p>
|
||||
Since semicolons do end statements, you may continue using them as in
|
||||
C++. However, that is not the recommended style. Idiomatic Go code
|
||||
omits unnecessary semicolons, which in practice is all of them other
|
||||
than the initial <code>for</code> loop clause and cases where you want several
|
||||
short statements on a single line.
|
||||
|
||||
<p>
|
||||
While we're on the topic, we recommend that rather than worry about
|
||||
semicolons and brace placement, you format your code with
|
||||
the <code>gofmt</code> program. That will produce a single standard
|
||||
Go style, and let you worry about your code rather than your
|
||||
formatting. While the style may initially seem odd, it is as good as
|
||||
any other style, and familiarity will lead to comfort.
|
||||
|
||||
<p>
|
||||
When using a pointer to a struct, you use <code>.</code> instead
|
||||
of <code>-></code>.
|
||||
Thus syntactically speaking a structure and a pointer to a structure
|
||||
are used in the same way.
|
||||
|
||||
<pre>
|
||||
type myStruct struct { i int }
|
||||
var v9 myStruct // v9 has structure type
|
||||
var p9 *myStruct // p9 is a pointer to a structure
|
||||
f(v9.i, p9.i)
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Go does not require parentheses around the condition of a <code>if</code>
|
||||
statement, or the expressions of a <code>for</code> statement, or the value of a
|
||||
<code>switch</code> statement. On the other hand, it does require curly braces
|
||||
around the body of an <code>if</code> or <code>for</code> statement.
|
||||
|
||||
<pre>
|
||||
if a < b { f() } // Valid
|
||||
if (a < b) { f() } // Valid (condition is a parenthesized expression)
|
||||
if (a < b) f() // INVALID
|
||||
for i = 0; i < 10; i++ {} // Valid
|
||||
for (i = 0; i < 10; i++) {} // INVALID
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Go does not have a <code>while</code> statement nor does it have a
|
||||
<code>do/while</code>
|
||||
statement. The <code>for</code> statement may be used with a single condition,
|
||||
which makes it equivalent to a <code>while</code> statement. Omitting the
|
||||
condition entirely is an endless loop.
|
||||
|
||||
<p>
|
||||
Go permits <code>break</code> and <code>continue</code> to specify a label.
|
||||
The label must
|
||||
refer to a <code>for</code>, <code>switch</code>, or <code>select</code>
|
||||
statement.
|
||||
|
||||
<p>
|
||||
In a <code>switch</code> statement, <code>case</code> labels do not fall
|
||||
through. You can
|
||||
make them fall through using the <code>fallthrough</code> keyword. This applies
|
||||
even to adjacent cases.
|
||||
|
||||
<pre>
|
||||
switch i {
|
||||
case 0: // empty case body
|
||||
case 1:
|
||||
f() // f is not called when i == 0!
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
But a <code>case</code> can have multiple values.
|
||||
|
||||
<pre>
|
||||
switch i {
|
||||
case 0, 1:
|
||||
f() // f is called if i == 0 || i == 1.
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
The values in a <code>case</code> need not be constants—or even integers;
|
||||
any type
|
||||
that supports the equality comparison operator, such as strings or
|
||||
pointers, can be used—and if the <code>switch</code>
|
||||
value is omitted it defaults to <code>true</code>.
|
||||
|
||||
<pre>
|
||||
switch {
|
||||
case i < 0:
|
||||
f1()
|
||||
case i == 0:
|
||||
f2()
|
||||
case i > 0:
|
||||
f3()
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
The <code>++</code> and <code>--</code> operators may only be used in
|
||||
statements, not in expressions.
|
||||
You cannot write <code>c = *p++</code>. <code>*p++</code> is parsed as
|
||||
<code>(*p)++</code>.
|
||||
|
||||
<p>
|
||||
The <code>defer</code> statement may be used to call a function after
|
||||
the function containing the <code>defer</code> statement returns.
|
||||
|
||||
<pre>
|
||||
fd := open("filename")
|
||||
defer close(fd) // fd will be closed when this function returns.
|
||||
</pre>
|
||||
|
||||
<h2 id="Constants">Constants </h2>
|
||||
|
||||
<p>
|
||||
In Go constants may be <i>untyped</i>. This applies even to constants
|
||||
named with a <code>const</code> declaration, if no
|
||||
type is given in the declaration and the initializer expression uses only
|
||||
untyped constants.
|
||||
A value derived from an untyped constant becomes typed when it
|
||||
is used within a context that
|
||||
requires a typed value. This permits constants to be used relatively
|
||||
freely without requiring general implicit type conversion.
|
||||
|
||||
<pre>
|
||||
var a uint
|
||||
f(a + 1) // untyped numeric constant "1" becomes typed as uint
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
The language does not impose any limits on the size of an untyped
|
||||
numeric constant or constant expression. A limit is only applied when
|
||||
a constant is used where a type is required.
|
||||
|
||||
<pre>
|
||||
const huge = 1 << 100
|
||||
f(huge >> 98)
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Go does not support enums. Instead, you can use the special name
|
||||
<code>iota</code> in a single <code>const</code> declaration to get a
|
||||
series of increasing
|
||||
value. When an initialization expression is omitted for a <code>const</code>,
|
||||
it reuses the preceding expression.
|
||||
|
||||
<pre>
|
||||
const (
|
||||
red = iota // red == 0
|
||||
blue // blue == 1
|
||||
green // green == 2
|
||||
)
|
||||
</pre>
|
||||
|
||||
<h2 id="Slices">Slices</h2>
|
||||
|
||||
<p>
|
||||
A slice is conceptually a struct with three fields: a
|
||||
pointer to an array, a length, and a capacity.
|
||||
Slices support
|
||||
the <code>[]</code> operator to access elements of the underlying array.
|
||||
The builtin
|
||||
<code>len</code> function returns the
|
||||
length of the slice. The builtin <code>cap</code> function returns the
|
||||
capacity.
|
||||
|
||||
<p>
|
||||
Given an array, or another slice, a new slice is created via
|
||||
<code>a[I:J]</code>. This
|
||||
creates a new slice which refers to <code>a</code>, starts at
|
||||
index <code>I</code>, and ends before index
|
||||
<code>J</code>. It has length <code>J - I</code>.
|
||||
The new slice refers to the same array
|
||||
to which <code>a</code>
|
||||
refers. That is, changes made using the new slice may be seen using
|
||||
<code>a</code>. The
|
||||
capacity of the new slice is simply the capacity of <code>a</code> minus
|
||||
<code>I</code>. The capacity
|
||||
of an array is the length of the array. You may also assign an array pointer
|
||||
to a variable of slice type; given <code>var s []int; var a[10] int</code>,
|
||||
the assignment <code>s = &a</code> is equivalent to
|
||||
<code>s = a[0:len(a)]</code>.
|
||||
|
||||
<p>
|
||||
What this means is that Go uses slices for some cases where C++ uses pointers.
|
||||
If you create a value of type <code>[100]byte</code> (an array of 100 bytes,
|
||||
perhaps a
|
||||
buffer) and you want to pass it to a function without copying it, you should
|
||||
declare the function parameter to have type <code>[]byte</code>, and pass the
|
||||
address
|
||||
of the array. Unlike in C++, it is not
|
||||
necessary to pass the length of the buffer; it is efficiently accessible via
|
||||
<code>len</code>.
|
||||
|
||||
<p>
|
||||
The slice syntax may also be used with a string. It returns a new string,
|
||||
whose value is a substring of the original string.
|
||||
Because strings are immutable, string slices can be implemented
|
||||
without allocating new storage for the slices's contents.
|
||||
|
||||
<h2 id="Making_values">Making values</h2>
|
||||
|
||||
<p>
|
||||
Go has a builtin function <code>new</code> which takes a type and
|
||||
allocates space
|
||||
on the heap. The allocated space will be zero-initialized for the type.
|
||||
For example, <code>new(int)</code> allocates a new int on the heap,
|
||||
initializes it with the value <code>0</code>,
|
||||
and returns its address, which has type <code>*int</code>.
|
||||
Unlike in C++, <code>new</code> is a function, not an operator;
|
||||
<code>new int</code> is a syntax error.
|
||||
|
||||
<p>
|
||||
Map and channel values must be allocated using the builtin function
|
||||
<code>make</code>.
|
||||
A variable declared with map or channel type without an initializer will be
|
||||
automatically initialized to <code>nil</code>.
|
||||
Calling <code>make(map[int]int)</code> returns a newly allocated value of
|
||||
type <code>map[int]int</code>.
|
||||
Note that <code>make</code> returns a value, not a pointer. This is
|
||||
consistent with
|
||||
the fact that map and channel values are passed by reference. Calling
|
||||
<code>make</code> with
|
||||
a map type takes an optional argument which is the expected capacity of the
|
||||
map. Calling <code>make</code> with a channel type takes an optional
|
||||
argument which sets the
|
||||
buffering capacity of the channel; the default is 0 (unbuffered).
|
||||
|
||||
<p>
|
||||
The <code>make</code> function may also be used to allocate a slice.
|
||||
In this case it
|
||||
allocates memory for the underlying array and returns a slice referring to it.
|
||||
There is one required argument, which is the number of elements in the slice.
|
||||
A second, optional, argument is the capacity of the slice. For example,
|
||||
<code>make([]int, 10, 20)</code>. This is identical to
|
||||
<code>new([20]int)[0:10]</code>. Since
|
||||
Go uses garbage collection, the newly allocated array will be discarded
|
||||
sometime after there are no references to the returned slice.
|
||||
|
||||
<h2 id="Interfaces">Interfaces</h2>
|
||||
|
||||
<p>
|
||||
Where C++ provides classes, subclasses and templates,
|
||||
Go provides interfaces. A
|
||||
Go interface is similar to a C++ pure abstract class: a class with no
|
||||
data members, with methods which are all pure virtual. However, in
|
||||
Go, any type which provides the methods named in the interface may be
|
||||
treated as an implementation of the interface. No explicitly declared
|
||||
inheritance is required. The implementation of the interface is
|
||||
entirely separate from the interface itself.
|
||||
|
||||
<p>
|
||||
A method looks like an ordinary function definition, except that it
|
||||
has a <em>receiver</em>. The receiver is similar to
|
||||
the <code>this</code> pointer in a C++ class method.
|
||||
|
||||
<pre>
|
||||
type myType struct { i int }
|
||||
func (p *myType) get() int { return p.i }
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
This declares a method <code>get</code> associated with <code>myType</code>.
|
||||
The receiver is named <code>p</code> in the body of the function.
|
||||
|
||||
<p>
|
||||
Methods are defined on named types. If you convert the value
|
||||
to a different type, the new value will have the methods of the new type,
|
||||
not the old type.
|
||||
|
||||
<p>
|
||||
You may define methods on a builtin type by declaring a new named type
|
||||
derived from it. The new type is distinct from the builtin type.
|
||||
|
||||
<pre>
|
||||
type myInteger int
|
||||
func (p myInteger) get() int { return int(p) } // Conversion required.
|
||||
func f(i int) { }
|
||||
var v myInteger
|
||||
// f(v) is invalid.
|
||||
// f(int(v)) is valid; int(v) has no defined methods.
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Given this interface:
|
||||
|
||||
<pre>
|
||||
type myInterface interface {
|
||||
get() int
|
||||
set(i int)
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
we can make <code>myType</code> satisfy the interface by adding
|
||||
|
||||
<pre>
|
||||
func (p *myType) set(i int) { p.i = i }
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Now any function which takes <code>myInterface</code> as a parameter
|
||||
will accept a
|
||||
variable of type <code>*myType</code>.
|
||||
|
||||
<pre>
|
||||
func getAndSet(x myInterface) {}
|
||||
func f1() {
|
||||
var p myType
|
||||
getAndSet(&p)
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
In other words, if we view <code>myInterface</code> as a C++ pure abstract
|
||||
base
|
||||
class, defining <code>set</code> and <code>get</code> for
|
||||
<code>*myType</code> made <code>*myType</code> automatically
|
||||
inherit from <code>myInterface</code>. A type may satisfy multiple interfaces.
|
||||
|
||||
<p>
|
||||
An anonymous field may be used to implement something much like a C++ child
|
||||
class.
|
||||
|
||||
<pre>
|
||||
type myChildType struct { myType; j int }
|
||||
func (p *myChildType) get() int { p.j++; return p.myType.get() }
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
This effectively implements <code>myChildType</code> as a child of
|
||||
<code>myType</code>.
|
||||
|
||||
<pre>
|
||||
func f2() {
|
||||
var p myChildType
|
||||
getAndSet(&p)
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
The <code>set</code> method is effectively inherited from
|
||||
<code>myChildType</code>, because
|
||||
methods associated with the anonymous field are promoted to become methods
|
||||
of the enclosing type. In this case, because <code>myChildType</code> has an
|
||||
anonymous field of type <code>myType</code>, the methods of
|
||||
<code>myType</code> also become methods of <code>myChildType</code>.
|
||||
In this example, the <code>get</code> method was
|
||||
overridden, and the <code>set</code> method was inherited.
|
||||
|
||||
<p>
|
||||
This is not precisely the same as a child class in C++.
|
||||
When a method of an anonymous field is called,
|
||||
its receiver is the field, not the surrounding struct.
|
||||
In other words, methods on anonymous fields are not virtual functions.
|
||||
When you want the equivalent of a virtual function, use an interface.
|
||||
|
||||
<p>
|
||||
A variable which has an interface type may be converted to have a
|
||||
different interface type using a special construct called a type assertion.
|
||||
This is implemented dynamically
|
||||
at run time, like C++ <code>dynamic_cast</code>. Unlike
|
||||
<code>dynamic_cast</code>, there does
|
||||
not need to be any declared relationship between the two interfaces.
|
||||
|
||||
<pre>
|
||||
type myPrintInterface interface {
|
||||
print()
|
||||
}
|
||||
func f3(x myInterface) {
|
||||
x.(myPrintInterface).print() // type assertion to myPrintInterface
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
The conversion to <code>myPrintInterface</code> is entirely dynamic.
|
||||
It will
|
||||
work as long as the underlying type of x (the <em>dynamic type</em>) defines
|
||||
a <code>print</code> method.
|
||||
|
||||
<p>
|
||||
Because the conversion is dynamic, it may be used to implement generic
|
||||
programming similar to templates in C++. This is done by
|
||||
manipulating values of the minimal interface.
|
||||
|
||||
<pre>
|
||||
type Any interface { }
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Containers may be written in terms of <code>Any</code>, but the caller
|
||||
must unbox using a type assertion to recover
|
||||
values of the contained type. As the typing is dynamic rather
|
||||
than static, there is no equivalent of the way that a C++ template may
|
||||
inline the relevant operations. The operations are fully type-checked
|
||||
at run time, but all operations will involve a function call.
|
||||
|
||||
<pre>
|
||||
type iterator interface {
|
||||
get() Any
|
||||
set(v Any)
|
||||
increment()
|
||||
equal(arg *iterator) bool
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h2 id="Goroutines">Goroutines</h2>
|
||||
|
||||
<p>
|
||||
Go permits starting a new thread of execution (a <em>goroutine</em>)
|
||||
using the <code>go</code>
|
||||
statement. The <code>go</code> statement runs a function in a
|
||||
different, newly created, goroutine.
|
||||
All goroutines in a single program share the same address space.
|
||||
|
||||
<p>
|
||||
Internally, goroutines act like coroutines that are multiplexed among
|
||||
multiple operating system threads. You do not have to worry
|
||||
about these details.
|
||||
|
||||
<pre>
|
||||
func server(i int) {
|
||||
for {
|
||||
print(i)
|
||||
sys.sleep(10)
|
||||
}
|
||||
}
|
||||
go server(1)
|
||||
go server(2)
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
(Note that the <code>for</code> statement in the <code>server</code>
|
||||
function is equivalent to a C++ <code>while (true)</code> loop.)
|
||||
|
||||
<p>
|
||||
Goroutines are (intended to be) cheap.
|
||||
|
||||
<p>
|
||||
Function literals (which Go implements as closures)
|
||||
can be useful with the <code>go</code> statement.
|
||||
|
||||
<pre>
|
||||
var g int
|
||||
go func(i int) {
|
||||
s := 0
|
||||
for j := 0; j < i; j++ { s += j }
|
||||
g = s
|
||||
}(1000) // Passes argument 1000 to the function literal.
|
||||
</pre>
|
||||
|
||||
<h2 id="Channels">Channels</h2>
|
||||
|
||||
<p>
|
||||
Channels are used to communicate between goroutines. Any value may be
|
||||
sent over a channel. Channels are (intended to be) efficient and
|
||||
cheap. To send a value on a channel, use <code><-</code> as a binary
|
||||
operator. To
|
||||
receive a value on a channel, use <code><-</code> as a unary operator.
|
||||
When calling
|
||||
functions, channels are passed by reference.
|
||||
|
||||
<p>
|
||||
The Go library provides mutexes, but you can also use
|
||||
a single goroutine with a shared channel.
|
||||
Here is an example of using a manager function to control access to a
|
||||
single value.
|
||||
|
||||
<pre>
|
||||
type cmd struct { get bool; val int }
|
||||
func manager(ch chan cmd) {
|
||||
var val int = 0
|
||||
for {
|
||||
c := <- ch
|
||||
if c.get { c.val = val; ch <- c }
|
||||
else { val = c.val }
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
In that example the same channel is used for input and output.
|
||||
This is incorrect if there are multiple goroutines communicating
|
||||
with the manager at once: a goroutine waiting for a response
|
||||
from the manager might receive a request from another goroutine
|
||||
instead.
|
||||
A solution is to pass in a channel.
|
||||
|
||||
<pre>
|
||||
type cmd2 struct { get bool; val int; ch <- chan int }
|
||||
func manager2(ch chan cmd2) {
|
||||
var val int = 0
|
||||
for {
|
||||
c := <- ch
|
||||
if c.get { c.ch <- val }
|
||||
else { val = c.val }
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
To use <code>manager2</code>, given a channel to it:
|
||||
|
||||
<pre>
|
||||
func f4(ch <- chan cmd2) int {
|
||||
myCh := make(chan int)
|
||||
c := cmd2{ true, 0, myCh } // Composite literal syntax.
|
||||
ch <- c
|
||||
return <-myCh
|
||||
}
|
||||
</pre>
|
||||
@@ -1,8 +1,5 @@
|
||||
<!--{
|
||||
"Title": "The Go Memory Model",
|
||||
"Subtitle": "Version of March 6, 2012",
|
||||
"Path": "/ref/mem"
|
||||
}-->
|
||||
<!-- The Go Memory Model -->
|
||||
<!-- subtitle Version of June 10, 2011 -->
|
||||
|
||||
<style>
|
||||
p.rule {
|
||||
@@ -57,7 +54,7 @@ if both of the following hold:
|
||||
</p>
|
||||
|
||||
<ol>
|
||||
<li><span class="event">r</span> does not happen before <span class="event">w</span>.</li>
|
||||
<li><span class="event">w</span> happens before <span class="event">r</span>.</li>
|
||||
<li>There is no other write <span class="event">w'</span> to <code>v</code> that happens
|
||||
after <span class="event">w</span> but before <span class="event">r</span>.</li>
|
||||
</ol>
|
||||
@@ -107,9 +104,9 @@ unspecified order.
|
||||
<h3>Initialization</h3>
|
||||
|
||||
<p>
|
||||
Program initialization runs in a single goroutine,
|
||||
but that goroutine may create other goroutines,
|
||||
which run concurrently.
|
||||
Program initialization runs in a single goroutine and
|
||||
new goroutines created during initialization do not
|
||||
start running until initialization ends.
|
||||
</p>
|
||||
|
||||
<p class="rule">
|
||||
@@ -122,6 +119,11 @@ The start of the function <code>main.main</code> happens after
|
||||
all <code>init</code> functions have finished.
|
||||
</p>
|
||||
|
||||
<p class="rule">
|
||||
The execution of any goroutines created during <code>init</code>
|
||||
functions happens after all <code>init</code> functions have finished.
|
||||
</p>
|
||||
|
||||
<h3>Goroutine creation</h3>
|
||||
|
||||
<p class="rule">
|
||||
@@ -283,7 +285,7 @@ The <code>sync</code> package implements two lock data types,
|
||||
|
||||
<p class="rule">
|
||||
For any <code>sync.Mutex</code> or <code>sync.RWMutex</code> variable <code>l</code> and <i>n</i> < <i>m</i>,
|
||||
call <i>n</i> of <code>l.Unlock()</code> happens before call <i>m</i> of <code>l.Lock()</code> returns.
|
||||
the <i>n</i>'th call to <code>l.Unlock()</code> happens before the <i>m</i>'th call to <code>l.Lock()</code> returns.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
@@ -316,9 +318,9 @@ which happens before the <code>print</code>.
|
||||
|
||||
<p class="rule">
|
||||
For any call to <code>l.RLock</code> on a <code>sync.RWMutex</code> variable <code>l</code>,
|
||||
there is an <i>n</i> such that the <code>l.RLock</code> happens (returns) after call <i>n</i> to
|
||||
there is an <i>n</i> such that the <code>l.RLock</code> happens (returns) after the <i>n</i>'th call to
|
||||
<code>l.Unlock</code> and the matching <code>l.RUnlock</code> happens
|
||||
before call <i>n</i>+1 to <code>l.Lock</code>.
|
||||
before the <i>n</i>+1'th call to <code>l.Lock</code>.
|
||||
</p>
|
||||
|
||||
<h3>Once</h3>
|
||||
|
||||