mirror of
https://github.com/golang/go.git
synced 2026-01-29 15:12:08 +03:00
Compare commits
404 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
30be9b4313 | ||
|
|
2e0e7637c5 | ||
|
|
3f03b6f83a | ||
|
|
6f727ec2a8 | ||
|
|
c2de7b2cd6 | ||
|
|
6ab2bfa952 | ||
|
|
03b13534a6 | ||
|
|
074f8ae030 | ||
|
|
1a2a921f0a | ||
|
|
32d59a576a | ||
|
|
1a18d27e43 | ||
|
|
86f6236205 | ||
|
|
b15e848a2d | ||
|
|
bff99b63f4 | ||
|
|
4ecd79f337 | ||
|
|
c4a12429a7 | ||
|
|
e65172afbe | ||
|
|
c01c6c672d | ||
|
|
a0adc48823 | ||
|
|
4ba17d5097 | ||
|
|
92125eecb5 | ||
|
|
b7f91ba06f | ||
|
|
fc8f4af6b9 | ||
|
|
717f1d6a6c | ||
|
|
ed4d4cb231 | ||
|
|
ec783af29c | ||
|
|
4dfecf3675 | ||
|
|
e4fca6366b | ||
|
|
353788a830 | ||
|
|
a3874a5873 | ||
|
|
75b71e8cae | ||
|
|
bc5b14d00a | ||
|
|
a580f888eb | ||
|
|
0dabae4a85 | ||
|
|
261565842d | ||
|
|
915635ed41 | ||
|
|
0809931b2f | ||
|
|
3e9c29d50f | ||
|
|
56c58e4e5b | ||
|
|
5db7b7524d | ||
|
|
023fbb810d | ||
|
|
0d1bbdf52e | ||
|
|
c57119f04c | ||
|
|
e2ce5a37b1 | ||
|
|
b4724ad7ed | ||
|
|
7da9e79fb3 | ||
|
|
7f2163954d | ||
|
|
e26dc4a8d8 | ||
|
|
e302bba792 | ||
|
|
75d33bc540 | ||
|
|
5b7e9adfc3 | ||
|
|
e09cf61b64 | ||
|
|
42b1754775 | ||
|
|
d6b260855d | ||
|
|
8731f80e9f | ||
|
|
dfd413bda1 | ||
|
|
7ed136f121 | ||
|
|
e412389169 | ||
|
|
ef83c54490 | ||
|
|
9d7ca4b0e6 | ||
|
|
94403eb5d3 | ||
|
|
d340f52100 | ||
|
|
fac6d765df | ||
|
|
7b3dffcfdd | ||
|
|
238c3afd6e | ||
|
|
aec9af0acb | ||
|
|
8851c49989 | ||
|
|
b0f42aa17c | ||
|
|
c9e6f1c069 | ||
|
|
3093d88aa6 | ||
|
|
7102f123cf | ||
|
|
69d7a560e9 | ||
|
|
b19b12b536 | ||
|
|
a3ab361b9c | ||
|
|
7feabb4b94 | ||
|
|
f35d7ff932 | ||
|
|
81d2ac7c5d | ||
|
|
01b381f337 | ||
|
|
2d514df3b3 | ||
|
|
3b332b704b | ||
|
|
2725f37244 | ||
|
|
e4c8a2841c | ||
|
|
686eac5fdd | ||
|
|
e31957cddb | ||
|
|
76d42fbd80 | ||
|
|
17fed3c6b4 | ||
|
|
bf68e33053 | ||
|
|
41f42120a5 | ||
|
|
21bf9e9561 | ||
|
|
5d5b9ef640 | ||
|
|
c7c975809b | ||
|
|
dde4af3655 | ||
|
|
c8ba0a40b4 | ||
|
|
d3f4ba0c71 | ||
|
|
43bf5e8ec8 | ||
|
|
be1207e735 | ||
|
|
ab4821d468 | ||
|
|
b14a4bf211 | ||
|
|
630451ab83 | ||
|
|
a7a74e2011 | ||
|
|
a7f34e69cd | ||
|
|
9810cb4cad | ||
|
|
da6a2756c8 | ||
|
|
602c922095 | ||
|
|
625dea7cba | ||
|
|
e8e3cc97d0 | ||
|
|
ccc55fc069 | ||
|
|
39a2841980 | ||
|
|
c469cb7c5d | ||
|
|
c645541691 | ||
|
|
1a07fca27d | ||
|
|
b1de53a1f0 | ||
|
|
1fe72f034f | ||
|
|
a0e780b7ec | ||
|
|
64a3b18387 | ||
|
|
ab91d4fe2a | ||
|
|
35b989ed7b | ||
|
|
524bb8d755 | ||
|
|
40e77b01f5 | ||
|
|
dda61d68c8 | ||
|
|
6425aa28f2 | ||
|
|
6410538c72 | ||
|
|
bedafd2ddb | ||
|
|
82de010886 | ||
|
|
ed3e546000 | ||
|
|
31f6401799 | ||
|
|
19e7a721ba | ||
|
|
706832a088 | ||
|
|
5f07ee41ea | ||
|
|
2ab2bfaf2f | ||
|
|
56d3f951d1 | ||
|
|
5efc4b03b4 | ||
|
|
1489fd1a3e | ||
|
|
37401b00bf | ||
|
|
9ff8d11c31 | ||
|
|
6601acb041 | ||
|
|
53299c4326 | ||
|
|
8f41e7cd81 | ||
|
|
0db8f6814b | ||
|
|
c9cf888cd2 | ||
|
|
b222c9e39b | ||
|
|
a351c67593 | ||
|
|
6701fa60b6 | ||
|
|
402d6b1f5f | ||
|
|
74282e400c | ||
|
|
d9c11a7164 | ||
|
|
e40fdffc13 | ||
|
|
071933faef | ||
|
|
20ce5bfb6a | ||
|
|
9a0e2e63a3 | ||
|
|
5c47098ec8 | ||
|
|
d88fcebcd8 | ||
|
|
4d5ce93cb9 | ||
|
|
920cc5211e | ||
|
|
d74aea6fdc | ||
|
|
34be79e078 | ||
|
|
aa3ca5f6d7 | ||
|
|
705534bd30 | ||
|
|
ca64251832 | ||
|
|
939e2b572d | ||
|
|
9a1209a215 | ||
|
|
9dec2eb42a | ||
|
|
530d9535c8 | ||
|
|
d251529231 | ||
|
|
0a128f203e | ||
|
|
ba2a1df948 | ||
|
|
e2541bf319 | ||
|
|
4662a76477 | ||
|
|
171e72bf28 | ||
|
|
40b5d5481a | ||
|
|
ecd62d606a | ||
|
|
7d1ddf2b28 | ||
|
|
4b3a35b979 | ||
|
|
759c410691 | ||
|
|
f98661e77e | ||
|
|
731bbfef3b | ||
|
|
9786db83e9 | ||
|
|
df2bb18fae | ||
|
|
e1092f2746 | ||
|
|
118f2163bc | ||
|
|
e3bc1e4206 | ||
|
|
6263484de5 | ||
|
|
f7a20edf47 | ||
|
|
5c990db214 | ||
|
|
7cf931beb0 | ||
|
|
ba76560a34 | ||
|
|
025324f030 | ||
|
|
9c094065d2 | ||
|
|
a2c35039af | ||
|
|
2f34673073 | ||
|
|
81c423a763 | ||
|
|
270db92140 | ||
|
|
ef54d5cff0 | ||
|
|
3b81bac147 | ||
|
|
fd70e5dd66 | ||
|
|
e409b76bb8 | ||
|
|
de4d684429 | ||
|
|
ad8ecb7d82 | ||
|
|
5ba3b575bb | ||
|
|
a1bfd04394 | ||
|
|
4aaf800fd7 | ||
|
|
133727bd0c | ||
|
|
e67e930344 | ||
|
|
4cc0efc468 | ||
|
|
e84e197cca | ||
|
|
fbf580a3bc | ||
|
|
c8e6fca26b | ||
|
|
34141f7c1b | ||
|
|
3046fc9754 | ||
|
|
002a3b4722 | ||
|
|
2eb00d042e | ||
|
|
0352cdb054 | ||
|
|
53538d8ad3 | ||
|
|
69a3887662 | ||
|
|
5557e72b70 | ||
|
|
63608ff3be | ||
|
|
1f107b58f7 | ||
|
|
299e7d20a3 | ||
|
|
4900af0839 | ||
|
|
6e3205f519 | ||
|
|
59db4e26d2 | ||
|
|
2898687794 | ||
|
|
cb71577d10 | ||
|
|
cb6c6570b7 | ||
|
|
d0eabe2bbf | ||
|
|
75fff72d44 | ||
|
|
5d333a6de5 | ||
|
|
596e6f390b | ||
|
|
96ab6e4a84 | ||
|
|
4a0549ffc6 | ||
|
|
95c8f44f3a | ||
|
|
687e047b14 | ||
|
|
2117541627 | ||
|
|
1ddbfeedae | ||
|
|
e819613d08 | ||
|
|
ef902f8c8e | ||
|
|
2c396a8f4a | ||
|
|
5169191e96 | ||
|
|
a2f13c8cf2 | ||
|
|
0d5061ac95 | ||
|
|
61364c1b97 | ||
|
|
a56e41d518 | ||
|
|
4bc9ddf82f | ||
|
|
dc0f7d6fde | ||
|
|
cec2715018 | ||
|
|
24ee3e4eef | ||
|
|
0db7bc2ed8 | ||
|
|
2ed8b2011d | ||
|
|
d261dc39aa | ||
|
|
d4a15ab8ca | ||
|
|
3a9bd603ed | ||
|
|
9f0345c4ec | ||
|
|
0508326926 | ||
|
|
1ba00e32da | ||
|
|
4c35c0b498 | ||
|
|
0a6b1d66f6 | ||
|
|
f384564778 | ||
|
|
47c317c50b | ||
|
|
c30e746666 | ||
|
|
01faffd009 | ||
|
|
8da546a3cf | ||
|
|
95cffc1227 | ||
|
|
c558dc787d | ||
|
|
5fc093e3c0 | ||
|
|
19af0b28c5 | ||
|
|
56ef99d910 | ||
|
|
39c6f00c9a | ||
|
|
f12183ff6a | ||
|
|
c8ba37cf37 | ||
|
|
d0176e77e7 | ||
|
|
35a1aa0420 | ||
|
|
4fcdfe1eb6 | ||
|
|
90f1a852dc | ||
|
|
71b3ca0817 | ||
|
|
6835ec91dd | ||
|
|
920ebab03c | ||
|
|
dfb11495b5 | ||
|
|
73052c1d6c | ||
|
|
c8e2ccdc9c | ||
|
|
ce85383682 | ||
|
|
f5ef888ce9 | ||
|
|
84d3dc5a93 | ||
|
|
ea2a0ad508 | ||
|
|
b260999d4c | ||
|
|
536be05e32 | ||
|
|
7de2fc41a2 | ||
|
|
0d814d213e | ||
|
|
88c11420a3 | ||
|
|
3c10f29757 | ||
|
|
40960a55c3 | ||
|
|
cee42ca53b | ||
|
|
adb732b5fd | ||
|
|
b503008c9d | ||
|
|
03fab00ed0 | ||
|
|
b7250b205a | ||
|
|
603ace6f8a | ||
|
|
aea18fe74b | ||
|
|
eae44968e3 | ||
|
|
f5a5f17847 | ||
|
|
6a87464709 | ||
|
|
ed3ffb7013 | ||
|
|
3d8275cc3a | ||
|
|
8516b743a8 | ||
|
|
c7b02ba811 | ||
|
|
31ccae9af8 | ||
|
|
dcd49f5eaf | ||
|
|
2f89bfbf8e | ||
|
|
0c2ee38a0a | ||
|
|
9fdd043517 | ||
|
|
fd2dfebd88 | ||
|
|
bd0227bbec | ||
|
|
ff5f88f214 | ||
|
|
dc2889c57e | ||
|
|
237b087af6 | ||
|
|
aceb23ef83 | ||
|
|
52b822298e | ||
|
|
a53a74c204 | ||
|
|
87372e839e | ||
|
|
a340c2a131 | ||
|
|
1927afba99 | ||
|
|
cc52fe30c1 | ||
|
|
c60564f59b | ||
|
|
778529bd58 | ||
|
|
3cbadbd631 | ||
|
|
5ccc50c8d6 | ||
|
|
fcfedc0117 | ||
|
|
c08ef1339e | ||
|
|
db26f2a473 | ||
|
|
7a4e18dbe6 | ||
|
|
43f2be4f4b | ||
|
|
2555bbfdd8 | ||
|
|
0b4c5d7946 | ||
|
|
3a3d8826b4 | ||
|
|
ec1cbabbac | ||
|
|
fd30163bdb | ||
|
|
8ac275bb01 | ||
|
|
763858faca | ||
|
|
e983ddae2f | ||
|
|
2cdf371346 | ||
|
|
2a9009f417 | ||
|
|
50be632ee4 | ||
|
|
2fffba7fe1 | ||
|
|
1c15a46489 | ||
|
|
318b29d661 | ||
|
|
c7a1baf1f0 | ||
|
|
19b11c49a9 | ||
|
|
6b8d891e4e | ||
|
|
cbffaffa6d | ||
|
|
8f2d48993a | ||
|
|
a8cea4cda0 | ||
|
|
342f4bf288 | ||
|
|
b4ea696b49 | ||
|
|
c619931610 | ||
|
|
bff1a8a3b1 | ||
|
|
cb6f9ce4c7 | ||
|
|
01dce10cbf | ||
|
|
86990145a6 | ||
|
|
8b5350b8e4 | ||
|
|
802ac98ffc | ||
|
|
554316495f | ||
|
|
69a8369b87 | ||
|
|
56612a5dc8 | ||
|
|
78bf569018 | ||
|
|
5fe252d191 | ||
|
|
dd58503eaf | ||
|
|
5c69520377 | ||
|
|
85a2bbe135 | ||
|
|
65904a75bc | ||
|
|
ad0c81b124 | ||
|
|
30f431fe2e | ||
|
|
e4806c2a18 | ||
|
|
cd73d696d0 | ||
|
|
18a71beb07 | ||
|
|
bde649ca89 | ||
|
|
ec0b7b7de4 | ||
|
|
a200931cae | ||
|
|
01479df5b6 | ||
|
|
610fc6598b | ||
|
|
8f72d82b63 | ||
|
|
4df8143754 | ||
|
|
70e139f3bc | ||
|
|
9b1d0910e1 | ||
|
|
54fc7ef5ad | ||
|
|
41848f960c | ||
|
|
c3882041a9 | ||
|
|
d98b9dac03 | ||
|
|
ca246227a8 | ||
|
|
02c38a83b9 | ||
|
|
6b68716f85 | ||
|
|
eacdcccb9e | ||
|
|
efcd0d5bd8 | ||
|
|
7510885c4d | ||
|
|
b4f17bdf98 | ||
|
|
879f5d9007 | ||
|
|
c50da29f00 | ||
|
|
465aef6f86 | ||
|
|
d9b3c09097 | ||
|
|
931e05acde | ||
|
|
78b1980875 | ||
|
|
8af4ac6444 | ||
|
|
0c34a28d85 | ||
|
|
6d62c5c99a | ||
|
|
6174b5e21e | ||
|
|
4081aa1277 |
38
AUTHORS
38
AUTHORS
@@ -10,38 +10,49 @@
|
||||
|
||||
Abhinav Gupta <abhinav.g90@gmail.com>
|
||||
Adrian O'Grady <elpollouk@gmail.com>
|
||||
Akshat Kumar <seed@mail.nanosouffle.net>
|
||||
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>
|
||||
Amir Mohammad Saied <amir@gluegadget.com>
|
||||
Amrut Joshi <amrut.joshi@gmail.com>
|
||||
Andrei Vieru <euvieru@gmail.com>
|
||||
Andrew Balholm <andybalholm@gmail.com>
|
||||
Andrew Harding <andrew@spacemonkey.com>
|
||||
Andrew Lutomirski <andy@luto.us>
|
||||
Andrew Pritchard <awpritchard@gmail.com>
|
||||
Andrew Skiba <skibaa@gmail.com>
|
||||
Andrew Wilkins <axwalk@gmail.com>
|
||||
Andrey Mirtchovski <mirtchovski@gmail.com>
|
||||
Andy Davis <andy@bigandian.com>
|
||||
Anh Hai Trinh <anh.hai.trinh@gmail.com>
|
||||
Anschel Schaffer-Cohen <anschelsc@gmail.com>
|
||||
Anthony Eufemio <anthony.eufemio@gmail.com>
|
||||
Anthony Martin <ality@pbrane.org>
|
||||
Anthony Starks <ajstarks@gmail.com>
|
||||
Aron Nopanen <aron.nopanen@gmail.com>
|
||||
Arvindh Rajesh Tamilmani <art@a-30.net>
|
||||
Ben Olive <sionide21@gmail.com>
|
||||
Benjamin Black <b@b3k.us>
|
||||
Benny Siegert <bsiegert@gmail.com>
|
||||
Berengar Lehr <berengar.lehr@gmx.de>
|
||||
Brian Dellisanti <briandellisanti@gmail.com>
|
||||
Bjorn Tillenius <bjorn@tillenius.me>
|
||||
Bjorn Tipling <bjorn.tipling@gmail.com>
|
||||
Blake Mizerany <blake.mizerany@gmail.com>
|
||||
Bobby Powers <bobbypowers@gmail.com>
|
||||
Caine Tighe <arctanofyourface@gmail.com>
|
||||
Carlos Castillo <cookieo9@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>
|
||||
Christine Hansmann <chhansmann@gmail.com>
|
||||
Christoph Hack <christoph@tux21b.org>
|
||||
Christopher Nielsen <m4dh4tt3r@gmail.com>
|
||||
Christopher Redden <christopher.redden@gmail.com>
|
||||
@@ -53,6 +64,7 @@ Damian Gryski <dgryski@gmail.com>
|
||||
Dan Sinclair <dan.sinclair@gmail.com>
|
||||
Daniel Fleischman <danielfleischman@gmail.com>
|
||||
Daniel Krech <eikeon@eikeon.com>
|
||||
Daniel Morsing <daniel.morsing@gmail.com>
|
||||
Daniel Theophanes <kardianos@gmail.com>
|
||||
Darren Elwood <darren@textnode.com>
|
||||
Dave Cheney <dave@cheney.net>
|
||||
@@ -69,7 +81,7 @@ 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>
|
||||
Eric Roshan-Eisner <eric.d.eisner@gmail.com>
|
||||
Esko Luontola <esko.luontola@gmail.com>
|
||||
Evan Shaw <chickencha@gmail.com>
|
||||
Fan Hongjian <fan.howard@gmail.com>
|
||||
@@ -93,6 +105,7 @@ Icarus Sparry <golang@icarus.freeuk.com>
|
||||
Ingo Oeser <nightlyone@googlemail.com>
|
||||
Isaac Wagner <ibw@isaacwagner.me>
|
||||
James Fysh <james.fysh@gmail.com>
|
||||
James Gray <james@james4k.com>
|
||||
James Meneghello <rawrz0r@gmail.com>
|
||||
James P. Cooper <jamespcooper@gmail.com>
|
||||
James Toy <nil@opensesame.st>
|
||||
@@ -100,14 +113,17 @@ James Whitehead <jnwhiteh@gmail.com>
|
||||
Jan H. Hosang <jan.hosang@gmail.com>
|
||||
Jan Mercl <befelemepeseveze@gmail.com>
|
||||
Jan Newmarch <jan.newmarch@gmail.com>
|
||||
Jan Ziak <0xe2.0x9a.0x9b@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>
|
||||
Joakim Sernbrant <serbaut@gmail.com>
|
||||
Joe Poirier <jdpoirier@gmail.com>
|
||||
John Asmuth <jasmuth@gmail.com>
|
||||
Jonathan Gold <jgold.bg@gmail.com>
|
||||
Jonathan Mark <jhmark@xenops.com>
|
||||
Jonathan Wills <runningwild@gmail.com>
|
||||
Jongmin Kim <atomaths@gmail.com>
|
||||
@@ -115,6 +131,7 @@ Jose Luis Vázquez González <josvazg@gmail.com>
|
||||
Josh Goebel <dreamer3@gmail.com>
|
||||
Jukka-Pekka Kekkonen <karatepekka@gmail.com>
|
||||
Julian Phillips <julian@quantumfyre.co.uk>
|
||||
Julien Schmidt <google@julienschmidt.com>
|
||||
Kai Backman <kaib@golang.org>
|
||||
Kei Son <hey.calmdown@gmail.com>
|
||||
Keith Rarick <kr@xph.us>
|
||||
@@ -123,19 +140,27 @@ Ken Rockot <ken@oz.gs>
|
||||
Kevin Ballard <kevin@sb.org>
|
||||
Kyle Consalus <consalus@gmail.com>
|
||||
Kyle Lemons <kyle@kylelemons.net>
|
||||
L Campbell <unpantsu@gmail.com>
|
||||
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>
|
||||
Markus Sonderegger <marraison@gmail.com>
|
||||
Martin Neubauer <m.ne@gmx.net>
|
||||
Mateusz Czapliński <czapkofan@gmail.com>
|
||||
Mathieu Lonjaret <mathieu.lonjaret@gmail.com>
|
||||
Mats Lidell <mats.lidell@cag.se>
|
||||
Matt Jibson <matt.jibson@gmail.com>
|
||||
Matthew Horsnell <matthew.horsnell@gmail.com>
|
||||
Micah Stetson <micah.stetson@gmail.com>
|
||||
Michael Chaten <mchaten@gmail.com>
|
||||
Michael Elkins <michael.elkins@gmail.com>
|
||||
Michael Gehring <mg@ebfe.org>
|
||||
Michael Hoisie <hoisie@gmail.com>
|
||||
Michael Lewis <mikelikespie@gmail.com>
|
||||
Michael Stapelberg <michael@stapelberg.de>
|
||||
Michał Derkacz <ziutek@lnet.pl>
|
||||
Miek Gieben <miek@miek.nl>
|
||||
Mikael Tillenius <mikti42@gmail.com>
|
||||
@@ -148,17 +173,22 @@ Môshe van der Sterre <moshevds@gmail.com>
|
||||
ngmoco, LLC
|
||||
Nicholas Waples <nwaples@gmail.com>
|
||||
Nigel Kerr <nigel.kerr@gmail.com>
|
||||
Oling Cat <olingcat@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 Crosby <patrick@stathat.com>
|
||||
Patrick Gavlin <pgavlin@gmail.com>
|
||||
Patrick Higgins <patrick.allen.higgins@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 Armitage <peter.armitage@gmail.com>
|
||||
Peter Froehlich <peter.hans.froehlich@gmail.com>
|
||||
Peter Kleiweg <pkleiweg@xs4all.nl>
|
||||
Peter Mundy <go.peter.90@gmail.com>
|
||||
Peter Williams <pwil3058@gmail.com>
|
||||
Pieter Droogendijk <pieter@binky.org.uk>
|
||||
@@ -180,17 +210,22 @@ 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>
|
||||
Shawn Smith <shawn.p.smith@gmail.com>
|
||||
Shenghou Ma <minux.ma@gmail.com>
|
||||
Spring Mc <heresy.mc@gmail.com>
|
||||
Stefan Nilsson <snilsson@nada.kth.se> <trolleriprofessorn@gmail.com>
|
||||
Stéphane Travostino <stephane.travostino@gmail.com>
|
||||
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>
|
||||
Thomas Alan Copeland <talan.copeland@gmail.com>
|
||||
Timo Savola <timo.savola@gmail.com>
|
||||
Tobias Columbus <tobias.columbus@gmail.com>
|
||||
Tor Andersson <tor.andersson@gmail.com>
|
||||
Ugorji Nwoke <ugorji@gmail.com>
|
||||
Uriel Mangado <uriel@berlinblue.org>
|
||||
Vadim Vygonets <unixdj@gmail.com>
|
||||
Vincent Ambo <tazjin@googlemail.com>
|
||||
Vincent Vanackere <vincent.vanackere@gmail.com>
|
||||
@@ -198,6 +233,7 @@ Vinu Rajashekhar <vinutheraj@gmail.com>
|
||||
Volker Dobler <dr.volker.dobler@gmail.com>
|
||||
Wei Guangjing <vcc.163@gmail.com>
|
||||
William Josephson <wjosephson@gmail.com>
|
||||
Xing Xing <mikespook@gmail.com>
|
||||
Yasuhiro Matsumoto <mattn.jp@gmail.com>
|
||||
Yissakhar Z. Beck <yissakhar.beck@gmail.com>
|
||||
Yongjian Xu <i3dmaster@gmail.com>
|
||||
|
||||
51
CONTRIBUTORS
51
CONTRIBUTORS
@@ -31,9 +31,12 @@
|
||||
|
||||
# Please keep the list sorted.
|
||||
|
||||
Aaron Kemp <kemp.aaron@gmail.com>
|
||||
Abhinav Gupta <abhinav.g90@gmail.com>
|
||||
Adam Langley <agl@golang.org>
|
||||
Adrian O'Grady <elpollouk@gmail.com>
|
||||
Akshat Kumar <seed@mail.nanosouffle.net>
|
||||
Alan Donovan <adonovan@google.com>
|
||||
Albert Strasheim <fullung@gmail.com>
|
||||
Aleksandar Dezelin <dezelin@gmail.com>
|
||||
Alex Brainman <alex.brainman@gmail.com>
|
||||
@@ -41,17 +44,23 @@ Alexander Orlov <alexander.orlov@loxal.net>
|
||||
Alexander Reece <awreece@gmail.com>
|
||||
Alexandru Moșoi <brtzsnr@gmail.com>
|
||||
Alexey Borzenkov <snaury@gmail.com>
|
||||
Amir Mohammad Saied <amir@gluegadget.com>
|
||||
Amrut Joshi <amrut.joshi@gmail.com>
|
||||
Andrea Spadaccini <spadaccio@google.com>
|
||||
Andreas Jellinghaus <andreas@ionisiert.de> <anj@google.com>
|
||||
Andrei Vieru <euvieru@gmail.com>
|
||||
Andrew Balholm <andybalholm@gmail.com>
|
||||
Andrew Gerrand <adg@golang.org>
|
||||
Andrew Harding <andrew@spacemonkey.com>
|
||||
Andrew Lutomirski <andy@luto.us>
|
||||
Andrew Pritchard <awpritchard@gmail.com>
|
||||
Andrew Skiba <skibaa@gmail.com>
|
||||
Andrew Wilkins <axwalk@gmail.com>
|
||||
Andrey Mirtchovski <mirtchovski@gmail.com>
|
||||
Andy Davis <andy@bigandian.com>
|
||||
Anh Hai Trinh <anh.hai.trinh@gmail.com>
|
||||
Anschel Schaffer-Cohen <anschelsc@gmail.com>
|
||||
Anthony Eufemio <anthony.eufemio@gmail.com>
|
||||
Anthony Martin <ality@pbrane.org>
|
||||
Anthony Starks <ajstarks@gmail.com>
|
||||
Aron Nopanen <aron.nopanen@gmail.com>
|
||||
@@ -62,15 +71,21 @@ Ben Eitzen <eitzenb@golang.org>
|
||||
Ben Fried <ben.fried@gmail.com>
|
||||
Ben Lynn <benlynn@gmail.com>
|
||||
Ben Olive <sionide21@gmail.com>
|
||||
Benjamin Black <b@b3k.us>
|
||||
Benny Siegert <bsiegert@gmail.com>
|
||||
Berengar Lehr <Berengar.Lehr@gmx.de>
|
||||
Bill Neubauer <wcn@golang.org> <wcn@google.com>
|
||||
Bill Thiede <couchmoney@gmail.com>
|
||||
Bjorn Tillenius <bjorn@tillenius.me>
|
||||
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>
|
||||
Brian Dellisanti <briandellisanti@gmail.com>
|
||||
Brian Slesinsky <skybrian@google.com>
|
||||
Brendan O'Dea <bod@golang.org>
|
||||
Caine Tighe <arctanofyourface@gmail.com>
|
||||
Carlos Castillo <cookieo9@gmail.com>
|
||||
Cary Hull <chull@google.com>
|
||||
Charles L. Dorian <cldorian@gmail.com>
|
||||
Chris Dollin <ehog.hedge@gmail.com>
|
||||
@@ -79,20 +94,24 @@ 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>
|
||||
Christine Hansmann <chhansmann@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>
|
||||
Colby Ranger <cranger@google.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 Morsing <daniel.morsing@gmail.com>
|
||||
Daniel Nadasi <dnadasi@google.com>
|
||||
Daniel Theophanes <kardianos@gmail.com>
|
||||
Darren Elwood <darren@textnode.com>
|
||||
Dave Borowitz <dborowitz@google.com>
|
||||
Dave Cheney <dave@cheney.net>
|
||||
Dave Grijalva <dgrijalva@ngmoco.com>
|
||||
David Anderson <danderson@google.com>
|
||||
@@ -112,7 +131,7 @@ 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>
|
||||
Eric Roshan-Eisner <eric.d.eisner@gmail.com>
|
||||
Esko Luontola <esko.luontola@gmail.com>
|
||||
Evan Martin <evan.martin@gmail.com>
|
||||
Evan Shaw <chickencha@gmail.com>
|
||||
@@ -121,6 +140,7 @@ 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>
|
||||
Francesc Campoy <campoy@golang.org>
|
||||
Francisco Souza <franciscossouza@gmail.com>
|
||||
Fumitoshi Ukai <ukai@google.com>
|
||||
Gary Burd <gary@beagledreams.com> <gary.burd@gmail.com>
|
||||
@@ -130,6 +150,7 @@ 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>
|
||||
Han-Wen Nienhuys <hanwen@google.com>
|
||||
Harley Laue <losinggeneration@gmail.com>
|
||||
Hector Chu <hectorchu@gmail.com>
|
||||
Hong Ruiqi <hongruiqi@gmail.com>
|
||||
@@ -141,6 +162,7 @@ Ivan Krasin <krasin@golang.org>
|
||||
Jacob Baskin <jbaskin@google.com>
|
||||
James Aguilar <jaguilar@google.com>
|
||||
James Fysh <james.fysh@gmail.com>
|
||||
James Gray <james@james4k.com>
|
||||
James Meneghello <rawrz0r@gmail.com>
|
||||
James P. Cooper <jamespcooper@gmail.com>
|
||||
James Toy <nil@opensesame.st>
|
||||
@@ -149,12 +171,15 @@ Jamie Gennis <jgennis@google.com> <jgennis@gmail.com>
|
||||
Jan H. Hosang <jan.hosang@gmail.com>
|
||||
Jan Mercl <befelemepeseveze@gmail.com>
|
||||
Jan Newmarch <jan.newmarch@gmail.com>
|
||||
Jan Ziak <0xe2.0x9a.0x9b@gmail.com>
|
||||
Jani Monoses <jani.monoses@ubuntu.com> <jani.monoses@gmail.com>
|
||||
Jaroslavas Počepko <jp@webmaster.ms>
|
||||
Jean-Marc Eurin <jmeurin@google.com>
|
||||
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>
|
||||
Joakim Sernbrant <serbaut@gmail.com>
|
||||
Joe Poirier <jdpoirier@gmail.com>
|
||||
Joel Sing <jsing@google.com>
|
||||
Johan Euphrosine <proppy@google.com>
|
||||
@@ -162,6 +187,7 @@ John Asmuth <jasmuth@gmail.com>
|
||||
John Beisley <huin@google.com>
|
||||
John DeNero <denero@google.com>
|
||||
Jonathan Allie <jonallie@google.com>
|
||||
Jonathan Gold <jgold.bg@gmail.com>
|
||||
Jonathan Mark <jhmark@xenops.com> <jhmark000@gmail.com>
|
||||
Jonathan Pittman <jmpittman@google.com> <jonathan.mark.pittman@gmail.com>
|
||||
Jonathan Wills <runningwild@gmail.com>
|
||||
@@ -171,6 +197,7 @@ Jose Luis Vázquez González <josvazg@gmail.com>
|
||||
Josh Goebel <dreamer3@gmail.com>
|
||||
Jukka-Pekka Kekkonen <karatepekka@gmail.com>
|
||||
Julian Phillips <julian@quantumfyre.co.uk>
|
||||
Julien Schmidt <google@julienschmidt.com>
|
||||
Kai Backman <kaib@golang.org>
|
||||
Kei Son <hey.calmdown@gmail.com>
|
||||
Keith Rarick <kr@xph.us>
|
||||
@@ -181,6 +208,7 @@ Kevin Ballard <kevin@sb.org>
|
||||
Kirklin McDonald <kirklin.mcdonald@gmail.com>
|
||||
Kyle Consalus <consalus@gmail.com>
|
||||
Kyle Lemons <kyle@kylelemons.net> <kevlar@google.com>
|
||||
L Campbell <unpantsu@gmail.com>
|
||||
Lai Jiangshan <eag0628@gmail.com>
|
||||
Larry Hosken <lahosken@golang.org>
|
||||
Lorenzo Stoakes <lstoakes@gmail.com>
|
||||
@@ -189,20 +217,28 @@ 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>
|
||||
Manu Garg <manugarg@google.com>
|
||||
Marcel van Lohuizen <mpvl@golang.org>
|
||||
Mark Zavislak <zavislak@google.com>
|
||||
Markus Duft <markus.duft@salomon.at>
|
||||
Markus Sonderegger <marraison@gmail.com>
|
||||
Martin Neubauer <m.ne@gmx.net>
|
||||
Mateusz Czapliński <czapkofan@gmail.com>
|
||||
Mathieu Lonjaret <mathieu.lonjaret@gmail.com>
|
||||
Mats Lidell <mats.lidell@cag.se> <mats.lidell@gmail.com>
|
||||
Matt Jones <mrjones@google.com>
|
||||
Matt Jibson <matt.jibson@gmail.com>
|
||||
Matthew Horsnell <matthew.horsnell@gmail.com>
|
||||
Maxim Pimenov <mpimenov@google.com>
|
||||
Maxim Ushakov <ushakov@google.com>
|
||||
Micah Stetson <micah.stetson@gmail.com>
|
||||
Michael Chaten <mchaten@gmail.com>
|
||||
Michael Elkins <michael.elkins@gmail.com>
|
||||
Michael Gehring <mg@ebfe.org>
|
||||
Michael Hoisie <hoisie@gmail.com>
|
||||
Michael Lewis <mikelikespie@gmail.com>
|
||||
Michael Shields <mshields@google.com>
|
||||
Michael Stapelberg <michael@stapelberg.de> <mstplbrg@googlemail.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>
|
||||
@@ -218,21 +254,27 @@ Môshe van der Sterre <moshevds@gmail.com>
|
||||
Nicholas Waples <nwaples@gmail.com>
|
||||
Nigel Kerr <nigel.kerr@gmail.com>
|
||||
Nigel Tao <nigeltao@golang.org>
|
||||
Oling Cat <olingcat@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 Crosby <patrick@stathat.com>
|
||||
Patrick Gavlin <pgavlin@gmail.com>
|
||||
Patrick Higgins <patrick.allen.higgins@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 Armitage <peter.armitage@gmail.com>
|
||||
Peter Froehlich <peter.hans.froehlich@gmail.com>
|
||||
Peter Kleiweg <pkleiweg@xs4all.nl>
|
||||
Peter McKenzie <petermck@google.com>
|
||||
Peter Mundy <go.peter.90@gmail.com>
|
||||
Péter Szabó <pts@google.com>
|
||||
Peter Weinberger <pjw@golang.org>
|
||||
Peter Williams <pwil3058@gmail.com>
|
||||
Phil Pennock <pdp@golang.org>
|
||||
Pieter Droogendijk <pieter@binky.org.uk>
|
||||
@@ -250,6 +292,7 @@ Roger Peppe <rogpeppe@gmail.com>
|
||||
Ron Minnich <rminnich@gmail.com>
|
||||
Ross Light <rlight2@gmail.com>
|
||||
Russ Cox <rsc@golang.org>
|
||||
Ryan Barrett <ryanb@google.com>
|
||||
Ryan Hitchman <hitchmanr@gmail.com>
|
||||
Sam Thorogood <thorogood@google.com> <sam.thorogood@gmail.com>
|
||||
Sameer Ajmani <sameer@golang.org> <ajmani@gmail.com>
|
||||
@@ -261,9 +304,11 @@ 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>
|
||||
Shawn Smith <shawn.p.smith@gmail.com>
|
||||
Shenghou Ma <minux.ma@gmail.com>
|
||||
Spring Mc <heresy.mc@gmail.com>
|
||||
Stefan Nilsson <snilsson@nada.kth.se> <trolleriprofessorn@gmail.com>
|
||||
Stéphane Travostino <stephane.travostino@gmail.com>
|
||||
Stephen Ma <stephenm@golang.org>
|
||||
Stephen Weinberg <stephen@q5comm.com>
|
||||
Sugu Sougoumarane <ssougou@gmail.com>
|
||||
@@ -271,11 +316,14 @@ Sven Almgren <sven@tras.se>
|
||||
Szabolcs Nagy <nsz@port70.net>
|
||||
Tarmigan Casebolt <tarmigan@gmail.com>
|
||||
Taru Karttunen <taruti@taruti.net>
|
||||
Thomas Alan Copeland <talan.copeland@gmail.com>
|
||||
Timo Savola <timo.savola@gmail.com>
|
||||
Tobias Columbus <tobias.columbus@gmail.com> <tobias.columbus@googlemail.com>
|
||||
Tom Szymanski <tgs@google.com>
|
||||
Tor Andersson <tor.andersson@gmail.com>
|
||||
Trevor Strohman <trevor.strohman@gmail.com>
|
||||
Ugorji Nwoke <ugorji@gmail.com>
|
||||
Uriel Mangado <uriel@berlinblue.org>
|
||||
Vadim Vygonets <unixdj@gmail.com>
|
||||
Vincent Ambo <tazjin@googlemail.com>
|
||||
Vincent Vanackere <vincent.vanackere@gmail.com>
|
||||
@@ -285,6 +333,7 @@ Volker Dobler <dr.volker.dobler@gmail.com>
|
||||
Wei Guangjing <vcc.163@gmail.com>
|
||||
William Chan <willchan@chromium.org>
|
||||
William Josephson <wjosephson@gmail.com>
|
||||
Xing Xing <mikespook@gmail.com>
|
||||
Yasuhiro Matsumoto <mattn.jp@gmail.com>
|
||||
Yissakhar Z. Beck <yissakhar.beck@gmail.com>
|
||||
Yongjian Xu <i3dmaster@gmail.com>
|
||||
|
||||
11
api/README
Normal file
11
api/README
Normal file
@@ -0,0 +1,11 @@
|
||||
Files in this directory are data for Go's API checker ("go tool api", in src/cmd/api).
|
||||
|
||||
Each file is a list of of API features, one per line.
|
||||
|
||||
go1.txt (and similarly named files) are frozen once a version has been
|
||||
shipped. Each file adds new lines but does not remove any.
|
||||
|
||||
next.txt is the only file intended to be mutated. It's a list of
|
||||
features that may be added to the next version. It only affects
|
||||
warning output from the go api tool.
|
||||
|
||||
6296
api/go1.txt
6296
api/go1.txt
File diff suppressed because it is too large
Load Diff
428
api/next.txt
Normal file
428
api/next.txt
Normal file
@@ -0,0 +1,428 @@
|
||||
pkg crypto/tls, const TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA uint16
|
||||
pkg crypto/tls, const TLS_RSA_WITH_AES_256_CBC_SHA uint16
|
||||
pkg crypto/x509, const ECDSA PublicKeyAlgorithm
|
||||
pkg crypto/x509, const ECDSAWithSHA1 SignatureAlgorithm
|
||||
pkg crypto/x509, const ECDSAWithSHA256 SignatureAlgorithm
|
||||
pkg crypto/x509, const ECDSAWithSHA384 SignatureAlgorithm
|
||||
pkg crypto/x509, const ECDSAWithSHA512 SignatureAlgorithm
|
||||
pkg debug/elf, type FileHeader struct, Entry uint64
|
||||
pkg go/doc, var IllegalPrefixes []string
|
||||
pkg math/big, method (*Int) MarshalJSON() ([]byte, error)
|
||||
pkg math/big, method (*Int) UnmarshalJSON([]byte) error
|
||||
pkg regexp/syntax, const ErrUnexpectedParen ErrorCode
|
||||
pkg syscall (darwin-386), const B0 ideal-int
|
||||
pkg syscall (darwin-386), const B110 ideal-int
|
||||
pkg syscall (darwin-386), const B115200 ideal-int
|
||||
pkg syscall (darwin-386), const B1200 ideal-int
|
||||
pkg syscall (darwin-386), const B134 ideal-int
|
||||
pkg syscall (darwin-386), const B14400 ideal-int
|
||||
pkg syscall (darwin-386), const B150 ideal-int
|
||||
pkg syscall (darwin-386), const B1800 ideal-int
|
||||
pkg syscall (darwin-386), const B19200 ideal-int
|
||||
pkg syscall (darwin-386), const B200 ideal-int
|
||||
pkg syscall (darwin-386), const B230400 ideal-int
|
||||
pkg syscall (darwin-386), const B2400 ideal-int
|
||||
pkg syscall (darwin-386), const B28800 ideal-int
|
||||
pkg syscall (darwin-386), const B300 ideal-int
|
||||
pkg syscall (darwin-386), const B38400 ideal-int
|
||||
pkg syscall (darwin-386), const B4800 ideal-int
|
||||
pkg syscall (darwin-386), const B50 ideal-int
|
||||
pkg syscall (darwin-386), const B57600 ideal-int
|
||||
pkg syscall (darwin-386), const B600 ideal-int
|
||||
pkg syscall (darwin-386), const B7200 ideal-int
|
||||
pkg syscall (darwin-386), const B75 ideal-int
|
||||
pkg syscall (darwin-386), const B76800 ideal-int
|
||||
pkg syscall (darwin-386), const B9600 ideal-int
|
||||
pkg syscall (darwin-386), const BRKINT ideal-int
|
||||
pkg syscall (darwin-386), const CFLUSH ideal-int
|
||||
pkg syscall (darwin-386), const CLOCAL ideal-int
|
||||
pkg syscall (darwin-386), const CREAD ideal-int
|
||||
pkg syscall (darwin-386), const CS5 ideal-int
|
||||
pkg syscall (darwin-386), const CS6 ideal-int
|
||||
pkg syscall (darwin-386), const CS7 ideal-int
|
||||
pkg syscall (darwin-386), const CS8 ideal-int
|
||||
pkg syscall (darwin-386), const CSIZE ideal-int
|
||||
pkg syscall (darwin-386), const CSTART ideal-int
|
||||
pkg syscall (darwin-386), const CSTATUS ideal-int
|
||||
pkg syscall (darwin-386), const CSTOP ideal-int
|
||||
pkg syscall (darwin-386), const CSTOPB ideal-int
|
||||
pkg syscall (darwin-386), const CSUSP ideal-int
|
||||
pkg syscall (darwin-386), const FLUSHO ideal-int
|
||||
pkg syscall (darwin-386), const HUPCL ideal-int
|
||||
pkg syscall (darwin-386), const ICANON ideal-int
|
||||
pkg syscall (darwin-386), const ICRNL ideal-int
|
||||
pkg syscall (darwin-386), const IEXTEN ideal-int
|
||||
pkg syscall (darwin-386), const IGNBRK ideal-int
|
||||
pkg syscall (darwin-386), const IGNCR ideal-int
|
||||
pkg syscall (darwin-386), const IGNPAR ideal-int
|
||||
pkg syscall (darwin-386), const IMAXBEL ideal-int
|
||||
pkg syscall (darwin-386), const INLCR ideal-int
|
||||
pkg syscall (darwin-386), const INPCK ideal-int
|
||||
pkg syscall (darwin-386), const ISIG ideal-int
|
||||
pkg syscall (darwin-386), const ISTRIP ideal-int
|
||||
pkg syscall (darwin-386), const IUTF8 ideal-int
|
||||
pkg syscall (darwin-386), const IXANY ideal-int
|
||||
pkg syscall (darwin-386), const IXOFF ideal-int
|
||||
pkg syscall (darwin-386), const IXON ideal-int
|
||||
pkg syscall (darwin-386), const NOFLSH ideal-int
|
||||
pkg syscall (darwin-386), const OCRNL ideal-int
|
||||
pkg syscall (darwin-386), const OFDEL ideal-int
|
||||
pkg syscall (darwin-386), const OFILL ideal-int
|
||||
pkg syscall (darwin-386), const ONLCR ideal-int
|
||||
pkg syscall (darwin-386), const ONLRET ideal-int
|
||||
pkg syscall (darwin-386), const ONOCR ideal-int
|
||||
pkg syscall (darwin-386), const ONOEOT ideal-int
|
||||
pkg syscall (darwin-386), const OPOST ideal-int
|
||||
pkg syscall (darwin-386), const PARENB ideal-int
|
||||
pkg syscall (darwin-386), const PARMRK ideal-int
|
||||
pkg syscall (darwin-386), const PARODD ideal-int
|
||||
pkg syscall (darwin-386), const PENDIN ideal-int
|
||||
pkg syscall (darwin-386), const TCIFLUSH ideal-int
|
||||
pkg syscall (darwin-386), const TCIOFLUSH ideal-int
|
||||
pkg syscall (darwin-386), const TCOFLUSH ideal-int
|
||||
pkg syscall (darwin-386), const TCSAFLUSH ideal-int
|
||||
pkg syscall (darwin-386), const TOSTOP ideal-int
|
||||
pkg syscall (darwin-386), const VDISCARD ideal-int
|
||||
pkg syscall (darwin-386), const VDSUSP ideal-int
|
||||
pkg syscall (darwin-386), const VEOF ideal-int
|
||||
pkg syscall (darwin-386), const VEOL ideal-int
|
||||
pkg syscall (darwin-386), const VEOL2 ideal-int
|
||||
pkg syscall (darwin-386), const VERASE ideal-int
|
||||
pkg syscall (darwin-386), const VINTR ideal-int
|
||||
pkg syscall (darwin-386), const VKILL ideal-int
|
||||
pkg syscall (darwin-386), const VLNEXT ideal-int
|
||||
pkg syscall (darwin-386), const VMIN ideal-int
|
||||
pkg syscall (darwin-386), const VQUIT ideal-int
|
||||
pkg syscall (darwin-386), const VREPRINT ideal-int
|
||||
pkg syscall (darwin-386), const VSTART ideal-int
|
||||
pkg syscall (darwin-386), const VSTATUS ideal-int
|
||||
pkg syscall (darwin-386), const VSTOP ideal-int
|
||||
pkg syscall (darwin-386), const VSUSP ideal-int
|
||||
pkg syscall (darwin-386), const VT0 ideal-int
|
||||
pkg syscall (darwin-386), const VT1 ideal-int
|
||||
pkg syscall (darwin-386), const VTDLY ideal-int
|
||||
pkg syscall (darwin-386), const VTIME ideal-int
|
||||
pkg syscall (darwin-386), const VWERASE ideal-int
|
||||
pkg syscall (darwin-386), type Termios struct
|
||||
pkg syscall (darwin-386), type Termios struct, Cc [20]uint8
|
||||
pkg syscall (darwin-386), type Termios struct, Cflag uint32
|
||||
pkg syscall (darwin-386), type Termios struct, Iflag uint32
|
||||
pkg syscall (darwin-386), type Termios struct, Ispeed uint32
|
||||
pkg syscall (darwin-386), type Termios struct, Lflag uint32
|
||||
pkg syscall (darwin-386), type Termios struct, Oflag uint32
|
||||
pkg syscall (darwin-386), type Termios struct, Ospeed uint32
|
||||
pkg syscall (darwin-386-cgo), const B0 ideal-int
|
||||
pkg syscall (darwin-386-cgo), const B110 ideal-int
|
||||
pkg syscall (darwin-386-cgo), const B115200 ideal-int
|
||||
pkg syscall (darwin-386-cgo), const B1200 ideal-int
|
||||
pkg syscall (darwin-386-cgo), const B134 ideal-int
|
||||
pkg syscall (darwin-386-cgo), const B14400 ideal-int
|
||||
pkg syscall (darwin-386-cgo), const B150 ideal-int
|
||||
pkg syscall (darwin-386-cgo), const B1800 ideal-int
|
||||
pkg syscall (darwin-386-cgo), const B19200 ideal-int
|
||||
pkg syscall (darwin-386-cgo), const B200 ideal-int
|
||||
pkg syscall (darwin-386-cgo), const B230400 ideal-int
|
||||
pkg syscall (darwin-386-cgo), const B2400 ideal-int
|
||||
pkg syscall (darwin-386-cgo), const B28800 ideal-int
|
||||
pkg syscall (darwin-386-cgo), const B300 ideal-int
|
||||
pkg syscall (darwin-386-cgo), const B38400 ideal-int
|
||||
pkg syscall (darwin-386-cgo), const B4800 ideal-int
|
||||
pkg syscall (darwin-386-cgo), const B50 ideal-int
|
||||
pkg syscall (darwin-386-cgo), const B57600 ideal-int
|
||||
pkg syscall (darwin-386-cgo), const B600 ideal-int
|
||||
pkg syscall (darwin-386-cgo), const B7200 ideal-int
|
||||
pkg syscall (darwin-386-cgo), const B75 ideal-int
|
||||
pkg syscall (darwin-386-cgo), const B76800 ideal-int
|
||||
pkg syscall (darwin-386-cgo), const B9600 ideal-int
|
||||
pkg syscall (darwin-386-cgo), const BRKINT ideal-int
|
||||
pkg syscall (darwin-386-cgo), const CFLUSH ideal-int
|
||||
pkg syscall (darwin-386-cgo), const CLOCAL ideal-int
|
||||
pkg syscall (darwin-386-cgo), const CREAD ideal-int
|
||||
pkg syscall (darwin-386-cgo), const CS5 ideal-int
|
||||
pkg syscall (darwin-386-cgo), const CS6 ideal-int
|
||||
pkg syscall (darwin-386-cgo), const CS7 ideal-int
|
||||
pkg syscall (darwin-386-cgo), const CS8 ideal-int
|
||||
pkg syscall (darwin-386-cgo), const CSIZE ideal-int
|
||||
pkg syscall (darwin-386-cgo), const CSTART ideal-int
|
||||
pkg syscall (darwin-386-cgo), const CSTATUS ideal-int
|
||||
pkg syscall (darwin-386-cgo), const CSTOP ideal-int
|
||||
pkg syscall (darwin-386-cgo), const CSTOPB ideal-int
|
||||
pkg syscall (darwin-386-cgo), const CSUSP ideal-int
|
||||
pkg syscall (darwin-386-cgo), const FLUSHO ideal-int
|
||||
pkg syscall (darwin-386-cgo), const HUPCL ideal-int
|
||||
pkg syscall (darwin-386-cgo), const ICANON ideal-int
|
||||
pkg syscall (darwin-386-cgo), const ICRNL ideal-int
|
||||
pkg syscall (darwin-386-cgo), const IEXTEN ideal-int
|
||||
pkg syscall (darwin-386-cgo), const IGNBRK ideal-int
|
||||
pkg syscall (darwin-386-cgo), const IGNCR ideal-int
|
||||
pkg syscall (darwin-386-cgo), const IGNPAR ideal-int
|
||||
pkg syscall (darwin-386-cgo), const IMAXBEL ideal-int
|
||||
pkg syscall (darwin-386-cgo), const INLCR ideal-int
|
||||
pkg syscall (darwin-386-cgo), const INPCK ideal-int
|
||||
pkg syscall (darwin-386-cgo), const ISIG ideal-int
|
||||
pkg syscall (darwin-386-cgo), const ISTRIP ideal-int
|
||||
pkg syscall (darwin-386-cgo), const IUTF8 ideal-int
|
||||
pkg syscall (darwin-386-cgo), const IXANY ideal-int
|
||||
pkg syscall (darwin-386-cgo), const IXOFF ideal-int
|
||||
pkg syscall (darwin-386-cgo), const IXON ideal-int
|
||||
pkg syscall (darwin-386-cgo), const NOFLSH ideal-int
|
||||
pkg syscall (darwin-386-cgo), const OCRNL ideal-int
|
||||
pkg syscall (darwin-386-cgo), const OFDEL ideal-int
|
||||
pkg syscall (darwin-386-cgo), const OFILL ideal-int
|
||||
pkg syscall (darwin-386-cgo), const ONLCR ideal-int
|
||||
pkg syscall (darwin-386-cgo), const ONLRET ideal-int
|
||||
pkg syscall (darwin-386-cgo), const ONOCR ideal-int
|
||||
pkg syscall (darwin-386-cgo), const ONOEOT ideal-int
|
||||
pkg syscall (darwin-386-cgo), const OPOST ideal-int
|
||||
pkg syscall (darwin-386-cgo), const PARENB ideal-int
|
||||
pkg syscall (darwin-386-cgo), const PARMRK ideal-int
|
||||
pkg syscall (darwin-386-cgo), const PARODD ideal-int
|
||||
pkg syscall (darwin-386-cgo), const PENDIN ideal-int
|
||||
pkg syscall (darwin-386-cgo), const TCIFLUSH ideal-int
|
||||
pkg syscall (darwin-386-cgo), const TCIOFLUSH ideal-int
|
||||
pkg syscall (darwin-386-cgo), const TCOFLUSH ideal-int
|
||||
pkg syscall (darwin-386-cgo), const TCSAFLUSH ideal-int
|
||||
pkg syscall (darwin-386-cgo), const TOSTOP ideal-int
|
||||
pkg syscall (darwin-386-cgo), const VDISCARD ideal-int
|
||||
pkg syscall (darwin-386-cgo), const VDSUSP ideal-int
|
||||
pkg syscall (darwin-386-cgo), const VEOF ideal-int
|
||||
pkg syscall (darwin-386-cgo), const VEOL ideal-int
|
||||
pkg syscall (darwin-386-cgo), const VEOL2 ideal-int
|
||||
pkg syscall (darwin-386-cgo), const VERASE ideal-int
|
||||
pkg syscall (darwin-386-cgo), const VINTR ideal-int
|
||||
pkg syscall (darwin-386-cgo), const VKILL ideal-int
|
||||
pkg syscall (darwin-386-cgo), const VLNEXT ideal-int
|
||||
pkg syscall (darwin-386-cgo), const VMIN ideal-int
|
||||
pkg syscall (darwin-386-cgo), const VQUIT ideal-int
|
||||
pkg syscall (darwin-386-cgo), const VREPRINT ideal-int
|
||||
pkg syscall (darwin-386-cgo), const VSTART ideal-int
|
||||
pkg syscall (darwin-386-cgo), const VSTATUS ideal-int
|
||||
pkg syscall (darwin-386-cgo), const VSTOP ideal-int
|
||||
pkg syscall (darwin-386-cgo), const VSUSP ideal-int
|
||||
pkg syscall (darwin-386-cgo), const VT0 ideal-int
|
||||
pkg syscall (darwin-386-cgo), const VT1 ideal-int
|
||||
pkg syscall (darwin-386-cgo), const VTDLY ideal-int
|
||||
pkg syscall (darwin-386-cgo), const VTIME ideal-int
|
||||
pkg syscall (darwin-386-cgo), const VWERASE ideal-int
|
||||
pkg syscall (darwin-386-cgo), type Termios struct
|
||||
pkg syscall (darwin-386-cgo), type Termios struct, Cc [20]uint8
|
||||
pkg syscall (darwin-386-cgo), type Termios struct, Cflag uint32
|
||||
pkg syscall (darwin-386-cgo), type Termios struct, Iflag uint32
|
||||
pkg syscall (darwin-386-cgo), type Termios struct, Ispeed uint32
|
||||
pkg syscall (darwin-386-cgo), type Termios struct, Lflag uint32
|
||||
pkg syscall (darwin-386-cgo), type Termios struct, Oflag uint32
|
||||
pkg syscall (darwin-386-cgo), type Termios struct, Ospeed uint32
|
||||
pkg syscall (darwin-amd64), const B0 ideal-int
|
||||
pkg syscall (darwin-amd64), const B110 ideal-int
|
||||
pkg syscall (darwin-amd64), const B115200 ideal-int
|
||||
pkg syscall (darwin-amd64), const B1200 ideal-int
|
||||
pkg syscall (darwin-amd64), const B134 ideal-int
|
||||
pkg syscall (darwin-amd64), const B14400 ideal-int
|
||||
pkg syscall (darwin-amd64), const B150 ideal-int
|
||||
pkg syscall (darwin-amd64), const B1800 ideal-int
|
||||
pkg syscall (darwin-amd64), const B19200 ideal-int
|
||||
pkg syscall (darwin-amd64), const B200 ideal-int
|
||||
pkg syscall (darwin-amd64), const B230400 ideal-int
|
||||
pkg syscall (darwin-amd64), const B2400 ideal-int
|
||||
pkg syscall (darwin-amd64), const B28800 ideal-int
|
||||
pkg syscall (darwin-amd64), const B300 ideal-int
|
||||
pkg syscall (darwin-amd64), const B38400 ideal-int
|
||||
pkg syscall (darwin-amd64), const B4800 ideal-int
|
||||
pkg syscall (darwin-amd64), const B50 ideal-int
|
||||
pkg syscall (darwin-amd64), const B57600 ideal-int
|
||||
pkg syscall (darwin-amd64), const B600 ideal-int
|
||||
pkg syscall (darwin-amd64), const B7200 ideal-int
|
||||
pkg syscall (darwin-amd64), const B75 ideal-int
|
||||
pkg syscall (darwin-amd64), const B76800 ideal-int
|
||||
pkg syscall (darwin-amd64), const B9600 ideal-int
|
||||
pkg syscall (darwin-amd64), const BRKINT ideal-int
|
||||
pkg syscall (darwin-amd64), const CFLUSH ideal-int
|
||||
pkg syscall (darwin-amd64), const CLOCAL ideal-int
|
||||
pkg syscall (darwin-amd64), const CREAD ideal-int
|
||||
pkg syscall (darwin-amd64), const CS5 ideal-int
|
||||
pkg syscall (darwin-amd64), const CS6 ideal-int
|
||||
pkg syscall (darwin-amd64), const CS7 ideal-int
|
||||
pkg syscall (darwin-amd64), const CS8 ideal-int
|
||||
pkg syscall (darwin-amd64), const CSIZE ideal-int
|
||||
pkg syscall (darwin-amd64), const CSTART ideal-int
|
||||
pkg syscall (darwin-amd64), const CSTATUS ideal-int
|
||||
pkg syscall (darwin-amd64), const CSTOP ideal-int
|
||||
pkg syscall (darwin-amd64), const CSTOPB ideal-int
|
||||
pkg syscall (darwin-amd64), const CSUSP ideal-int
|
||||
pkg syscall (darwin-amd64), const FLUSHO ideal-int
|
||||
pkg syscall (darwin-amd64), const HUPCL ideal-int
|
||||
pkg syscall (darwin-amd64), const ICANON ideal-int
|
||||
pkg syscall (darwin-amd64), const ICRNL ideal-int
|
||||
pkg syscall (darwin-amd64), const IEXTEN ideal-int
|
||||
pkg syscall (darwin-amd64), const IGNBRK ideal-int
|
||||
pkg syscall (darwin-amd64), const IGNCR ideal-int
|
||||
pkg syscall (darwin-amd64), const IGNPAR ideal-int
|
||||
pkg syscall (darwin-amd64), const IMAXBEL ideal-int
|
||||
pkg syscall (darwin-amd64), const INLCR ideal-int
|
||||
pkg syscall (darwin-amd64), const INPCK ideal-int
|
||||
pkg syscall (darwin-amd64), const ISIG ideal-int
|
||||
pkg syscall (darwin-amd64), const ISTRIP ideal-int
|
||||
pkg syscall (darwin-amd64), const IUTF8 ideal-int
|
||||
pkg syscall (darwin-amd64), const IXANY ideal-int
|
||||
pkg syscall (darwin-amd64), const IXOFF ideal-int
|
||||
pkg syscall (darwin-amd64), const IXON ideal-int
|
||||
pkg syscall (darwin-amd64), const NOFLSH ideal-int
|
||||
pkg syscall (darwin-amd64), const OCRNL ideal-int
|
||||
pkg syscall (darwin-amd64), const OFDEL ideal-int
|
||||
pkg syscall (darwin-amd64), const OFILL ideal-int
|
||||
pkg syscall (darwin-amd64), const ONLCR ideal-int
|
||||
pkg syscall (darwin-amd64), const ONLRET ideal-int
|
||||
pkg syscall (darwin-amd64), const ONOCR ideal-int
|
||||
pkg syscall (darwin-amd64), const ONOEOT ideal-int
|
||||
pkg syscall (darwin-amd64), const OPOST ideal-int
|
||||
pkg syscall (darwin-amd64), const PARENB ideal-int
|
||||
pkg syscall (darwin-amd64), const PARMRK ideal-int
|
||||
pkg syscall (darwin-amd64), const PARODD ideal-int
|
||||
pkg syscall (darwin-amd64), const PENDIN ideal-int
|
||||
pkg syscall (darwin-amd64), const TCIFLUSH ideal-int
|
||||
pkg syscall (darwin-amd64), const TCIOFLUSH ideal-int
|
||||
pkg syscall (darwin-amd64), const TCOFLUSH ideal-int
|
||||
pkg syscall (darwin-amd64), const TCSAFLUSH ideal-int
|
||||
pkg syscall (darwin-amd64), const TOSTOP ideal-int
|
||||
pkg syscall (darwin-amd64), const VDISCARD ideal-int
|
||||
pkg syscall (darwin-amd64), const VDSUSP ideal-int
|
||||
pkg syscall (darwin-amd64), const VEOF ideal-int
|
||||
pkg syscall (darwin-amd64), const VEOL ideal-int
|
||||
pkg syscall (darwin-amd64), const VEOL2 ideal-int
|
||||
pkg syscall (darwin-amd64), const VERASE ideal-int
|
||||
pkg syscall (darwin-amd64), const VINTR ideal-int
|
||||
pkg syscall (darwin-amd64), const VKILL ideal-int
|
||||
pkg syscall (darwin-amd64), const VLNEXT ideal-int
|
||||
pkg syscall (darwin-amd64), const VMIN ideal-int
|
||||
pkg syscall (darwin-amd64), const VQUIT ideal-int
|
||||
pkg syscall (darwin-amd64), const VREPRINT ideal-int
|
||||
pkg syscall (darwin-amd64), const VSTART ideal-int
|
||||
pkg syscall (darwin-amd64), const VSTATUS ideal-int
|
||||
pkg syscall (darwin-amd64), const VSTOP ideal-int
|
||||
pkg syscall (darwin-amd64), const VSUSP ideal-int
|
||||
pkg syscall (darwin-amd64), const VT0 ideal-int
|
||||
pkg syscall (darwin-amd64), const VT1 ideal-int
|
||||
pkg syscall (darwin-amd64), const VTDLY ideal-int
|
||||
pkg syscall (darwin-amd64), const VTIME ideal-int
|
||||
pkg syscall (darwin-amd64), const VWERASE ideal-int
|
||||
pkg syscall (darwin-amd64), type Termios struct
|
||||
pkg syscall (darwin-amd64), type Termios struct, Cc [20]uint8
|
||||
pkg syscall (darwin-amd64), type Termios struct, Cflag uint64
|
||||
pkg syscall (darwin-amd64), type Termios struct, Iflag uint64
|
||||
pkg syscall (darwin-amd64), type Termios struct, Ispeed uint64
|
||||
pkg syscall (darwin-amd64), type Termios struct, Lflag uint64
|
||||
pkg syscall (darwin-amd64), type Termios struct, Oflag uint64
|
||||
pkg syscall (darwin-amd64), type Termios struct, Ospeed uint64
|
||||
pkg syscall (darwin-amd64), type Termios struct, Pad_cgo_0 [4]byte
|
||||
pkg syscall (darwin-amd64-cgo), const B0 ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const B110 ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const B115200 ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const B1200 ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const B134 ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const B14400 ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const B150 ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const B1800 ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const B19200 ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const B200 ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const B230400 ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const B2400 ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const B28800 ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const B300 ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const B38400 ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const B4800 ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const B50 ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const B57600 ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const B600 ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const B7200 ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const B75 ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const B76800 ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const B9600 ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const BRKINT ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const CFLUSH ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const CLOCAL ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const CREAD ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const CS5 ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const CS6 ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const CS7 ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const CS8 ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const CSIZE ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const CSTART ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const CSTATUS ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const CSTOP ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const CSTOPB ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const CSUSP ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const FLUSHO ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const HUPCL ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const ICANON ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const ICRNL ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const IEXTEN ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const IGNBRK ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const IGNCR ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const IGNPAR ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const IMAXBEL ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const INLCR ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const INPCK ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const ISIG ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const ISTRIP ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const IUTF8 ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const IXANY ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const IXOFF ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const IXON ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const NOFLSH ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const OCRNL ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const OFDEL ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const OFILL ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const ONLCR ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const ONLRET ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const ONOCR ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const ONOEOT ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const OPOST ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const PARENB ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const PARMRK ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const PARODD ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const PENDIN ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const TCIFLUSH ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const TCIOFLUSH ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const TCOFLUSH ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const TCSAFLUSH ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const TOSTOP ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const VDISCARD ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const VDSUSP ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const VEOF ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const VEOL ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const VEOL2 ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const VERASE ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const VINTR ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const VKILL ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const VLNEXT ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const VMIN ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const VQUIT ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const VREPRINT ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const VSTART ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const VSTATUS ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const VSTOP ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const VSUSP ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const VT0 ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const VT1 ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const VTDLY ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const VTIME ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const VWERASE ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), type Termios struct
|
||||
pkg syscall (darwin-amd64-cgo), type Termios struct, Cc [20]uint8
|
||||
pkg syscall (darwin-amd64-cgo), type Termios struct, Cflag uint64
|
||||
pkg syscall (darwin-amd64-cgo), type Termios struct, Iflag uint64
|
||||
pkg syscall (darwin-amd64-cgo), type Termios struct, Ispeed uint64
|
||||
pkg syscall (darwin-amd64-cgo), type Termios struct, Lflag uint64
|
||||
pkg syscall (darwin-amd64-cgo), type Termios struct, Oflag uint64
|
||||
pkg syscall (darwin-amd64-cgo), type Termios struct, Ospeed uint64
|
||||
pkg syscall (darwin-amd64-cgo), type Termios struct, Pad_cgo_0 [4]byte
|
||||
pkg syscall (windows-386), const CREATE_NEW_PROCESS_GROUP ideal-int
|
||||
pkg syscall (windows-386), const CTRL_BREAK_EVENT ideal-int
|
||||
pkg syscall (windows-386), const CTRL_C_EVENT ideal-int
|
||||
pkg syscall (windows-386), func GetCurrentProcessId() uint32
|
||||
pkg syscall (windows-386), type SysProcAttr struct, CreationFlags uint32
|
||||
pkg syscall (windows-amd64), const CREATE_NEW_PROCESS_GROUP ideal-int
|
||||
pkg syscall (windows-amd64), const CTRL_BREAK_EVENT ideal-int
|
||||
pkg syscall (windows-amd64), const CTRL_C_EVENT ideal-int
|
||||
pkg syscall (windows-amd64), func GetCurrentProcessId() uint32
|
||||
pkg syscall (windows-amd64), type SysProcAttr struct, CreationFlags uint32
|
||||
@@ -17,7 +17,7 @@ and launching a goroutine that sleeps before sending on the channel:
|
||||
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.
|
||||
<code>ch</code> is abandoned.
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/timeout1.go" `/select {/` `/STOP/`}}
|
||||
@@ -64,7 +64,7 @@ could fail since no one is ready.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
This problem is a textbook of example of what is known as a
|
||||
This problem is a textbook 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>),
|
||||
|
||||
@@ -89,7 +89,7 @@ interface which has a <code>Set</code> method.
|
||||
|
||||
<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
|
||||
source. The <code>Uniform</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
|
||||
@@ -189,7 +189,7 @@ To draw an image through a circular mask with center <code>p</code> and radius
|
||||
|
||||
<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
|
||||
an <code>image.Uniform</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>
|
||||
|
||||
@@ -45,7 +45,7 @@ classic algebra:
|
||||
dstr, dstg, dstb, dsta := dst.RGBA()
|
||||
srcr, srcg, srcb, srca := src.RGBA()
|
||||
_, _, _, m := mask.RGBA()
|
||||
const M = 1<<16 - 1
|
||||
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
|
||||
@@ -130,7 +130,7 @@ much easier to type.
|
||||
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
|
||||
<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.)
|
||||
@@ -193,8 +193,8 @@ way to iterate over an <code>Image</code> m's pixels looks like:
|
||||
|
||||
<pre>
|
||||
b := m.Bounds()
|
||||
for y := b.Min.Y; y < b.Max.Y; y++ {
|
||||
for x := b.Min.X; y < b.Max.X; x++ {
|
||||
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))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,8 +82,8 @@ is <code>nil</code>).
|
||||
|
||||
<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.
|
||||
begin with an uppercase letter). Therefore only the exported fields of a struct
|
||||
will be present in the JSON output.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
|
||||
@@ -57,7 +57,7 @@ original functionality. From there it is simple to build a
|
||||
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>
|
||||
<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>
|
||||
|
||||
|
||||
@@ -243,7 +243,7 @@ slice itself) of a re-slice modifies the elements of the original slice:
|
||||
d := []byte{'r', 'o', 'a', 'd'}
|
||||
e := d[2:]
|
||||
// e == []byte{'a', 'd'}
|
||||
e[1] == 'm'
|
||||
e[1] = 'm'
|
||||
// e == []byte{'a', 'm'}
|
||||
// d == []byte{'r', 'o', 'a', 'm'}
|
||||
</pre>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<h1>Editing {{.Title |html}}</h1>
|
||||
<h1>Editing {{.Title}}</h1>
|
||||
|
||||
<form action="/save/{{.Title |html}}" method="POST">
|
||||
<div><textarea name="body" rows="20" cols="80">{{printf "%s" .Body |html}}</textarea></div>
|
||||
<form action="/save/{{.Title}}" method="POST">
|
||||
<div><textarea name="body" rows="20" cols="80">{{printf "%s" .Body}}</textarea></div>
|
||||
<div><input type="submit" value="Save"></div>
|
||||
</form>
|
||||
|
||||
@@ -359,10 +359,10 @@ First, we must add <code>html/template</code> to the list of imports:
|
||||
|
||||
<pre>
|
||||
import (
|
||||
<b>"html/template"</b>
|
||||
"http"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
<b>"html/template"</b>
|
||||
)
|
||||
</pre>
|
||||
|
||||
@@ -397,10 +397,11 @@ 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.
|
||||
The <code>html/template</code> package helps guarantee that only safe and
|
||||
correct-looking HTML is generated by template actions. For instance, it
|
||||
automatically escapes any greater than sign (<code>></code>), replacing it
|
||||
with <code>&gt;</code>, to make sure user data does not corrupt the form
|
||||
HTML.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<h1>{{.Title |html}}</h1>
|
||||
<h1>{{.Title}}</h1>
|
||||
|
||||
<p>[<a href="/edit/{{.Title |html}}">edit</a>]</p>
|
||||
<p>[<a href="/edit/{{.Title}}">edit</a>]</p>
|
||||
|
||||
<div>{{printf "%s" .Body |html}}</div>
|
||||
<div>{{printf "%s" .Body}}</div>
|
||||
|
||||
@@ -182,7 +182,7 @@ 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++ {
|
||||
for i := 0; i < 1000; i++ {
|
||||
z -= (z*z - x) / (2 * x)
|
||||
}
|
||||
return z
|
||||
@@ -236,7 +236,7 @@ are built and installed correctly.
|
||||
<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:
|
||||
has the same effect as the one above:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
@@ -300,7 +300,8 @@ func main() {
|
||||
|
||||
<p>
|
||||
Next, run <code>go install</code>, which builds and installs the binary to
|
||||
<code>$GOPATH/bin</code>:
|
||||
<code>$GOPATH/bin</code> (or <code>$GOBIN</code>, if set; to simplify
|
||||
presentation, this document assumes <code>GOBIN</code> is unset):
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
@@ -384,7 +385,7 @@ package newmath
|
||||
import "testing"
|
||||
|
||||
func TestSqrt(t *testing.T) {
|
||||
const in, out = 9, 3
|
||||
const in, out = 4, 2
|
||||
if x := Sqrt(in); x != out {
|
||||
t.Errorf("Sqrt(%v) = %v, want %v", in, x, out)
|
||||
}
|
||||
@@ -397,7 +398,7 @@ Now run the test with <code>go test</code>:
|
||||
|
||||
<pre>
|
||||
$ go test example/newmath
|
||||
ok example/newmath
|
||||
ok example/newmath 0.165s
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
@@ -475,8 +476,8 @@ import "code.google.com/p/go.example/newmath"
|
||||
<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.
|
||||
The <a href="http://godashboard.appspot.com">Go Project Dashboard</a>
|
||||
is a list of external Go projects including programs and libraries.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
|
||||
@@ -1,115 +0,0 @@
|
||||
<!--{
|
||||
"Title": "Using Mercurial Queues with Codereview"
|
||||
}-->
|
||||
|
||||
<h2 id="Introduction">Introduction</h2>
|
||||
|
||||
<p>
|
||||
The Mercurial Queues extension (<code>mq</code>) provides a mechanism for
|
||||
managing patches on top of a Mercurial repository and is described in detail
|
||||
in Chapters
|
||||
<a href="http://hgbook.red-bean.com/read/managing-change-with-mercurial-queues.html">12</a>
|
||||
and <a href="http://hgbook.red-bean.com/read/advanced-uses-of-mercurial-queues.html">13</a>
|
||||
of <a href="http://hgbook.red-bean.com/read/">Mercurial: The Definitive Guide</a>.
|
||||
This document explains how to use <code>mq</code> in conjunction
|
||||
with the <code>codereview</code> Mercurial extension described in the
|
||||
instructions for <a href="contribute.html">contributing to the Go project</a>.
|
||||
It assumes you have read those instructions.
|
||||
</p>
|
||||
|
||||
<h2>Configuration</h2>
|
||||
|
||||
<p>
|
||||
To enable <code>mq</code> edit either <code>$HOME/.hgrc</code> (to enable it
|
||||
for all of your repositories) or <code>$GOROOT/.hg/hgrc</code> (to enable it for the
|
||||
repository at <code>$GOROOT</code>) to add:</p>
|
||||
|
||||
<pre>
|
||||
[extensions]
|
||||
mq=
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Since pulling, pushing, updating and committing while <code>mq</code> patches
|
||||
are applied can damage your repository or a remote one, add these lines to
|
||||
prevent that case:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
[hooks]
|
||||
# Prevent "hg pull" if MQ patches are applied.
|
||||
prechangegroup.mq-no-pull = ! hg qtop > /dev/null 2>&1
|
||||
# Prevent "hg push" if MQ patches are applied.
|
||||
preoutgoing.mq-no-push = ! hg qtop > /dev/null 2>&1
|
||||
# Prevent "hg update" if MQ patches are applied.
|
||||
preupdate.mq-no-update = ! hg qtop > /dev/null 2>&1
|
||||
</pre>
|
||||
|
||||
<h2>Making a change</h2>
|
||||
|
||||
<p>
|
||||
The entire checked-out tree is writable and you can use <code>mq</code>,
|
||||
as documented in Chapter
|
||||
<a href="http://hgbook.red-bean.com/read/managing-change-with-mercurial-queues.html">12</a>
|
||||
of "The Guide",
|
||||
to implement your change as a single patch or a series of patches.
|
||||
|
||||
</p>
|
||||
|
||||
<p>When you are ready to send a change out for review, run</p>
|
||||
|
||||
<pre>
|
||||
$ hg change
|
||||
</pre>
|
||||
|
||||
<p>from any directory in your Go repository with all of the <code>mq</code> patches relevant to your
|
||||
change applied and then proceed as instructed in <a href="contribute.html">contributing
|
||||
to the Go project</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The change number reported by <code>hg change</code>, preceded by a <code>+</code>,
|
||||
can be used as an <code>mq</code> patch guard to assist in controlling which patches
|
||||
are applied as described in Chapter
|
||||
<a href="http://hgbook.red-bean.com/read/advanced-uses-of-mercurial-queues.html">13</a>
|
||||
of "The Guide".
|
||||
For example, the command:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
for p in $(hg qapplied); do hg qguard $p +99999; done
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
will apply the guard <code>+99999</code> guard to all currently applied <code>mq</code>
|
||||
patches.
|
||||
</p>
|
||||
|
||||
<h2>Synchronizing your client</h2>
|
||||
|
||||
<p>While you were working, others might have submitted changes
|
||||
to the repository and, as explained in <a href="contribute.html">contributing
|
||||
to the Go project</a>, it is necessary to synchronize your repository using
|
||||
<code>hg sync</code>before sending your change list for review.
|
||||
Because <code>hg sync</code> runs <code>hg pull -u</code>,
|
||||
you should not run <code>hg sync</code> while <code>mq</code> patches are
|
||||
applied. Instead
|
||||
pop all your patches before running <code>hg sync</code> and reapply them after
|
||||
it has completed.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
When reapplying the patches, you may need to resolve conflicts
|
||||
as described in <a href="contribute.html">contributing to the Go project</a>.
|
||||
</p>
|
||||
|
||||
<h2>Mailing the change for review</h2>
|
||||
|
||||
<p>
|
||||
You should have all of the <code>mq</code> patches relevant to your
|
||||
change applied when you run <code>hg mail</code>.
|
||||
|
||||
<h2>Submitting the change after the review</h2>
|
||||
|
||||
If you are a committer, you should have all of the <code>mq</code> patches relevant to your
|
||||
change applied when you run <code>hg commit</code>.
|
||||
@@ -215,7 +215,7 @@ p[len(p)-1] = suffix
|
||||
|
||||
<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.
|
||||
<code><a href="/pkg/math/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.
|
||||
@@ -287,11 +287,11 @@ 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
|
||||
$ ./markov -words=10 < $GOROOT/README
|
||||
This is the source code repository for the Go source
|
||||
$ ./markov -prefix=1 -words=10 < $GOROOT/go/README
|
||||
$ ./markov -prefix=1 -words=10 < $GOROOT/README
|
||||
This is the go directory (the one containing this README).
|
||||
$ ./markov -prefix=1 -words=10 < $GOROOT/go/README
|
||||
$ ./markov -prefix=1 -words=10 < $GOROOT/README
|
||||
This is the variable if you have just untarred a</pre>
|
||||
</step>
|
||||
|
||||
|
||||
@@ -104,11 +104,6 @@ the code review extension disables the standard <code>hg commit</code>
|
||||
command.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Mercurial power users: if you prefer to use the Mercurial Queues extension, see
|
||||
<a href="codereview_with_mq.html">Using Mercurial Queues with Codereview</a>.
|
||||
</p>
|
||||
|
||||
<h3>Configure the extension</h3>
|
||||
|
||||
<p>Edit <code>$GOROOT/.hg/hgrc</code> to add:</p>
|
||||
|
||||
@@ -23,6 +23,14 @@ 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>
|
||||
|
||||
<p>
|
||||
The code generated by the <code>gc</code> compiler includes inlining of
|
||||
function invocations and registerization of variables. These optimizations
|
||||
can sometimes make debugging with <code>gdb</code> harder. To disable them
|
||||
when debugging, pass the flags <code>-gcflags "-N -l"</code> to the
|
||||
<a href="/cmd/go"><code>go</code></a> command used to build the code being
|
||||
debugged.
|
||||
</p>
|
||||
|
||||
<h3 id="Common_Operations">Common Operations</h3>
|
||||
|
||||
|
||||
@@ -35,6 +35,32 @@ The go1 release corresponds to
|
||||
<code><a href="weekly.html#2012-03-27">weekly.2012-03-27</a></code>.
|
||||
</p>
|
||||
|
||||
<h3 id="go1.minor">Minor revisions</h3>
|
||||
|
||||
<p>
|
||||
go1.0.1 (released 2012/04/25) was issued to
|
||||
<a href="https://code.google.com/p/go/source/detail?r=a890477d3dfb">fix</a> an
|
||||
<a href="https://code.google.com/p/go/issues/detail?id=3545">escape analysis
|
||||
bug</a> that can lead to memory corruption.
|
||||
It also includes several minor code and documentation fixes.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.0.2 (released 2012/06/13) was issued to fix two bugs in the implementation
|
||||
of maps using struct or array keys:
|
||||
<a href="http://code.google.com/p/go/issues/detail?id=3695">issue 3695</a> and
|
||||
<a href="http://code.google.com/p/go/issues/detail?id=3573">issue 3573</a>.
|
||||
It also includes many minor code and documentation fixes.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.0.3 (released 2012/09/21) includes minor code and documentation fixes.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
See the <a href="http://code.google.com/p/go/source/list?name=release-branch.go1">go1 release branch history</a> for the complete list of changes.
|
||||
</p>
|
||||
|
||||
<h2 id="r60">r60 (released 2011/09/07)</h2>
|
||||
|
||||
<p>
|
||||
|
||||
@@ -56,10 +56,13 @@ A must read for any new Go programmer. It augments the tour 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>
|
||||
<h3 id="ref"><a href="/ref/">Go References</a></h3>
|
||||
<p>Language specification, memory model, and detailed documentation for the commands and packages.</p>
|
||||
|
||||
<h3 id="appengine"><a href="https://developers.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>.
|
||||
<a href="https://developers.google.com/appengine/">Google App Engine</a>.
|
||||
</p>
|
||||
|
||||
<h3 id="go_faq"><a href="go_faq.html">Frequently Asked Questions (FAQ)</a></h3>
|
||||
@@ -139,27 +142,29 @@ before Go 1 and contain some examples that are no longer correct, but they are
|
||||
still of value.
|
||||
</p>
|
||||
|
||||
<h3 id="video_tour_of_go"><a href="http://research.swtch.com/gotour">A Video Tour of Go</a></h3>
|
||||
<p>
|
||||
Three things that make Go fast, fun, and productive:
|
||||
interfaces, reflection, and concurrency. Builds a toy web crawler to
|
||||
demonstrate these.
|
||||
</p>
|
||||
|
||||
<h3 id="go_concurrency_patterns"><a href="http://www.youtube.com/watch?v=f6kdp27TYZs">Go Concurrency Patterns</a></h3>
|
||||
<p>
|
||||
Concurrency is the key to designing high performance network services. Go's concurrency primitives (goroutines and channels) provide a simple and efficient means of expressing concurrent execution. In this talk we see how tricky concurrency problems can be solved gracefully with simple Go code.
|
||||
</p>
|
||||
|
||||
<h3 id="meet_the_go_team"><a href="http://www.youtube.com/watch?v=sln-gJaURzk">Meet the Go team</a></h3>
|
||||
<p>
|
||||
A panel discussion with David Symonds, Robert Griesemer, Rob Pike, Ken Thompson, Andrew Gerrand, and Brad Fitzpatrick.
|
||||
</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>
|
||||
<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
|
||||
and unveils the <a href="http://blog.golang.org/2011/05/go-and-google-app-engine.html">Go runtime for App Engine</a>.
|
||||
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>
|
||||
<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
|
||||
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.
|
||||
See the <a href="http://talks.golang.org/2011/Writing_Web_Apps_in_Go.pdf">presentation slides</a>.
|
||||
</p>
|
||||
|
||||
<h3 id="go_programming"><a href="http://www.youtube.com/watch?v=jgVhBThJdXc">Go Programming</a><font color="red">*</font></h3>
|
||||
@@ -170,14 +175,6 @@ examples demonstrating features particular to Go. These include concurrency,
|
||||
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>
|
||||
<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
|
||||
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>
|
||||
<p>
|
||||
See the <a href="http://code.google.com/p/go-wiki/wiki/GoTalks">GoTalks
|
||||
|
||||
39
doc/effective_go.html
Normal file → Executable file
39
doc/effective_go.html
Normal file → Executable file
@@ -714,6 +714,7 @@ func unhex(c byte) byte {
|
||||
<p>
|
||||
There is no automatic fall through, but cases can be presented
|
||||
in comma-separated lists.
|
||||
</p>
|
||||
<pre>
|
||||
func shouldEscape(c byte) bool {
|
||||
switch c {
|
||||
@@ -727,6 +728,7 @@ func shouldEscape(c byte) bool {
|
||||
<p>
|
||||
Here's a comparison routine for byte arrays that uses two
|
||||
<code>switch</code> statements:
|
||||
</p>
|
||||
<pre>
|
||||
// Compare returns an integer comparing the two byte arrays,
|
||||
// lexicographically.
|
||||
@@ -1180,6 +1182,7 @@ structure with length 10 and a capacity of 100 pointing at the first
|
||||
for more information.)
|
||||
In contrast, <code>new([]int)</code> returns a pointer to a newly allocated, zeroed slice
|
||||
structure, that is, a pointer to a <code>nil</code> slice value.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
These examples illustrate the difference between <code>new</code> and
|
||||
@@ -1330,6 +1333,8 @@ func Append(slice, data[]byte) []byte {
|
||||
We must return the slice afterwards because, although <code>Append</code>
|
||||
can modify the elements of <code>slice</code>, the slice itself (the run-time data
|
||||
structure holding the pointer, length, and capacity) is passed by value.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The idea of appending to a slice is so useful it's captured by the
|
||||
<code>append</code> built-in function. To understand that function's
|
||||
@@ -1545,6 +1550,7 @@ a space in the format (<code>% x</code>) it puts spaces between the bytes.
|
||||
</p>
|
||||
<p>
|
||||
Another handy format is <code>%T</code>, which prints the <em>type</em> of a value.
|
||||
</p>
|
||||
<pre>
|
||||
fmt.Printf("%T\n", timeZone)
|
||||
</pre>
|
||||
@@ -1606,6 +1612,7 @@ func Println(v ...interface{}) {
|
||||
We write <code>...</code> after <code>v</code> in the nested call to <code>Sprintln</code> to tell the
|
||||
compiler to treat <code>v</code> as a list of arguments; otherwise it would just pass
|
||||
<code>v</code> as a single slice argument.
|
||||
</p>
|
||||
<p>
|
||||
There's even more to printing than we've covered here. See the <code>godoc</code> documentation
|
||||
for package <code>fmt</code> for the details.
|
||||
@@ -1783,6 +1790,7 @@ func init() {
|
||||
<p>
|
||||
Methods can be defined for any named type that is not a pointer or an interface;
|
||||
the receiver does not have to be a struct.
|
||||
</p>
|
||||
<p>
|
||||
In the discussion of slices above, we wrote an <code>Append</code>
|
||||
function. We can define it as a method on slices instead. To do
|
||||
@@ -2012,6 +2020,7 @@ Those methods include the standard <code>Write</code> method, so an
|
||||
can be used.
|
||||
<code>Request</code> is a struct containing a parsed representation
|
||||
of the request from the client.
|
||||
</p>
|
||||
<p>
|
||||
For brevity, let's ignore POSTs and assume HTTP requests are always
|
||||
GETs; that simplification does not affect the way the handlers are
|
||||
@@ -2034,6 +2043,7 @@ func (ctr *Counter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
(Keeping with our theme, note how <code>Fprintf</code> can print to an
|
||||
<code>http.ResponseWriter</code>.)
|
||||
For reference, here's how to attach such a server to a node on the URL tree.
|
||||
</p>
|
||||
<pre>
|
||||
import "net/http"
|
||||
...
|
||||
@@ -2187,6 +2197,7 @@ what a <code>Reader</code> does <em>and</em> what a <code>Writer</code>
|
||||
does; it is a union of the embedded interfaces (which must be disjoint
|
||||
sets of methods).
|
||||
Only interfaces can be embedded within interfaces.
|
||||
</p>
|
||||
<p>
|
||||
The same basic idea applies to structs, but with more far-reaching
|
||||
implications. The <code>bufio</code> package has two struct types,
|
||||
@@ -2291,7 +2302,7 @@ This would be useful if we wanted to refine the methods of <code>Logger</code>.
|
||||
</p>
|
||||
<pre>
|
||||
func (job *Job) Logf(format string, args ...interface{}) {
|
||||
job.Logger.Logf("%q: %s", job.Command, fmt.Sprintf(format, args))
|
||||
job.Logger.Logf("%q: %s", job.Command, fmt.Sprintf(format, args...))
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
@@ -2378,10 +2389,11 @@ 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 concurrently; don't wait for it.
|
||||
</pre>
|
||||
<p>
|
||||
A function literal can be handy in a goroutine invocation.
|
||||
</p>
|
||||
<pre>
|
||||
func Announce(message string, delay time.Duration) {
|
||||
go func() {
|
||||
@@ -2393,6 +2405,7 @@ func Announce(message string, delay time.Duration) {
|
||||
<p>
|
||||
In Go, function literals are closures: the implementation makes
|
||||
sure the variables referred to by the function survive as long as they are active.
|
||||
</p>
|
||||
<p>
|
||||
These examples aren't too practical because the functions have no way of signaling
|
||||
completion. For that, we need channels.
|
||||
@@ -2425,7 +2438,7 @@ c := make(chan int) // Allocate a channel.
|
||||
// Start the sort in a goroutine; when it completes, signal on the channel.
|
||||
go func() {
|
||||
list.Sort()
|
||||
c <- 1 // Send a signal; value does not matter.
|
||||
c <- 1 // Send a signal; value does not matter.
|
||||
}()
|
||||
doSomethingForAWhile()
|
||||
<-c // Wait for sort to finish; discard sent value.
|
||||
@@ -2479,7 +2492,7 @@ func handle(queue chan *Request) {
|
||||
}
|
||||
}
|
||||
|
||||
func Serve(clientRequests chan *clientRequests, quit chan bool) {
|
||||
func Serve(clientRequests chan *Request, quit chan bool) {
|
||||
// Start handlers
|
||||
for i := 0; i < MaxOutstanding; i++ {
|
||||
go handle(clientRequests)
|
||||
@@ -2494,6 +2507,7 @@ One of the most important properties of Go is that
|
||||
a channel is a first-class value that can be allocated and passed
|
||||
around like any other. A common use of this property is
|
||||
to implement safe, parallel demultiplexing.
|
||||
</p>
|
||||
<p>
|
||||
In the example in the previous section, <code>handle</code> was
|
||||
an idealized handler for a request but we didn't define the
|
||||
@@ -2992,11 +3006,11 @@ 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 <code>html/template</code> is powerful;
|
||||
this program just touches on its capabilities.
|
||||
In essence, it rewrites a piece of text on the fly by substituting elements derived
|
||||
In essence, it rewrites a piece of HTML text on the fly by substituting elements derived
|
||||
from data items passed to <code>templ.Execute</code>, in this case the
|
||||
form value.
|
||||
form value.
|
||||
Within the template text (<code>templateStr</code>),
|
||||
double-brace-delimited pieces denote template actions.
|
||||
The piece from <code>{{html "{{if .}}"}}</code>
|
||||
@@ -3005,13 +3019,14 @@ is non-empty.
|
||||
That is, 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
|
||||
for safe display on the web page.
|
||||
The two snippets <code>{{html "{{.}}"}}</code> say to show the data presented to
|
||||
the template—the query string—on the web page.
|
||||
The HTML template package automatically provides appropriate escaping so the
|
||||
text is safe to display.
|
||||
</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/html/template/">documentation</a>
|
||||
for the template package for a more thorough discussion.
|
||||
</p>
|
||||
<p>
|
||||
@@ -3025,7 +3040,7 @@ TODO
|
||||
<pre>
|
||||
verifying implementation
|
||||
type Color uint32
|
||||
|
||||
|
||||
// Check that Color implements image.Color and image.Image
|
||||
var _ image.Color = Black
|
||||
var _ image.Image = Black
|
||||
|
||||
@@ -1253,7 +1253,7 @@ Since the package's functionality is new, no updating is necessary.
|
||||
<p>
|
||||
In Go 1 the <a href="/pkg/net/http/"><code>http</code></a> package is refactored,
|
||||
putting some of the utilities into a
|
||||
<a href="/pkg/net/httputil/"><code>httputil</code></a> subdirectory.
|
||||
<a href="/pkg/net/http/httputil/"><code>httputil</code></a> subdirectory.
|
||||
These pieces are only rarely needed by HTTP clients.
|
||||
The affected items are:
|
||||
</p>
|
||||
@@ -1261,7 +1261,6 @@ The affected items are:
|
||||
<ul>
|
||||
<li>ClientConn</li>
|
||||
<li>DumpRequest</li>
|
||||
<li>DumpRequest</li>
|
||||
<li>DumpRequestOut</li>
|
||||
<li>DumpResponse</li>
|
||||
<li>NewChunkedReader</li>
|
||||
@@ -1789,7 +1788,7 @@ for full details.
|
||||
<td colspan="2"><hr></td>
|
||||
</tr>
|
||||
<tr><td>Atoui(x)</td> <td>ParseUint(x, 10, 0)§</td></tr>
|
||||
<tr><td>Atoi64(x)</td> <td>ParseInt(x, 10, 64)</td></tr>
|
||||
<tr><td>Atoui64(x)</td> <td>ParseUint(x, 10, 64)</td></tr>
|
||||
<tr>
|
||||
<td colspan="2"><hr></td>
|
||||
</tr>
|
||||
|
||||
@@ -54,6 +54,38 @@ By its design, Go proposes an approach for the construction of system
|
||||
software on multicore machines.
|
||||
</ul>
|
||||
|
||||
<h3 id="What_is_the_status_of_the_project">
|
||||
What is the status of the project?</h3>
|
||||
|
||||
<p>
|
||||
Go became a public open source project on November 10, 2009.
|
||||
After a couple of years of very active design and development, stability was called for and
|
||||
Go 1 was <a href="http://blog.golang.org/2012/03/go-version-1-is-released.html">released</a>
|
||||
on March 28, 2012.
|
||||
Go 1, which includes a <a href="/ref/spec">language specification</a>,
|
||||
<a href="/pkg/">standard libraries</a>,
|
||||
and <a href="/cmd/go/">custom tools</a>,
|
||||
provides a stable foundation for creating reliable products, projects, and publications.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
With that stability established, we are using Go to develop programs, products, and tools rather than
|
||||
actively changing the language and libraries.
|
||||
In fact, the purpose of Go 1 is to provide <a href="/doc/go1compat.html">long-term stability</a>.
|
||||
Backwards-incompatible changes will not be made to any Go 1 point release.
|
||||
We want to use what we have to learn how a future version of Go might look, rather than to play with
|
||||
the language underfoot.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Of course, development will continue on Go itself, but the focus will be on performance, reliability,
|
||||
portability and the addition of new functionality such as improved support for internationalization.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
There may well be a Go 2 one day, but not for a few years and it will be influenced by what we learn using Go 1 as it is today.
|
||||
</p>
|
||||
|
||||
<h3 id="What_is_the_origin_of_the_name">
|
||||
What is the origin of the name?</h3>
|
||||
|
||||
@@ -180,7 +212,7 @@ production inside Google. A public example is the server behind
|
||||
<a href="http://golang.org">http://golang.org</a>.
|
||||
It's just the <a href="/cmd/godoc"><code>godoc</code></a>
|
||||
document server running in a production configuration on
|
||||
<a href="http://code.google.com/appengine/">Google App Engine</a>.
|
||||
<a href="https://developers.google.com/appengine/">Google App Engine</a>.
|
||||
</p>
|
||||
|
||||
<h3 id="Do_Go_programs_link_with_Cpp_programs">
|
||||
@@ -509,7 +541,7 @@ Why doesn't Go have "implements" declarations?</h3>
|
||||
<p>
|
||||
A Go type satisfies an interface by implementing the methods of that interface,
|
||||
nothing more. This property allows interfaces to be defined and used without
|
||||
having to modify existing code. It enables a kind of "duck typing" that
|
||||
having to modify existing code. It enables a kind of structural typing that
|
||||
promotes separation of concerns and improves code re-use, and makes it easier
|
||||
to build on patterns that emerge as the code develops.
|
||||
The semantics of interfaces is one of the main reasons for Go's nimble,
|
||||
@@ -890,6 +922,32 @@ See the document
|
||||
for more information about how to proceed.
|
||||
</p>
|
||||
|
||||
<h3 id="Why_does_the_project_use_Mercurial_and_not_git">
|
||||
Why does the project use Mercurial and not git?</h3>
|
||||
|
||||
<p>
|
||||
The Go project, hosted by Google Code at
|
||||
<a href="http://code.google.com/p/go">code.google.com/p/go</a>,
|
||||
uses Mercurial as its version control system.
|
||||
When the project launched,
|
||||
Google Code supported only Subversion and Mercurial.
|
||||
Mercurial was a better choice because of its plugin mechanism
|
||||
that allowed us to create the "codereview" plugin to connect
|
||||
the project to the excellent code review tools at
|
||||
<a href="http://codereview.appspot.com">codereview.appspot.com</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Programmers who work
|
||||
with the Go project's source rather than release downloads sometimes
|
||||
ask for the project to switch to git.
|
||||
That would be possible, but it would be a lot of work and
|
||||
would also require reimplementing the codereview plugin.
|
||||
Given that Mercurial works today, with code review support,
|
||||
combined with the Go project's mostly linear, non-branching use of
|
||||
version control, a switch to git doesn't seem worthwhile.
|
||||
</p>
|
||||
|
||||
<h2 id="Pointers">Pointers and Allocation</h2>
|
||||
|
||||
<h3 id="pass_by_value">
|
||||
@@ -1188,8 +1246,9 @@ but <code>v</code> may have been modified since the goroutine was launched.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
To bind the value of <code>v</code> to each closure as they are launched, one
|
||||
could modify the inner loop to read:
|
||||
To bind the current value of <code>v</code> to each closure as it is launched, one
|
||||
must modify the inner loop to create a new variable each iteration.
|
||||
One way is to pass the variable as an argument to the closure:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
@@ -1207,6 +1266,21 @@ anonymous function. That value is then accessible inside the function as
|
||||
the variable <code>u</code>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Even easier is just to create a new variable, using a declaration style that may
|
||||
seem odd but works fine in Go:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
for _, v := range values {
|
||||
<b>v := v</b> // create a new 'v'.
|
||||
go func() {
|
||||
fmt.Println(<b>v</b>)
|
||||
done <- true
|
||||
}()
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h2 id="Control_flow">Control flow</h2>
|
||||
|
||||
<h3 id="Does_Go_have_a_ternary_form">
|
||||
|
||||
@@ -270,8 +270,8 @@ before the <code>print</code>.
|
||||
<p>
|
||||
If the channel were buffered (e.g., <code>c = make(chan int, 1)</code>)
|
||||
then the program would not be guaranteed to print
|
||||
<code>"hello, world"</code>. (It might print the empty string;
|
||||
it cannot print <code>"goodbye, universe"</code>, nor can it crash.)
|
||||
<code>"hello, world"</code>. (It might print the empty string,
|
||||
crash, or do something else.)
|
||||
</p>
|
||||
|
||||
<h3>Locks</h3>
|
||||
|
||||
253
doc/go_spec.html
253
doc/go_spec.html
@@ -1,6 +1,6 @@
|
||||
<!--{
|
||||
"Title": "The Go Programming Language Specification",
|
||||
"Subtitle": "Version of March 17, 2012",
|
||||
"Subtitle": "Version of September 4, 2012",
|
||||
"Path": "/ref/spec"
|
||||
}-->
|
||||
|
||||
@@ -15,7 +15,6 @@ TODO
|
||||
[ ] need explicit language about the result type of operations
|
||||
[ ] should probably write something about evaluation order of statements even
|
||||
though obvious
|
||||
[ ] review language on implicit dereferencing
|
||||
-->
|
||||
|
||||
|
||||
@@ -89,7 +88,8 @@ Source code is Unicode text encoded in
|
||||
canonicalized, so a single accented code point is distinct from the
|
||||
same character constructed from combining an accent and a letter;
|
||||
those are treated as two code points. For simplicity, this document
|
||||
will use the term <i>character</i> to refer to a Unicode code point.
|
||||
will use the unqualified term <i>character</i> to refer to a Unicode code point
|
||||
in the source text.
|
||||
</p>
|
||||
<p>
|
||||
Each code point is distinct; for instance, upper and lower case letters
|
||||
@@ -198,7 +198,7 @@ token is
|
||||
<a href="#Integer_literals">integer</a>,
|
||||
<a href="#Floating-point_literals">floating-point</a>,
|
||||
<a href="#Imaginary_literals">imaginary</a>,
|
||||
<a href="#Character_literals">character</a>, or
|
||||
<a href="#Rune_literals">rune</a>, or
|
||||
<a href="#String_literals">string</a> literal
|
||||
</li>
|
||||
|
||||
@@ -360,13 +360,15 @@ imaginary_lit = (decimals | float_lit) "i" .
|
||||
</pre>
|
||||
|
||||
|
||||
<h3 id="Character_literals">Character literals</h3>
|
||||
<h3 id="Rune_literals">Rune literals</h3>
|
||||
|
||||
<p>
|
||||
A character literal represents a <a href="#Constants">character constant</a>,
|
||||
typically a Unicode code point, as one or more characters enclosed in single
|
||||
quotes. Within the quotes, any character may appear except single
|
||||
quote and newline. A single quoted character represents itself,
|
||||
A rune literal represents a <a href="#Constants">rune constant</a>,
|
||||
an integer value identifying a Unicode code point.
|
||||
A rune literal is expressed as one or more characters enclosed in single quotes.
|
||||
Within the quotes, any character may appear except single
|
||||
quote and newline. A single quoted character represents the Unicode value
|
||||
of the character itself,
|
||||
while multi-character sequences beginning with a backslash encode
|
||||
values in various formats.
|
||||
</p>
|
||||
@@ -380,8 +382,8 @@ a literal <code>a</code>, Unicode U+0061, value <code>0x61</code>, while
|
||||
a literal <code>a</code>-dieresis, U+00E4, value <code>0xe4</code>.
|
||||
</p>
|
||||
<p>
|
||||
Several backslash escapes allow arbitrary values to be represented
|
||||
as ASCII text. There are four ways to represent the integer value
|
||||
Several backslash escapes allow arbitrary values to be encoded as
|
||||
ASCII text. There are four ways to represent the integer value
|
||||
as a numeric constant: <code>\x</code> followed by exactly two hexadecimal
|
||||
digits; <code>\u</code> followed by exactly four hexadecimal digits;
|
||||
<code>\U</code> followed by exactly eight hexadecimal digits, and a
|
||||
@@ -409,11 +411,11 @@ After a backslash, certain single-character escapes represent special values:
|
||||
\t U+0009 horizontal tab
|
||||
\v U+000b vertical tab
|
||||
\\ U+005c backslash
|
||||
\' U+0027 single quote (valid escape only within character literals)
|
||||
\' U+0027 single quote (valid escape only within rune literals)
|
||||
\" U+0022 double quote (valid escape only within string literals)
|
||||
</pre>
|
||||
<p>
|
||||
All other sequences starting with a backslash are illegal inside character literals.
|
||||
All other sequences starting with a backslash are illegal inside rune literals.
|
||||
</p>
|
||||
<pre class="ebnf">
|
||||
char_lit = "'" ( unicode_value | byte_value ) "'" .
|
||||
@@ -439,6 +441,11 @@ escaped_char = `\` ( "a" | "b" | "f" | "n" | "r" | "t" | "v" | `\` | "'" | `
|
||||
'\xff'
|
||||
'\u12e4'
|
||||
'\U00101234'
|
||||
'aa' // illegal: too many characters
|
||||
'\xa' // illegal: too few hexadecimal digits
|
||||
'\0' // illegal: too few octal digits
|
||||
'\uDFFF' // illegal: surrogate half
|
||||
'\U00110000' // illegal: invalid Unicode code point
|
||||
</pre>
|
||||
|
||||
|
||||
@@ -453,7 +460,8 @@ raw string literals and interpreted string literals.
|
||||
Raw string literals are character sequences between back quotes
|
||||
<code>``</code>. Within the quotes, any character is legal except
|
||||
back quote. The value of a raw string literal is the
|
||||
string composed of the uninterpreted characters between the quotes;
|
||||
string composed of the uninterpreted (implicitly UTF-8-encoded) characters
|
||||
between the quotes;
|
||||
in particular, backslashes have no special meaning and the string may
|
||||
contain newlines.
|
||||
Carriage returns inside raw string literals
|
||||
@@ -464,8 +472,9 @@ Interpreted string literals are character sequences between double
|
||||
quotes <code>""</code>. The text between the quotes,
|
||||
which may not contain newlines, forms the
|
||||
value of the literal, with backslash escapes interpreted as they
|
||||
are in character literals (except that <code>\'</code> is illegal and
|
||||
<code>\"</code> is legal). The three-digit octal (<code>\</code><i>nnn</i>)
|
||||
are in rune literals (except that <code>\'</code> is illegal and
|
||||
<code>\"</code> is legal), with the same restrictions.
|
||||
The three-digit octal (<code>\</code><i>nnn</i>)
|
||||
and two-digit hexadecimal (<code>\x</code><i>nn</i>) escapes represent individual
|
||||
<i>bytes</i> of the resulting string; all other escapes represent
|
||||
the (possibly multi-byte) UTF-8 encoding of individual <i>characters</i>.
|
||||
@@ -492,6 +501,8 @@ interpreted_string_lit = `"` { unicode_value | byte_value } `"` .
|
||||
"日本語"
|
||||
"\u65e5本\U00008a9e"
|
||||
"\xff\u00FF"
|
||||
"\uD800" // illegal: surrogate half
|
||||
"\U00110000" // illegal: invalid Unicode code point
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
@@ -501,15 +512,15 @@ These examples all represent the same string:
|
||||
<pre>
|
||||
"日本語" // UTF-8 input text
|
||||
`日本語` // UTF-8 input text as a raw literal
|
||||
"\u65e5\u672c\u8a9e" // The explicit Unicode code points
|
||||
"\U000065e5\U0000672c\U00008a9e" // The explicit Unicode code points
|
||||
"\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e" // The explicit UTF-8 bytes
|
||||
"\u65e5\u672c\u8a9e" // the explicit Unicode code points
|
||||
"\U000065e5\U0000672c\U00008a9e" // the explicit Unicode code points
|
||||
"\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e" // the explicit UTF-8 bytes
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
If the source code represents a character as two code points, such as
|
||||
a combining form involving an accent and a letter, the result will be
|
||||
an error if placed in a character literal (it is not a single code
|
||||
an error if placed in a rune literal (it is not a single code
|
||||
point), and will appear as two code points if placed in a string
|
||||
literal.
|
||||
</p>
|
||||
@@ -518,7 +529,7 @@ literal.
|
||||
<h2 id="Constants">Constants</h2>
|
||||
|
||||
<p>There are <i>boolean constants</i>,
|
||||
<i>character constants</i>,
|
||||
<i>rune constants</i>,
|
||||
<i>integer constants</i>,
|
||||
<i>floating-point constants</i>, <i>complex constants</i>,
|
||||
and <i>string constants</i>. Character, integer, floating-point,
|
||||
@@ -528,7 +539,7 @@ collectively called <i>numeric constants</i>.
|
||||
|
||||
<p>
|
||||
A constant value is represented by a
|
||||
<a href="#Character_literals">character</a>,
|
||||
<a href="#Rune_literals">rune</a>,
|
||||
<a href="#Integer_literals">integer</a>,
|
||||
<a href="#Floating-point_literals">floating-point</a>,
|
||||
<a href="#Imaginary_literals">imaginary</a>,
|
||||
@@ -622,14 +633,15 @@ expressions</a>.
|
||||
|
||||
<p>
|
||||
A type determines the set of values and operations specific to values of that
|
||||
type. A type may be specified by a (possibly qualified) <i>type name</i>
|
||||
(§<a href="#Qualified_identifiers">Qualified identifier</a>, §<a href="#Type_declarations">Type declarations</a>) or a <i>type literal</i>,
|
||||
type. A type may be specified by a
|
||||
(possibly <a href="#Qualified_identifiers">qualified</a>) <i>type name</i>
|
||||
(§<a href="#Type_declarations">Type declarations</a>) or a <i>type literal</i>,
|
||||
which composes a new type from previously declared types.
|
||||
</p>
|
||||
|
||||
<pre class="ebnf">
|
||||
Type = TypeName | TypeLit | "(" Type ")" .
|
||||
TypeName = QualifiedIdent .
|
||||
TypeName = identifier | QualifiedIdent .
|
||||
TypeLit = ArrayType | StructType | PointerType | FunctionType | InterfaceType |
|
||||
SliceType | MapType | ChannelType .
|
||||
</pre>
|
||||
@@ -684,6 +696,8 @@ consists of all methods with receiver type <code>T</code>.
|
||||
The method set of the corresponding pointer type <code>*T</code>
|
||||
is the set of all methods with receiver <code>*T</code> or <code>T</code>
|
||||
(that is, it also contains the method set of <code>T</code>).
|
||||
Further rules apply to structs containing anonymous fields, as described
|
||||
in the section on <a href="#Struct_types">struct types</a>.
|
||||
Any other type has an empty method set.
|
||||
In a method set, each method must have a
|
||||
<a href="#Uniqueness_of_identifiers">unique</a> <a href="#MethodName">method name</a>.
|
||||
@@ -955,28 +969,39 @@ struct {
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Fields and methods (§<a href="#Method_declarations">Method declarations</a>) of an anonymous field are
|
||||
promoted to be ordinary fields and methods of the struct (§<a href="#Selectors">Selectors</a>).
|
||||
The following rules apply for a struct type <code>S</code> and
|
||||
a type named <code>T</code>:
|
||||
A field or <a href="#Method_declarations">method</a> <code>f</code> of an
|
||||
anonymous field in a struct <code>x</code> is called <i>promoted</i> if
|
||||
<code>x.f</code> is a legal <a href="#Selectors">selector</a> that denotes
|
||||
that field or method <code>f</code>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Promoted fields act like ordinary fields
|
||||
of a struct except that they cannot be used as field names in
|
||||
<a href="#Composite_literals">composite literals</a> of the struct.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Given a struct type <code>S</code> and a type named <code>T</code>,
|
||||
promoted methods are included in the method set of the struct as follows:
|
||||
</p>
|
||||
<ul>
|
||||
<li>If <code>S</code> contains an anonymous field <code>T</code>, the
|
||||
<a href="#Method_sets">method set</a> of <code>S</code> includes the
|
||||
method set of <code>T</code>.
|
||||
<li>
|
||||
If <code>S</code> contains an anonymous field <code>T</code>,
|
||||
the <a href="#Method_sets">method sets</a> of <code>S</code>
|
||||
and <code>*S</code> both include promoted methods with receiver
|
||||
<code>T</code>. The method set of <code>*S</code> also
|
||||
includes promoted methods with receiver <code>*T</code>.
|
||||
</li>
|
||||
|
||||
<li>If <code>S</code> contains an anonymous field <code>*T</code>, the
|
||||
method set of <code>S</code> includes the method set of <code>*T</code>
|
||||
(which itself includes the method set of <code>T</code>).
|
||||
</li>
|
||||
|
||||
<li>If <code>S</code> contains an anonymous field <code>T</code> or
|
||||
<code>*T</code>, the method set of <code>*S</code> includes the
|
||||
method set of <code>*T</code> (which itself includes the method
|
||||
set of <code>T</code>).
|
||||
|
||||
<li>
|
||||
If <code>S</code> contains an anonymous field <code>*T</code>,
|
||||
the method sets of <code>S</code> and <code>*S</code> both
|
||||
include promoted methods with receiver <code>T</code> or
|
||||
<code>*T</code>.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
A field declaration may be followed by an optional string literal <i>tag</i>,
|
||||
which becomes an attribute for all the fields in the corresponding
|
||||
@@ -1598,7 +1623,7 @@ Given a set of identifiers, an identifier is called <i>unique</i> if it is
|
||||
<i>different</i> from every other in the set.
|
||||
Two identifiers are different if they are spelled differently, or if they
|
||||
appear in different <a href="#Packages">packages</a> and are not
|
||||
<a href="Exported_identifiers">exported</a>. Otherwise, they are the same.
|
||||
<a href="#Exported_identifiers">exported</a>. Otherwise, they are the same.
|
||||
</p>
|
||||
|
||||
<h3 id="Constant_declarations">Constant declarations</h3>
|
||||
@@ -2013,25 +2038,33 @@ operators and functions to operands.
|
||||
<h3 id="Operands">Operands</h3>
|
||||
|
||||
<p>
|
||||
Operands denote the elementary values in an expression.
|
||||
Operands denote the elementary values in an expression. An operand may be a
|
||||
literal, a (possibly <a href="#Qualified_identifiers">qualified</a>) identifier
|
||||
denoting a
|
||||
<a href="#Constant_declarations">constant</a>,
|
||||
<a href="#Variable_declarations">variable</a>, or
|
||||
<a href="#Function_declarations">function</a>,
|
||||
a <a href="#Method_expressions">method expression</a> yielding a function,
|
||||
or a parenthesized expression.
|
||||
</p>
|
||||
|
||||
<pre class="ebnf">
|
||||
Operand = Literal | QualifiedIdent | MethodExpr | "(" Expression ")" .
|
||||
Operand = Literal | OperandName | MethodExpr | "(" Expression ")" .
|
||||
Literal = BasicLit | CompositeLit | FunctionLit .
|
||||
BasicLit = int_lit | float_lit | imaginary_lit | char_lit | string_lit .
|
||||
OperandName = identifier | QualifiedIdent.
|
||||
</pre>
|
||||
|
||||
|
||||
<h3 id="Qualified_identifiers">Qualified identifiers</h3>
|
||||
|
||||
<p>
|
||||
A qualified identifier is a non-<a href="#Blank_identifier">blank</a> identifier
|
||||
qualified by a package name prefix.
|
||||
A qualified identifier is an identifier qualified with a package name prefix.
|
||||
Both the package name and the identifier must not be
|
||||
<a href="#Blank_identifier">blank</a>.
|
||||
</p>
|
||||
|
||||
<pre class="ebnf">
|
||||
QualifiedIdent = [ PackageName "." ] identifier .
|
||||
QualifiedIdent = PackageName "." identifier .
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
@@ -2185,7 +2218,7 @@ Within a composite literal of array, slice, or map type <code>T</code>,
|
||||
elements that are themselves composite literals may elide the respective
|
||||
literal type if it is identical to the element type of <code>T</code>.
|
||||
Similarly, elements that are addresses of composite literals may elide
|
||||
the <code>&T</code> when the the element type is <code>*T</code>.
|
||||
the <code>&T</code> when the element type is <code>*T</code>.
|
||||
</p>
|
||||
|
||||
|
||||
@@ -2302,7 +2335,6 @@ Point{1, 2}
|
||||
m["foo"]
|
||||
s[i : j + 1]
|
||||
obj.color
|
||||
math.Sin
|
||||
f.p[i].x()
|
||||
</pre>
|
||||
|
||||
@@ -2310,7 +2342,9 @@ f.p[i].x()
|
||||
<h3 id="Selectors">Selectors</h3>
|
||||
|
||||
<p>
|
||||
A primary expression of the form
|
||||
For a <a href="#Primary_expressions">primary expression</a> <code>x</code>
|
||||
that is not a <a href="#Package_clause">package name</a>, the
|
||||
<i>selector expression</i>
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
@@ -2318,17 +2352,20 @@ x.f
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
denotes the field or method <code>f</code> of the value denoted by <code>x</code>
|
||||
(or sometimes <code>*x</code>; see below). The identifier <code>f</code>
|
||||
is called the (field or method)
|
||||
<i>selector</i>; it must not be the <a href="#Blank_identifier">blank identifier</a>.
|
||||
The type of the expression is the type of <code>f</code>.
|
||||
denotes the field or method <code>f</code> of the value <code>x</code>
|
||||
(or sometimes <code>*x</code>; see below).
|
||||
The identifier <code>f</code> is called the (field or method) <i>selector</i>;
|
||||
it must not be the <a href="#Blank_identifier">blank identifier</a>.
|
||||
The type of the selector expression is the type of <code>f</code>.
|
||||
If <code>x</code> is a package name, see the section on
|
||||
<a href="#Qualified_identifiers">qualified identifiers</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
A selector <code>f</code> may denote a field or method <code>f</code> of
|
||||
a type <code>T</code>, or it may refer
|
||||
to a field or method <code>f</code> of a nested anonymous field of
|
||||
<code>T</code>.
|
||||
to a field or method <code>f</code> of a nested
|
||||
<a href="#Struct_types">anonymous field</a> of <code>T</code>.
|
||||
The number of anonymous fields traversed
|
||||
to reach <code>f</code> is called its <i>depth</i> in <code>T</code>.
|
||||
The depth of a field or method <code>f</code>
|
||||
@@ -2337,9 +2374,11 @@ The depth of a field or method <code>f</code> declared in
|
||||
an anonymous field <code>A</code> in <code>T</code> is the
|
||||
depth of <code>f</code> in <code>A</code> plus one.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The following rules apply to selectors:
|
||||
</p>
|
||||
|
||||
<ol>
|
||||
<li>
|
||||
For a value <code>x</code> of type <code>T</code> or <code>*T</code>
|
||||
@@ -2351,18 +2390,26 @@ If there is not exactly <a href="#Uniqueness_of_identifiers">one <code>f</code><
|
||||
with shallowest depth, the selector expression is illegal.
|
||||
</li>
|
||||
<li>
|
||||
For a variable <code>x</code> of type <code>I</code>
|
||||
where <code>I</code> is an interface type,
|
||||
<code>x.f</code> denotes the actual method with name <code>f</code> of the value assigned
|
||||
to <code>x</code> if there is such a method.
|
||||
If no value or <code>nil</code> was assigned to <code>x</code>, <code>x.f</code> is illegal.
|
||||
For a variable <code>x</code> of type <code>I</code> where <code>I</code>
|
||||
is an interface type, <code>x.f</code> denotes the actual method with name
|
||||
<code>f</code> of the value assigned to <code>x</code>.
|
||||
If there is no method with name <code>f</code> in the
|
||||
<a href="#Method_sets">method set</a> of <code>I</code>, the selector
|
||||
expression is illegal.
|
||||
</li>
|
||||
<li>
|
||||
In all other cases, <code>x.f</code> is illegal.
|
||||
</li>
|
||||
<li>
|
||||
If <code>x</code> is of pointer or interface type and has the value
|
||||
<code>nil</code>, assigning to, evaluating, or calling <code>x.f</code>
|
||||
causes a <a href="#Run_time_panics">run-time panic</a>.
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
<p>
|
||||
Selectors automatically dereference pointers to structs.
|
||||
Selectors automatically <a href="#Address_operators">dereference</a>
|
||||
pointers to structs.
|
||||
If <code>x</code> is a pointer to a struct, <code>x.y</code>
|
||||
is shorthand for <code>(*x).y</code>; if the field <code>y</code>
|
||||
is also a pointer to a struct, <code>x.y.z</code> is shorthand
|
||||
@@ -2371,6 +2418,7 @@ If <code>x</code> contains an anonymous field of type <code>*A</code>,
|
||||
where <code>A</code> is also a struct type,
|
||||
<code>x.f</code> is a shortcut for <code>(*x.A).f</code>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
For example, given the declarations:
|
||||
</p>
|
||||
@@ -2396,7 +2444,7 @@ type T2 struct {
|
||||
|
||||
func (recv *T2) M2()
|
||||
|
||||
var p *T2 // with p != nil and p.T1 != nil
|
||||
var p *T2 // with p != nil and p.T0 != nil
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
@@ -2659,7 +2707,7 @@ back to the calling function when the function returns.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Calling a <code>nil</code> function value
|
||||
Calling a <code>nil</code> function value
|
||||
causes a <a href="#Run_time_panics">run-time panic</a>.
|
||||
</p>
|
||||
|
||||
@@ -2963,10 +3011,10 @@ follows:
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
For floating-point numbers,
|
||||
For floating-point and complex numbers,
|
||||
<code>+x</code> is the same as <code>x</code>,
|
||||
while <code>-x</code> is the negation of <code>x</code>.
|
||||
The result of a floating-point division by zero is not specified beyond the
|
||||
The result of a floating-point or complex division by zero is not specified beyond the
|
||||
IEEE-754 standard; whether a <a href="#Run_time_panics">run-time panic</a>
|
||||
occurs is implementation-specific.
|
||||
</p>
|
||||
@@ -3030,29 +3078,29 @@ These terms and the result of the comparisons are defined as follows:
|
||||
<li>
|
||||
Integer values are comparable and ordered, in the usual way.
|
||||
</li>
|
||||
|
||||
|
||||
<li>
|
||||
Floating point values are comparable and ordered,
|
||||
as defined by the IEEE-754 standard.
|
||||
</li>
|
||||
|
||||
|
||||
<li>
|
||||
Complex values are comparable.
|
||||
Two complex values <code>u</code> and <code>v</code> are
|
||||
equal if both <code>real(u) == real(v)</code> and
|
||||
<code>imag(u) == imag(v)</code>.
|
||||
</li>
|
||||
|
||||
|
||||
<li>
|
||||
String values are comparable and ordered, lexically byte-wise.
|
||||
</li>
|
||||
|
||||
|
||||
<li>
|
||||
Pointer values are comparable.
|
||||
Two pointer values are equal if they point to the same variable or if both have value <code>nil</code>.
|
||||
Pointers to distinct <a href="#Size_and_alignment_guarantees">zero-size</a> variables may or may not be equal.
|
||||
</li>
|
||||
|
||||
|
||||
<li>
|
||||
Channel values are comparable.
|
||||
Two channel values are equal if they were created by the same call to <code>make</code>
|
||||
@@ -3065,7 +3113,7 @@ These terms and the result of the comparisons are defined as follows:
|
||||
Two interface values are equal if they have <a href="#Type_identity">identical</a> dynamic types
|
||||
and equal dynamic values or if both have value <code>nil</code>.
|
||||
</li>
|
||||
|
||||
|
||||
<li>
|
||||
A value <code>x</code> of non-interface type <code>X</code> and
|
||||
a value <code>t</code> of interface type <code>T</code> are comparable when values
|
||||
@@ -3080,7 +3128,7 @@ These terms and the result of the comparisons are defined as follows:
|
||||
Two struct values are equal if their corresponding
|
||||
non-<a href="#Blank_identifier">blank</a> fields are equal.
|
||||
</li>
|
||||
|
||||
|
||||
<li>
|
||||
Array values are comparable if values of the array element type are comparable.
|
||||
Two array values are equal if their corresponding elements are equal.
|
||||
@@ -3171,6 +3219,9 @@ the value of the receive operation <code><-ch</code> is the value received
|
||||
from the channel <code>ch</code>. The type of the value is the element type of
|
||||
the channel. The expression blocks until a value is available.
|
||||
Receiving from a <code>nil</code> channel blocks forever.
|
||||
Receiving from a <a href="#Close">closed</a> channel always succeeds,
|
||||
immediately returning the element type's <a href="#The_zero_value">zero
|
||||
value</a>.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
@@ -3191,11 +3242,11 @@ var x, ok = <-ch
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
yields an additional result.
|
||||
The boolean variable <code>ok</code> indicates whether
|
||||
the received value was sent on the channel (<code>true</code>)
|
||||
or is a <a href="#The_zero_value">zero value</a> returned
|
||||
because the channel is closed and empty (<code>false</code>).
|
||||
yields an additional result of type <code>bool</code> reporting whether the
|
||||
communication succeeded. The value of <code>ok</code> is <code>true</code>
|
||||
if the value received was delivered by a successful send operation to the
|
||||
channel, or <code>false</code> if it is a zero value generated because the
|
||||
channel is closed and empty.
|
||||
</p>
|
||||
|
||||
<!--
|
||||
@@ -3477,7 +3528,7 @@ the range of valid Unicode code points are converted to <code>"\uFFFD"</code>.
|
||||
|
||||
<pre>
|
||||
string('a') // "a"
|
||||
string(-1) // "\ufffd" == "\xef\xbf\xbd "
|
||||
string(-1) // "\ufffd" == "\xef\xbf\xbd"
|
||||
string(0xf8) // "\u00f8" == "ø" == "\xc3\xb8"
|
||||
type MyString string
|
||||
MyString(0x65e5) // "\u65e5" == "日" == "\xe6\x97\xa5"
|
||||
@@ -3547,7 +3598,7 @@ wherever it is legal to use an operand of boolean, numeric, or string type,
|
||||
respectively.
|
||||
Except for shift operations, if the operands of a binary operation are
|
||||
different kinds of untyped constants, the operation and, for non-boolean operations, the result use
|
||||
the kind that appears later in this list: integer, character, floating-point, complex.
|
||||
the kind that appears later in this list: integer, rune, floating-point, complex.
|
||||
For example, an untyped integer constant divided by an
|
||||
untyped complex constant yields an untyped complex constant.
|
||||
</p>
|
||||
@@ -3575,7 +3626,7 @@ const f = int32(1) << 33 // f == 0 (type int32)
|
||||
const g = float64(2) >> 1 // illegal (float64(2) is a typed floating-point constant)
|
||||
const h = "foo" > "bar" // h == true (untyped boolean constant)
|
||||
const j = true // j == true (untyped boolean constant)
|
||||
const k = 'w' + 1 // k == 'x' (untyped character constant)
|
||||
const k = 'w' + 1 // k == 'x' (untyped rune constant)
|
||||
const l = "hi" // l == "hi" (untyped string constant)
|
||||
const m = string(k) // m == "x" (type string)
|
||||
const Σ = 1 - 0.707i // (untyped complex constant)
|
||||
@@ -3585,7 +3636,7 @@ const Φ = iota*1i - 1/1i // (untyped complex constant)
|
||||
|
||||
<p>
|
||||
Applying the built-in function <code>complex</code> to untyped
|
||||
integer, character, or floating-point constants yields
|
||||
integer, rune, or floating-point constants yields
|
||||
an untyped complex constant.
|
||||
</p>
|
||||
|
||||
@@ -3655,8 +3706,10 @@ overflow etc. errors being caught.
|
||||
<h3 id="Order_of_evaluation">Order of evaluation</h3>
|
||||
|
||||
<p>
|
||||
When evaluating the elements of an assignment or expression,
|
||||
all function calls, method calls and
|
||||
When evaluating the <a href="#Operands">operands</a> of an expression,
|
||||
<a href="#Assignments">assignment</a>, or
|
||||
<a href="#Return_statements">return statement</a>,
|
||||
all function calls, method calls, and
|
||||
communication operations are evaluated in lexical left-to-right
|
||||
order.
|
||||
</p>
|
||||
@@ -3676,6 +3729,12 @@ and indexing of <code>x</code> and the evaluation
|
||||
of <code>y</code> is not specified.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
a := 1
|
||||
f := func() int { a = 2; return 3 }
|
||||
x := []int{a, f()} // x may be [1, 3] or [2, 3]: evaluation order between a and f() is not specified
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Floating-point operations within a single expression are evaluated according to
|
||||
the associativity of the operators. Explicit parentheses affect the evaluation
|
||||
@@ -3866,7 +3925,11 @@ x, _ = f() // ignore second value returned by f()
|
||||
In the second form, the number of operands on the left must equal the number
|
||||
of expressions on the right, each of which must be single-valued, and the
|
||||
<i>n</i>th expression on the right is assigned to the <i>n</i>th
|
||||
operand on the left. The assignment proceeds in two phases.
|
||||
operand on the left.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The assignment proceeds in two phases.
|
||||
First, the operands of <a href="#Indexes">index expressions</a>
|
||||
and <a href="#Address_operators">pointer indirections</a>
|
||||
(including implicit pointer indirections in <a href="#Selectors">selectors</a>)
|
||||
@@ -3885,13 +3948,20 @@ i, x[i] = 1, 2 // set i = 1, x[0] = 2
|
||||
i = 0
|
||||
x[i], i = 2, 1 // set x[0] = 2, i = 1
|
||||
|
||||
x[0], x[0] = 1, 2 // set x[0] = 1, then x[0] = 2 (so x[0] = 2 at end)
|
||||
x[0], x[0] = 1, 2 // set x[0] = 1, then x[0] = 2 (so x[0] == 2 at end)
|
||||
|
||||
x[1], x[3] = 4, 5 // set x[1] = 4, then panic setting x[3] = 5.
|
||||
|
||||
type Point struct { x, y int }
|
||||
var p *Point
|
||||
x[2], p.x = 6, 7 // set x[2] = 6, then panic setting p.x = 7
|
||||
|
||||
i = 2
|
||||
x = []int{3, 5, 7}
|
||||
for i, x[i] = range x { // set i, x[2] = 0, x[0]
|
||||
break
|
||||
}
|
||||
// after this loop, i == 0 and x == []int{3, 5, 3}
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
@@ -3902,7 +3972,7 @@ is assigned to a variable of interface type, the constant is <a href="#Conversio
|
||||
to type <code>bool</code>, <code>rune</code>, <code>int</code>, <code>float64</code>,
|
||||
<code>complex128</code> or <code>string</code>
|
||||
respectively, depending on whether the value is a
|
||||
boolean, character, integer, floating-point, complex, or string constant.
|
||||
boolean, rune, integer, floating-point, complex, or string constant.
|
||||
</p>
|
||||
|
||||
|
||||
@@ -5401,7 +5471,7 @@ type ArbitraryType int // shorthand for an arbitrary Go type; it is not a real
|
||||
type Pointer *ArbitraryType
|
||||
|
||||
func Alignof(variable ArbitraryType) uintptr
|
||||
func Offsetof(selector ArbitraryType) uinptr
|
||||
func Offsetof(selector ArbitraryType) uintptr
|
||||
func Sizeof(variable ArbitraryType) uintptr
|
||||
</pre>
|
||||
|
||||
@@ -5441,7 +5511,6 @@ uintptr(unsafe.Pointer(&x)) % unsafe.Alignof(x) == 0
|
||||
Calls to <code>Alignof</code>, <code>Offsetof</code>, and
|
||||
<code>Sizeof</code> are compile-time constant expressions of type <code>uintptr</code>.
|
||||
</p>
|
||||
<p>
|
||||
|
||||
<h3 id="Size_and_alignment_guarantees">Size and alignment guarantees</h3>
|
||||
|
||||
|
||||
@@ -86,8 +86,14 @@ To build it, you need a C compiler installed.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
On OS X, a C compiler can be installed as part of
|
||||
<a href="http://developer.apple.com/Xcode/">Xcode</a>.
|
||||
On OS X, a C compiler is bundled in the command line tools for
|
||||
<a href="http://developer.apple.com/Xcode/">Xcode</a>,
|
||||
and you don't need to install the whole Xcode to compile Go.
|
||||
If you have already installed Xcode 4.3+, you can install command
|
||||
line tools from the Components tab of the Downloads preferences panel.
|
||||
To verify you have a working compiler, just invoke <code>gcc</code>
|
||||
in a freshly created Terminal window, unless you see the
|
||||
"<code>gcc: command not found</code>" error, you are ready to go.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
@@ -106,26 +112,13 @@ On Windows, install <code>gcc</code> with
|
||||
|
||||
<p>
|
||||
To perform the next step you must have Mercurial installed. (Check that you
|
||||
have an <code>hg</code> command.) This suffices to install Mercurial on most
|
||||
Unix systems:
|
||||
have an <code>hg</code> command.)
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
sudo easy_install mercurial==2.0
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
On Ubuntu/Debian, the Mercurial in your distribution's
|
||||
package repository is most likely old and broken.
|
||||
You might try this first:
|
||||
</p>
|
||||
|
||||
<pre>apt-get install python-setuptools python-dev build-essential</pre>
|
||||
|
||||
<p>
|
||||
If that fails, or if you use Windows, install manually from the
|
||||
<a href="http://mercurial.selenic.com/wiki/Download">Mercurial Download</a>
|
||||
page.
|
||||
If you do not have a working Mercurial installation,
|
||||
follow the instructions on the
|
||||
<a href="http://mercurial.selenic.com/downloads/">Mercurial downloads</a> page.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
@@ -183,7 +176,6 @@ ALL TESTS PASSED
|
||||
Installed Go for linux/amd64 in /home/you/go.
|
||||
Installed commands in /home/you/go/bin.
|
||||
*** You need to add /home/you/go/bin to your $PATH. ***
|
||||
The compiler is 6g.
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
@@ -255,8 +247,8 @@ Bugs can be reported using the <a href="http://code.google.com/p/go/issues/list"
|
||||
<h2 id="releases">Keeping up with releases</h2>
|
||||
|
||||
<p>
|
||||
The Go project maintains two stable tags in its Mercurial repository:
|
||||
<code>release</code> and <code>weekly</code>.
|
||||
The Go project maintains a stable tag in its Mercurial repository:
|
||||
<code>release</code>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
@@ -277,12 +269,6 @@ $ hg update release
|
||||
$ ./all.bash
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
The <code>weekly</code> tag is updated about once a week, and should be used
|
||||
only by those who are actively working on the Go core.
|
||||
To use the <code>weekly</code> tag run <code>hg update weekly</code> instead.
|
||||
</p>
|
||||
|
||||
|
||||
<h2 id="environment">Optional environment variables</h2>
|
||||
|
||||
|
||||
@@ -24,6 +24,37 @@ For information about installing <code>gccgo</code>, see
|
||||
<a href="/doc/install/gccgo">Setting up and using gccgo</a>.
|
||||
</p>
|
||||
|
||||
<h2 id="requirements">System requirements</h2>
|
||||
<p>
|
||||
The <code>gc</code> compiler supports the following operating systems and
|
||||
architectures. Please ensure your system meets these requirements before
|
||||
proceeding. If your OS or architecture is not on the list, it's possible that
|
||||
<code>gccgo</code> might support your setup; see
|
||||
<a href="/doc/install/gccgo">Setting up and using gccgo</a> for details.
|
||||
</p>
|
||||
|
||||
<table class="codetable" frame="border" summary="requirements">
|
||||
<tr>
|
||||
<th align="middle">Operating system</th>
|
||||
<th align="middle">Architectures</th>
|
||||
<th align="middle">Notes</th>
|
||||
</tr>
|
||||
<tr><td colspan="3"><hr></td></tr>
|
||||
<tr><td>FreeBSD 7 or later</td> <td>amd64, 386</td> <td>Debian GNU/kFreeBSD not supported</td></tr>
|
||||
<tr><td>Linux 2.6.23 or later with glibc</td> <td>amd64, 386, arm</td> <td>CentOS/RHEL 5.x not supported; no binary distribution for ARM yet</td></tr>
|
||||
<tr><td>Mac OS X 10.6/10.7</td> <td>amd64, 386</td> <td>use the gcc<sup>†</sup> that comes with Xcode<sup>‡</sup></td></tr>
|
||||
<tr><td>Windows 2000 or later</td> <td>amd64, 386</td> <td>use mingw gcc<sup>†</sup>; cygwin or msys is not needed</td></tr>
|
||||
</table>
|
||||
|
||||
<p>
|
||||
<sup>†</sup><code>gcc</code> is required only if you plan to use
|
||||
<a href="/cmd/cgo">cgo</a>.<br/>
|
||||
<sup>‡</sup>You only need to install the command line tools for
|
||||
<a href="http://developer.apple.com/Xcode/">Xcode</a>. If you have already
|
||||
installed Xcode 4.3+, you can install it from the Components tab of the
|
||||
Downloads preferences panel.
|
||||
</p>
|
||||
|
||||
<h2 id="download">Download the Go tools</h2>
|
||||
|
||||
<p>
|
||||
@@ -72,10 +103,10 @@ Windows users should read the section about <a href="#windows_env">setting
|
||||
environment variables under Windows</a>.
|
||||
</p>
|
||||
|
||||
<h3 id="freebsd_linux">FreeBSD and Linux</h3>
|
||||
<h3 id="freebsd_linux">FreeBSD, Linux, and Mac OS X tarballs</h3>
|
||||
|
||||
<p>
|
||||
On FreeBSD and Linux, if you are upgrading from an older version of Go you must
|
||||
If you are upgrading from an older version of Go you must
|
||||
first remove the existing version from <code>/usr/local/go</code>:
|
||||
</p>
|
||||
|
||||
@@ -84,12 +115,12 @@ rm -r /usr/local/go
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Extract <a href="http://code.google.com/p/go/downloads/list?q=OpSys-FreeBSD+OR+OpSys-Linux">the archive</a>
|
||||
Extract <a href="http://code.google.com/p/go/downloads/list?q=OpSys-FreeBSD+OR+OpSys-Linux+OR+OpSys-OSX+AND+Type-Archive">the archive</a>
|
||||
into <code>/usr/local</code>, creating a Go tree in <code>/usr/local/go</code>:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
tar -C /usr/local -xzf go.release.go1.tar.gz
|
||||
tar -C /usr/local -xzf go1.0.2.linux-amd64.tar.gz
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
@@ -106,10 +137,10 @@ variable. You can do this by adding this line to your <code>/etc/profile</code>
|
||||
export PATH=$PATH:/usr/local/go/bin
|
||||
</pre>
|
||||
|
||||
<h3 id="osx">Mac OS X</h3>
|
||||
<h3 id="osx">Mac OS X package installer</h3>
|
||||
|
||||
<p>
|
||||
Open the <a href="http://code.google.com/p/go/downloads/list?q=OpSys-Darwin">package file</a>
|
||||
Open the <a href="http://code.google.com/p/go/downloads/list?q=OpSys-Darwin+AND+Type-Installer">package file</a>
|
||||
and follow the prompts to install the Go tools.
|
||||
The package installs the Go distribution to <code>/usr/local/go</code>.
|
||||
</p>
|
||||
@@ -129,7 +160,7 @@ a zip archive that requires you to set some environment variables and an
|
||||
experimental MSI installer that configures your installation automatically.
|
||||
</p>
|
||||
|
||||
<h4 id="windows_zip">Zip archive</h3>
|
||||
<h4 id="windows_zip">Zip archive</h4>
|
||||
|
||||
<p>
|
||||
Extract the <a href="http://code.google.com/p/go/downloads/list?q=OpSys-Windows+Type%3DArchive">zip file</a>
|
||||
@@ -145,7 +176,7 @@ the <code>GOROOT</code> environment variable to your chosen path.
|
||||
Add the <code>bin</code> subdirectory of your Go root (for example, <code>c:\Go\bin</code>) to to your <code>PATH</code> environment variable.
|
||||
</p>
|
||||
|
||||
<h4 id="windows_msi">MSI installer (experimental)</h3>
|
||||
<h4 id="windows_msi">MSI installer (experimental)</h4>
|
||||
|
||||
<p>
|
||||
Open the <a href="http://code.google.com/p/go/downloads/list?q=OpSys-Windows+Type%3DInstaller">MSI file</a>
|
||||
|
||||
@@ -6,13 +6,14 @@
|
||||
// codeEl - code editor element
|
||||
// outputEl - program output element
|
||||
// runEl - run button element
|
||||
// fmtEl - fmt button element (optional)
|
||||
// shareEl - share button element (optional)
|
||||
// shareURLEl - share URL text input element (optional)
|
||||
// shareRedirect - base URL to redirect to on share (optional)
|
||||
// preCompile - callback to mutate request data before compiling
|
||||
// postCompile - callback to read response data after compiling
|
||||
// simple - use plain textarea instead of CodeMirror.
|
||||
// toysEl - select element with a list of toys.
|
||||
// preCompile - callback to mutate request data before compiling (optional)
|
||||
// postCompile - callback to read response data after compiling (optional)
|
||||
// simple - use plain textarea instead of CodeMirror. (optional)
|
||||
// toysEl - select element with a list of toys. (optional)
|
||||
function playground(opts) {
|
||||
var simple = opts['simple'];
|
||||
var code = $(opts['codeEl']);
|
||||
@@ -97,7 +98,7 @@ function playground(opts) {
|
||||
if (!editor) {
|
||||
return;
|
||||
}
|
||||
var errorRe = /[a-z]+\.go:([0-9]+): /g;
|
||||
var errorRe = /[a-z]+\.go:([0-9]+):/g;
|
||||
var result;
|
||||
while ((result = errorRe.exec(text)) != null) {
|
||||
var line = result[1]*1-1;
|
||||
@@ -120,13 +121,23 @@ function playground(opts) {
|
||||
function origin(href) {
|
||||
return (""+href).split("/").slice(0, 3).join("/");
|
||||
}
|
||||
function loading() {
|
||||
output.removeClass("error").html(
|
||||
'<div class="loading">Waiting for remote server...</div>'
|
||||
);
|
||||
}
|
||||
function setOutput(text, error) {
|
||||
output.empty();
|
||||
if (error) {
|
||||
output.addClass("error");
|
||||
}
|
||||
$("<pre/>").text(text).appendTo(output);
|
||||
}
|
||||
|
||||
var seq = 0;
|
||||
function run() {
|
||||
clearErrors();
|
||||
output.removeClass("error").html(
|
||||
'<div class="loading">Waiting for remote server...</div>'
|
||||
);
|
||||
loading();
|
||||
seq++;
|
||||
var cur = seq;
|
||||
var data = {"body": body()};
|
||||
@@ -141,8 +152,6 @@ function playground(opts) {
|
||||
if (seq != cur) {
|
||||
return;
|
||||
}
|
||||
pre = $("<pre/>");
|
||||
output.empty().append(pre);
|
||||
if (opts['postCompile']) {
|
||||
opts['postCompile'](data);
|
||||
}
|
||||
@@ -150,8 +159,7 @@ function playground(opts) {
|
||||
return;
|
||||
}
|
||||
if (data.compile_errors != "") {
|
||||
pre.text(data.compile_errors);
|
||||
output.addClass("error");
|
||||
setOutput(data.compile_errors, true);
|
||||
highlightErrors(data.compile_errors);
|
||||
return;
|
||||
}
|
||||
@@ -164,11 +172,10 @@ function playground(opts) {
|
||||
output.empty().append(img);
|
||||
return;
|
||||
}
|
||||
pre.text(out);
|
||||
setOutput(out, false);
|
||||
},
|
||||
error: function(xhr) {
|
||||
var text = "Error communicating with remote server.";
|
||||
console.log(xhr.status);
|
||||
if (xhr.status == 501) {
|
||||
text = xhr.responseText;
|
||||
}
|
||||
@@ -178,6 +185,41 @@ function playground(opts) {
|
||||
}
|
||||
$(opts['runEl']).click(run);
|
||||
|
||||
$(opts['fmtEl']).click(function() {
|
||||
loading();
|
||||
$.ajax("/fmt", {
|
||||
data: {"body": body()},
|
||||
type: "POST",
|
||||
dataType: "json",
|
||||
success: function(data) {
|
||||
if (data.Error) {
|
||||
setOutput(data.Error, true);
|
||||
highlightErrors(data.Error);
|
||||
return;
|
||||
}
|
||||
setBody(data.Body);
|
||||
setOutput("", false);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$(opts['toysEl']).bind('change', function() {
|
||||
var toy = $(this).val();
|
||||
loading();
|
||||
$.ajax("/doc/play/"+toy, {
|
||||
processData: false,
|
||||
type: "GET",
|
||||
complete: function(xhr) {
|
||||
if (xhr.status != 200) {
|
||||
setOutput("Server error; try again.", true);
|
||||
return;
|
||||
}
|
||||
setBody(xhr.responseText);
|
||||
setOutput("", false);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
if (opts['shareEl'] != null && (opts['shareURLEl'] != null || opts['shareRedirect'] != null)) {
|
||||
var shareURL;
|
||||
if (opts['shareURLEl']) {
|
||||
@@ -213,22 +255,5 @@ function playground(opts) {
|
||||
});
|
||||
}
|
||||
|
||||
if (opts['toysEl'] != null) {
|
||||
$(opts['toysEl']).bind('change', function() {
|
||||
var toy = $(this).val();
|
||||
$.ajax("/doc/play/"+toy, {
|
||||
processData: false,
|
||||
type: "GET",
|
||||
complete: function(xhr) {
|
||||
if (xhr.status != 200) {
|
||||
alert("Server error; try again.")
|
||||
return;
|
||||
}
|
||||
setBody(xhr.responseText);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return editor;
|
||||
}
|
||||
|
||||
@@ -2,9 +2,9 @@ package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"html/template"
|
||||
"log"
|
||||
"net/http"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
var addr = flag.String("addr", ":1718", "http service address") // Q=17, R=18
|
||||
@@ -31,9 +31,9 @@ const templateStr = `
|
||||
</head>
|
||||
<body>
|
||||
{{if .}}
|
||||
<img src="http://chart.apis.google.com/chart?chs=300x300&cht=qr&choe=UTF-8&chl={{urlquery .}}" />
|
||||
<img src="http://chart.apis.google.com/chart?chs=300x300&cht=qr&choe=UTF-8&chl={{.}}" />
|
||||
<br>
|
||||
{{html .}}
|
||||
{{.}}
|
||||
<br>
|
||||
<br>
|
||||
{{end}}
|
||||
|
||||
@@ -84,8 +84,8 @@ func ConvAndCircle() {
|
||||
|
||||
// CONV OMIT
|
||||
b := src.Bounds()
|
||||
m := image.NewRGBA(image.Rect(0, 0, b.Dx(), b.Dy()))
|
||||
draw.Draw(m, m.Bounds(), src, b.Min, draw.Src)
|
||||
m := image.NewRGBA(b)
|
||||
draw.Draw(m, b, src, b.Min, draw.Src)
|
||||
// STOP OMIT
|
||||
|
||||
p := image.Point{100, 100}
|
||||
|
||||
@@ -24,10 +24,10 @@ The documentation for the Go tools.
|
||||
The official Go Language specification.
|
||||
</p>
|
||||
|
||||
<h3 id="appengine"><a href="http://code.google.com/appengine/docs/go/">App Engine Go Runtime Documentation</a></h3>
|
||||
<h3 id="appengine"><a href="https://developers.google.com/appengine/docs/go/">App Engine Go Runtime Documentation</a></h3>
|
||||
<p>
|
||||
The documentation for
|
||||
<a href="http://code.google.com/appengine/">Google App Engine</a>'s Go runtime.
|
||||
<a href="https://developers.google.com/appengine/">Google App Engine</a>'s Go runtime.
|
||||
</p>
|
||||
|
||||
<h3 id="go_mem"><a href="/ref/mem">The Go Memory Model</a></h3>
|
||||
|
||||
@@ -68,8 +68,7 @@ Linux, Mac OS X, Windows, and more.
|
||||
|
||||
<div id="video">
|
||||
<div class="rootHeading">Featured video</div>
|
||||
<a class="title" href="http://www.youtube.com/watch?v=Mo1YKpIF1PQ">Building integrated apps on Google's cloud platform with Go</a>
|
||||
<iframe width="415" height="241" src="http://www.youtube.com/embed/Mo1YKpIF1PQ" frameborder="0" allowfullscreen></iframe>
|
||||
<iframe width="415" height="241" src="http://www.youtube.com/embed/ytEkHepK08c" frameborder="0" allowfullscreen></iframe>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -108,7 +108,9 @@ table.dir td {
|
||||
word-wrap: break-word;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
div#page.wide table.dir td.name {
|
||||
white-space: nowrap;
|
||||
}
|
||||
.alert {
|
||||
color: #AA0000;
|
||||
}
|
||||
@@ -371,6 +373,7 @@ div#blog .read {
|
||||
.toggleVisible .expanded { display: block; }
|
||||
|
||||
table.codetable { margin-left: auto; margin-right: auto; border-style: none; }
|
||||
table.codetable td { padding-right: 10px; }
|
||||
hr { border-style: none; border-top: 1px solid black; }
|
||||
|
||||
img.gopher {
|
||||
@@ -388,4 +391,3 @@ img.gopher {
|
||||
margin-bottom: -120px;
|
||||
}
|
||||
h2 { clear: right; }
|
||||
|
||||
|
||||
Binary file not shown.
@@ -1,411 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<title>Go (January 12, 2010)</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="font-size-adjustment" content="-1" />
|
||||
<link rel="stylesheet" href="slidy.css"
|
||||
type="text/css" media="screen, projection, print" />
|
||||
<script src="slidy.js" type="text/javascript">
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<!-- this defines the slide background -->
|
||||
|
||||
<div class="background">
|
||||
|
||||
<div class="header">
|
||||
<!-- sized and colored via CSS -->
|
||||
</div>
|
||||
|
||||
<div class="footer"></div>
|
||||
</div>
|
||||
|
||||
<div class="slide titlepage">
|
||||
<div style="height: 135px; width: 480px; overflow: hidden; position: fixed; top: auto; bottom: 10px; left: auto; right: 0; ">
|
||||
<img src="../gordon/bumper480x270.png" style="margin: -135px 0 0 0;"/>
|
||||
</div>
|
||||
<!-- <img src="google.png" style="position: fixed; top: auto; bottom: 30px; left: 20px; right: auto;"/> -->
|
||||
<br/>
|
||||
<img src="../go-logo-white.png">
|
||||
<br/>
|
||||
<br/>
|
||||
<h1 style="padding-right: 0pt; margin-right: 0pt; color: #0066cc; font-size: 250%; border-bottom: 0px;">The Go Programming Language</h1>
|
||||
<div style="color: #ffcc00;">
|
||||
<h2>Russ Cox</h2>
|
||||
<!-- <h3><i>rsc@google.com</i></h3> -->
|
||||
<br/>
|
||||
<h3>Stanford University<br/><br/>January 12, 2010</h3>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="slide">
|
||||
<h1>Go</h1>
|
||||
|
||||
<h2>New</h2>
|
||||
<h2>Experimental</h2>
|
||||
<h2>Concurrent</h2>
|
||||
<h2>Garbage-collected</h2>
|
||||
<h2>Systems</h2>
|
||||
<h2>Language</h2>
|
||||
</div>
|
||||
|
||||
<div class="slide">
|
||||
<h1>Hello, world</h1>
|
||||
<pre>
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
fmt.Printf("Hello, 世界\n")
|
||||
}
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<div class="slide">
|
||||
<h1>History</h1>
|
||||
|
||||
<h2>Design started in late 2007.</h2>
|
||||
<h2>Implementation starting to work mid-2008.</h2>
|
||||
<h2>Released as an open source project in November 2009.</h2>
|
||||
<h2>Work continues.<h2>
|
||||
<h2>Robert Griesemer, Ken Thompson, Rob Pike, Ian Lance Taylor, Russ Cox, many others</h2>
|
||||
</div>
|
||||
|
||||
<div class="slide">
|
||||
<h1>Why?</h1>
|
||||
|
||||
<h2>Go fast!</h2>
|
||||
<h2>Make programming fun again.</h2>
|
||||
</div>
|
||||
|
||||
<div class="slide">
|
||||
<h1>Why isn't programming fun?</h1>
|
||||
|
||||
<div class="incremental">
|
||||
<h2>Compiled, statically-typed languages (C, C++, Java) require too much typing and too much typing:</h2>
|
||||
|
||||
<ul>
|
||||
<li>verbose, lots of repetition</li>
|
||||
<li>too much focus on type hierarchy</li>
|
||||
<li>types get in the way as much as they help</li>
|
||||
<li>compiles take far too long</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="incremental">
|
||||
<h2>Dynamic languages (Python, JavaScript) fix these problems (no more types, no more compiler) but introduce others:</h2>
|
||||
|
||||
<ul>
|
||||
<li>errors at run time that should be caught statically</li>
|
||||
<li>no compilation means slow code</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<h2 class="incremental">Can we combine the best of both?</h2>
|
||||
</div>
|
||||
|
||||
<div class="slide">
|
||||
<h1>Go</h1>
|
||||
|
||||
<h2>Make the language fast.</h2>
|
||||
<h2>Make the tools fast.</h2>
|
||||
</div>
|
||||
|
||||
<div class="slide">
|
||||
<h1>Go Approach: Static Types</h1>
|
||||
|
||||
<h2>Static types, but declarations can infer type from expression:</h2>
|
||||
|
||||
<pre>
|
||||
var one, hi = 1, "hello"
|
||||
|
||||
var double = func(x int) int { return x*2 }
|
||||
</pre>
|
||||
|
||||
<h2>Not full Hindley-Milner type inference.</h2>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="slide">
|
||||
<h1>Go Approach: Methods</h1>
|
||||
|
||||
<h2>Methods can be defined on any type.</h2>
|
||||
|
||||
<pre>
|
||||
type Point struct {
|
||||
X, Y float64
|
||||
}
|
||||
|
||||
func (p Point) Abs() float64 {
|
||||
return math.Sqrt(p.X*p.X + p.Y*p.Y)
|
||||
}
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<div class="slide">
|
||||
<h1>Go Approach: Methods</h1>
|
||||
|
||||
<h2>Methods can be defined on any type.</h2>
|
||||
|
||||
<pre>
|
||||
type MyFloat float64
|
||||
|
||||
func (f MyFloat) Abs() float64 {
|
||||
v := float64(f)
|
||||
if v < 0 {
|
||||
v = -v
|
||||
}
|
||||
return v
|
||||
}
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<div class="slide">
|
||||
<h1>Go Approach: Abstract Types</h1>
|
||||
|
||||
<h2>An interface type lists a set of methods. Any value with those methods satisfies the interface.</h2>
|
||||
|
||||
<pre>
|
||||
type Abser interface {
|
||||
Abs() float64
|
||||
}
|
||||
|
||||
func AbsPrinter(a Abser)
|
||||
</pre>
|
||||
|
||||
<h2>Can use Point or MyFloat (or ...):</h2>
|
||||
|
||||
<pre>
|
||||
p := Point{3, 4}
|
||||
AbsPrinter(p)
|
||||
|
||||
f := MyFloat(-10)
|
||||
AbsPrinter(f)
|
||||
</pre>
|
||||
|
||||
<h2>Notice that Point never declared that it implements Abser. It just does. Same with MyFloat.</h2>
|
||||
</div>
|
||||
|
||||
<div class="slide">
|
||||
<h1>Go Approach: Packages</h1>
|
||||
|
||||
<h2>A Go program comprises one or more packages.</h2>
|
||||
<h2>Each package is one or more source files compiled and imported as a unit.</h2>
|
||||
<pre>
|
||||
package draw
|
||||
|
||||
type Point struct {
|
||||
X, Y int
|
||||
}
|
||||
</pre>
|
||||
|
||||
<pre>
|
||||
package main
|
||||
|
||||
import "draw"
|
||||
|
||||
var p draw.Point
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<div class="slide">
|
||||
<h1>Go Approach: Visibility</h1>
|
||||
|
||||
<h2>Inside a package, all locally defined names are visible in all source files.</h2>
|
||||
|
||||
<h2>When imported, only the upper case names are visible.</h2>
|
||||
|
||||
<pre>
|
||||
package draw
|
||||
|
||||
type <span style="color: black;">Point</span> struct {
|
||||
<span style="color: black;">X</span>, <span style="color: black;">Y</span> int
|
||||
dist float64
|
||||
}
|
||||
|
||||
type cache map[Point] float64
|
||||
</pre>
|
||||
|
||||
<h2>Clients that <code>import "draw"</code> can use the black names only.</h2>
|
||||
|
||||
<h2>“Shift is the new <code>public</code>.”</h2>
|
||||
</div>
|
||||
|
||||
<div class="slide">
|
||||
<h1>Go Approach: Concurrency</h1>
|
||||
|
||||
<h2>Cheap to create a new flow of control (goroutine):</h2>
|
||||
|
||||
<pre>
|
||||
func main() {
|
||||
go expensiveComputation(x, y, z)
|
||||
anotherExpensiveComputation(a, b, c)
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h2>Two expensive computations in parallel.</h2>
|
||||
</div>
|
||||
|
||||
<div class="slide">
|
||||
<h1>Go Approach: Synchronization</h1>
|
||||
|
||||
<h2>Use explicit messages to communicate and synchronize.</h2>
|
||||
|
||||
<pre>
|
||||
func computeAndSend(ch chan int, x, y, z int) {
|
||||
ch <- expensiveComputation(x, y, z)
|
||||
}
|
||||
|
||||
func main() {
|
||||
ch := make(chan int)
|
||||
go computeAndSend(ch, x, y, z)
|
||||
v2 := anotherExpensiveComputation(a, b, c)
|
||||
v1 := <-ch
|
||||
fmt.Println(v1, v2)
|
||||
}
|
||||
</pre>
|
||||
<h2>Notice communication of result in addition to synchronization.</h2>
|
||||
</div>
|
||||
|
||||
<div class="slide">
|
||||
<h1>Go Fast: Language</h1>
|
||||
|
||||
<h2 class="incremental">Static types: enough to compile well, but inferred much of the time.</h2>
|
||||
|
||||
<h2 class="incremental">Methods: on any type, orthogonal to type system.</h2>
|
||||
|
||||
<h2 class="incremental">Abstract types: interface values, relations inferred statically.</h2>
|
||||
|
||||
<h2 class="incremental">Visibility: inferred from case of name.</h2>
|
||||
|
||||
<h2 class="incremental">Concurrency: lightweight way to start new thread of control.</h2>
|
||||
|
||||
<h2 class="incremental">Synchronization: explicit, easy message passing.</h2>
|
||||
|
||||
<br/>
|
||||
|
||||
<h2 class="incremental">Lightweight feel of a scripting language but compiled.</h2>
|
||||
</div>
|
||||
|
||||
<div class="slide">
|
||||
<h1>Compile fast</h1>
|
||||
|
||||
<div class="incremental">
|
||||
<h2>Observation: much of the compile time for a source file is spent processing
|
||||
other, often unrelated files.</h2>
|
||||
|
||||
<h2>In C: <code>a.c</code> includes <code>b.h</code>, which includes <code>c.h</code>, which includes <code>d.h</code>.
|
||||
</h2>
|
||||
|
||||
<h2>Except that it's more often a tree instead of a chain.</h2>
|
||||
|
||||
<h2>On my Mac (OS X 10.5.8, gcc 4.0.1):</h2>
|
||||
<ul>
|
||||
<li>C: <code>#include <stdio.h></code> reads 360 lines from 9 files.
|
||||
<li>C++: <code>#include <iostream></code> reads 25,326 lines from 131 files.
|
||||
<li>Objective C: <code>#include <Carbon/Carbon.h></code> reads 124,730 lines from 689 files.
|
||||
</ul>
|
||||
|
||||
<h2>And we haven't done any real work yet!</h2>
|
||||
|
||||
<h2>Same story in Java, Python, but reading binaries instead of source files.</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="slide">
|
||||
<h1>Implementation: Summarize Dependencies</h1>
|
||||
|
||||
<pre>
|
||||
package gui
|
||||
|
||||
import "draw"
|
||||
|
||||
type Mouse struct {
|
||||
Loc draw.Point
|
||||
Buttons uint
|
||||
}
|
||||
</pre>
|
||||
<h2>Compiled form of <code>gui</code> summarizes the necessary part of <code>draw</code> (just <code>Point</code>).</h2>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="slide">
|
||||
<h1>Implementation: Summarize Dependencies</h1>
|
||||
|
||||
<h2>Compiled form of <code>gui</code> summarizes the necessary part of <code>draw</code> (just <code>Point</code>). Pseudo-object:</h2>
|
||||
|
||||
<pre>
|
||||
package gui
|
||||
type draw.Point struct {
|
||||
X, Y int
|
||||
}
|
||||
type gui.Mouse struct {
|
||||
Loc draw.Point
|
||||
Buttons uint
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h2>A file that imports <code>gui</code> compiles without consulting <code>draw</code> or its dependencies.</h2>
|
||||
|
||||
<h2>In Go: <code>import "fmt"</code> reads <i>one</i> file: 184 lines summarizing types from 7 packages.</h2>
|
||||
|
||||
<h2>Tiny effect in this program but can be exponential in large programs.</h2>
|
||||
</div>
|
||||
|
||||
<div class="slide">
|
||||
<h1>Compilation Demo</h1>
|
||||
|
||||
<h2>Build all standard Go packages: ~120,000 lines of code.</h2>
|
||||
</div>
|
||||
|
||||
<div class="slide">
|
||||
<h1>Go Status</h1>
|
||||
|
||||
<div class="incremental">
|
||||
<div>
|
||||
<h2>Open source:</h2>
|
||||
<ul>
|
||||
<li>released on November 10, 2009
|
||||
<li>regular releases (~ weekly)
|
||||
<li>all development done in public Mercurial repository
|
||||
<li>outside contributions welcome
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h2>Portable:</h2>
|
||||
<ul>
|
||||
<li>FreeBSD, Linux, OS X (x86, x86-64)
|
||||
<li>(in progress) Linux arm, Native Client x86, Windows x86.
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h2>Still in progress, experimental. Yet to come:</h2>
|
||||
<ul>
|
||||
<li>mature garbage collector
|
||||
<li>generics?
|
||||
<li>exceptions?
|
||||
<li>unions or sum types?
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="slide titlepage">
|
||||
<h1>Questions?</h1>
|
||||
<br><br>
|
||||
<center>
|
||||
<img src="../gordon/bumper640x360.png">
|
||||
</center>
|
||||
<br><br>
|
||||
<div style="color: #ffcc00;">
|
||||
<!-- <h3><i>rsc@google.com</i></h3> -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body></html>
|
||||
@@ -1,453 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<title>Go, Networked (January 21, 2010)</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="font-size-adjustment" content="-1" />
|
||||
<link rel="stylesheet" href="slidy.css"
|
||||
type="text/css" media="screen, projection, print" />
|
||||
<script src="slidy.js" type="text/javascript">
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<!-- this defines the slide background -->
|
||||
|
||||
<div class="background">
|
||||
|
||||
<div class="header">
|
||||
<!-- sized and colored via CSS -->
|
||||
</div>
|
||||
|
||||
<div class="footer"></div>
|
||||
</div>
|
||||
|
||||
<div class="slide titlepage">
|
||||
<div style="height: 135px; width: 480px; overflow: hidden; position: fixed; top: auto; bottom: 10px; left: auto; right: 0; ">
|
||||
<img src="../gordon/bumper480x270.png" style="margin: -135px 0 0 0;"/>
|
||||
</div>
|
||||
<!-- <img src="../google.png" style="position: fixed; top: auto; bottom: 30px; left: 20px; right: auto;"/> -->
|
||||
<br/>
|
||||
<img src="../go-logo-white.png">
|
||||
<br/>
|
||||
<br/>
|
||||
<h1 style="padding-right: 0pt; margin-right: 0pt; color: #0066cc; font-size: 250%; border-bottom: 0px;">The Go Programming Language</h1>
|
||||
<div style="color: #ffcc00;">
|
||||
<h2>Russ Cox</h2>
|
||||
<!-- <h3><i>rsc@google.com</i></h3> -->
|
||||
<br/>
|
||||
<h3>CNS Winter Research Review<br/><br/>January 21, 2010</h3>
|
||||
<br/>
|
||||
<br/>
|
||||
<!--
|
||||
<h4><i>click to start; then left/right arrow to change slides</i></h4> -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="slide">
|
||||
<h1>Go</h1>
|
||||
|
||||
<h2>New</h2>
|
||||
<h2>Experimental</h2>
|
||||
<h2>Concurrent</h2>
|
||||
<h2>Garbage-collected</h2>
|
||||
<h2>Systems</h2>
|
||||
<h2>Language</h2>
|
||||
</div>
|
||||
|
||||
<div class="slide">
|
||||
<h1>Hello, world</h1>
|
||||
<pre>
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
fmt.Printf("Hello, 世界\n")
|
||||
}
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<div class="slide">
|
||||
<h1>History</h1>
|
||||
|
||||
<h2>Design started in late 2007.</h2>
|
||||
<h2>Implementation starting to work mid-2008.</h2>
|
||||
<h2>Released as an open source project in November 2009.</h2>
|
||||
<h2>Work continues.<h2>
|
||||
<h2>Robert Griesemer, Ken Thompson, Rob Pike, Ian Lance Taylor, Russ Cox, many others</h2>
|
||||
</div>
|
||||
|
||||
<div class="slide">
|
||||
<h1>Goals and Motivation</h1>
|
||||
|
||||
<h2>Go fast!</h2>
|
||||
<h2>Make programming fun again.</h2>
|
||||
<h2>Targeted at systems software, broadly.</h2>
|
||||
</div>
|
||||
|
||||
<div class="slide">
|
||||
<h1>Why isn't programming fun?</h1>
|
||||
|
||||
<div class="incremental">
|
||||
<h2>Compiled, statically-typed languages (C, C++, Java) require too much typing and too much typing:</h2>
|
||||
|
||||
<ul>
|
||||
<li>verbose, lots of repetition</li>
|
||||
<li>too much focus on type hierarchy</li>
|
||||
<li>types get in the way as much as they help</li>
|
||||
<li>compiles take far too long</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="incremental">
|
||||
<h2>Dynamic languages (Python, JavaScript) fix these problems (no more types, no more compiler) but introduce others:</h2>
|
||||
|
||||
<ul>
|
||||
<li>errors at run time that should be caught statically</li>
|
||||
<li>no compilation means slow code</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<h2 class="incremental">Can we combine the best of both?</h2>
|
||||
</div>
|
||||
|
||||
<div class="slide">
|
||||
<h1>Why a new language?</h1>
|
||||
|
||||
<div class="incremental">
|
||||
<h2>No new systems language in 10+ years.</h2>
|
||||
<h2>Current languages designed before ...</h2>
|
||||
<h3>... rise of large-scale, networked and multicore computing</h3>
|
||||
<h3>... rise of Internet-scale distributed development (many libraries)</h3>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="slide">
|
||||
<h1>Go</h1>
|
||||
|
||||
<h2>Make the language fast.</h2>
|
||||
<h2>Make the tools fast.</h2>
|
||||
</div>
|
||||
|
||||
<div class="slide">
|
||||
<h1>Compilation Demo</h1>
|
||||
|
||||
<h2>Build all standard Go packages: ~120,000 lines of code.</h2>
|
||||
</div>
|
||||
|
||||
<div class="slide">
|
||||
<h1>Go in one slide</h1>
|
||||
|
||||
<h2 class="incremental">Lightweight syntax.</h2>
|
||||
|
||||
<h2 class="incremental">Static types: enough to compile well, but inferred much of the time.</h2>
|
||||
|
||||
<h2 class="incremental">Methods: on any type, orthogonal to type system.</h2>
|
||||
|
||||
<h2 class="incremental">Abstract types: interface values, relations inferred statically.</h2>
|
||||
|
||||
<h2 class="incremental">Visibility: inferred from case of name.</h2>
|
||||
|
||||
<h2 class="incremental">First-class functions.</h2>
|
||||
|
||||
<h2 class="incremental">Garbage collection.</h2>
|
||||
|
||||
<br/>
|
||||
|
||||
<h2 class="incremental">Lightweight feel of a scripting language but compiled.</h2>
|
||||
</div>
|
||||
|
||||
<div class="slide">
|
||||
<h1>Go, concurrently</h1>
|
||||
|
||||
<h2>Cheap to create a new flow of control (goroutine):</h2>
|
||||
|
||||
<pre>
|
||||
func main() {
|
||||
go expensiveComputation(x, y, z)
|
||||
anotherExpensiveComputation(a, b, c)
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h2>Two expensive computations in parallel.</h2>
|
||||
</div>
|
||||
|
||||
<div class="slide">
|
||||
<h1>Go, concurrently</h1>
|
||||
|
||||
<h2>Cheap to create a new flow of control (goroutine):</h2>
|
||||
|
||||
<pre>
|
||||
for {
|
||||
rw := l.Accept()
|
||||
conn := newConn(rw, handler)
|
||||
go conn.serve()
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h2>Concurrent web server.</h2>
|
||||
<h2>Network connections multiplexed onto epoll.</h2>
|
||||
<ul>
|
||||
<li>many blocked Read calls != many blocked OS threads</li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="slide">
|
||||
<h1>Go, synchronized</h1>
|
||||
|
||||
<h2>Use explicit messages to communicate and synchronize.</h2>
|
||||
|
||||
<pre>
|
||||
func computeAndSend(ch chan int, x, y, z int) {
|
||||
ch <- expensiveComputation(x, y, z)
|
||||
}
|
||||
|
||||
func main() {
|
||||
ch := make(chan int)
|
||||
go computeAndSend(ch, x, y, z)
|
||||
v2 := anotherExpensiveComputation(a, b, c)
|
||||
v1 := <-ch
|
||||
fmt.Println(v1, v2)
|
||||
}
|
||||
</pre>
|
||||
<h2>Notice communication of result in addition to synchronization.</h2>
|
||||
</div>
|
||||
|
||||
<div class="slide">
|
||||
<h1>Go, synchronized</h1>
|
||||
|
||||
<h2>RPC client</h2>
|
||||
|
||||
<pre>
|
||||
func (client *Client) Call(method string, args, reply interface{}) os.Error {
|
||||
// Send RPC message.
|
||||
call := client.Go(method, args, reply, nil)
|
||||
|
||||
// Read reply from Done channel.
|
||||
<-call.Done
|
||||
|
||||
return call.Error
|
||||
}
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<div class="slide">
|
||||
<h1>Go, synchronized</h1>
|
||||
|
||||
<h2>RPC client demux</h2>
|
||||
|
||||
<pre>
|
||||
func (client *Client) input() {
|
||||
for {
|
||||
resp := client.readResponse()
|
||||
client.mutex.Lock()
|
||||
c := client.pending[resp.Seq]
|
||||
client.pending[resp.Seq] = c, false
|
||||
client.mutex.Unlock()
|
||||
if resp.Error != "" {
|
||||
c.Error = os.ErrorString(resp.error)
|
||||
}
|
||||
resp.Decode(c.Reply)
|
||||
c.Done <- c
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<div class="slide">
|
||||
<h1>Go, synchronized</h1>
|
||||
|
||||
<h2>RPC client demux</h2>
|
||||
|
||||
<pre>
|
||||
func (client *Client) input() {
|
||||
for {
|
||||
<font style="color: black;">resp := client.readResponse()</font>
|
||||
client.mutex.Lock()
|
||||
c := client.pending[resp.Seq]
|
||||
client.pending[resp.Seq] = c, false
|
||||
client.mutex.Unlock()
|
||||
if resp.Error != "" {
|
||||
c.Error = os.ErrorString(resp.error)
|
||||
}
|
||||
resp.Decode(c.Reply)
|
||||
c.Done <- c
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
<h2>Read response from network.</h2
|
||||
</div>
|
||||
|
||||
<div class="slide">
|
||||
<h1>Go, synchronized</h1>
|
||||
|
||||
<h2>RPC client demux</h2>
|
||||
|
||||
<pre>
|
||||
func (client *Client) input() {
|
||||
for {
|
||||
resp := client.readResponse()
|
||||
<font style="color: black;">client.mutex.Lock()
|
||||
c := client.pending[resp.Seq]
|
||||
client.pending[resp.Seq] = c, false
|
||||
client.mutex.Unlock()</font>
|
||||
if resp.Error != "" {
|
||||
c.Error = os.ErrorString(resp.error)
|
||||
}
|
||||
resp.Decode(c.Reply)
|
||||
c.Done <- c
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
<h2>Look up request by sequence number.</h2
|
||||
</div>
|
||||
|
||||
<div class="slide">
|
||||
<h1>Go, synchronized</h1>
|
||||
|
||||
<h2>RPC client demux</h2>
|
||||
|
||||
<pre>
|
||||
func (client *Client) input() {
|
||||
for {
|
||||
resp := client.readResponse()
|
||||
client.mutex.Lock()
|
||||
c := client.pending[resp.Seq]
|
||||
client.pending[resp.Seq] = c, false
|
||||
client.mutex.Unlock()
|
||||
<font style="color: black;">if resp.Error != "" {
|
||||
c.Error = os.ErrorString(resp.error)
|
||||
}
|
||||
resp.Decode(c.Reply)</font>
|
||||
c.Done <- c
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
<h2>Decode response fields from payload.</h2
|
||||
</div>
|
||||
|
||||
<div class="slide">
|
||||
<h1>Go, synchronized</h1>
|
||||
|
||||
<h2>RPC client demux</h2>
|
||||
|
||||
<pre>
|
||||
func (client *Client) input() {
|
||||
for {
|
||||
resp := client.readResponse()
|
||||
client.mutex.Lock()
|
||||
c := client.pending[resp.Seq]
|
||||
client.pending[resp.Seq] = c, false
|
||||
client.mutex.Unlock()
|
||||
if resp.Error != "" {
|
||||
c.Error = os.ErrorString(resp.error)
|
||||
}
|
||||
resp.Decode(c.Reply)
|
||||
<font style="color: black;">c.Done <- c</font>
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
<h2>Tell client that it finished.</h2
|
||||
</div>
|
||||
|
||||
<div class="slide">
|
||||
<h1>Go, synchronized</h1>
|
||||
|
||||
<h2>RPC client demux</h2>
|
||||
|
||||
<pre>
|
||||
func (client *Client) input() {
|
||||
for {
|
||||
resp := client.readResponse()
|
||||
client.mutex.Lock()
|
||||
c := client.pending[resp.Seq]
|
||||
client.pending[resp.Seq] = c, false
|
||||
client.mutex.Unlock()
|
||||
if resp.Error != "" {
|
||||
c.Error = os.ErrorString(resp.error)
|
||||
}
|
||||
resp.Decode(c.Reply)
|
||||
c.Done <- c
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h2>Can create multiple Calls with same Done channel
|
||||
and distinguish which finished by inspecting value sent on channel.
|
||||
</h2>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="slide">
|
||||
<h1>Goroutine demo</h1>
|
||||
|
||||
<h2>Chain together 100,000 goroutines connected by 100,001 channels.</h2>
|
||||
|
||||
<h2>Send a value to one end of the chain.</h2>
|
||||
|
||||
<h2>Each passes it along, increments.</h2>
|
||||
|
||||
<h2>Receive value out the other end of the chain.</h2>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="slide">
|
||||
<h1>Go Status</h1>
|
||||
</div>
|
||||
|
||||
<div class="slide">
|
||||
<h1>Go Status</h1>
|
||||
|
||||
<h2>Open source:</h2>
|
||||
<ul>
|
||||
<li>released on November 10, 2009
|
||||
<li>regular releases (~ weekly)
|
||||
<li>all development done in public Mercurial repository
|
||||
<li>outside contributions welcome
|
||||
<li>two independent compiler implementations
|
||||
<li>XML, JSON, HTTP, TLS/SSL, native RPC, (network channels,) ...
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="slide">
|
||||
<h1>Go Status</h1>
|
||||
|
||||
<h2>Open source</h2>
|
||||
|
||||
<h2>Portable:</h2>
|
||||
<ul>
|
||||
<li>FreeBSD, Linux, OS X (x86, x86-64)
|
||||
<li>(in progress) Linux arm, Native Client x86, Windows x86.
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="slide">
|
||||
<h1>Go Status</h1>
|
||||
|
||||
<h2>Open source</h2>
|
||||
<h2>Portable</h2>
|
||||
|
||||
<h2>Still in progress, experimental. Yet to come:</h2>
|
||||
<ul>
|
||||
<li>production garbage collector
|
||||
<li>generics?
|
||||
<li>exceptions?
|
||||
<li>unions or sum types?
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="slide titlepage">
|
||||
<h1>Questions?</h1>
|
||||
<br><br>
|
||||
<center>
|
||||
<img src="../gordon/bumper640x360.png">
|
||||
</center>
|
||||
<br><br>
|
||||
<div style="color: #ffcc00;">
|
||||
<!-- <h3><i>rsc@google.com</i></h3> -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body></html>
|
||||
@@ -1,395 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<title>Go Tech Talk</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="font-size-adjustment" content="-1" />
|
||||
<link rel="stylesheet" href="slidy.css"
|
||||
type="text/css" media="screen, projection, print" />
|
||||
<script src="slidy.js" type="text/javascript">
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<!-- this defines the slide background -->
|
||||
|
||||
<div class="background">
|
||||
|
||||
<div class="header">
|
||||
<!-- sized and colored via CSS -->
|
||||
</div>
|
||||
|
||||
<div class="footer"></div>
|
||||
</div>
|
||||
|
||||
<div class="slide titlepage">
|
||||
<br/>
|
||||
<br/>
|
||||
<img src="../go-logo-white.png" width="588px" height="217px">
|
||||
<br/>
|
||||
<h1 style="padding-right: 0pt; margin-right: 0pt; color: #0066cc; font-size: 250%; border-bottom: 0px;">The Go Programming Language</h1>
|
||||
<div style="color: #ffcc00;">
|
||||
<br/>
|
||||
<h3>Sydney University<br/><br/>March 23, 2010</h3>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="slide">
|
||||
<h1>Go</h1>
|
||||
|
||||
<h2>New</h2>
|
||||
<h2>Experimental</h2>
|
||||
<h2>Concurrent</h2>
|
||||
<h2>Garbage Collected</h2>
|
||||
<h2>Systems Language</h2>
|
||||
</div>
|
||||
|
||||
<div class="slide">
|
||||
<h1>Hello, world</h1>
|
||||
<pre>
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
fmt.Printf("Hello, 世界\n")
|
||||
}
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<div class="slide">
|
||||
<h1>Hello, world 2.0</h1>
|
||||
|
||||
<h2>Serving <a href="http://localhost:8080/world">http://localhost:8080/world</a></h2>
|
||||
<pre>
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"http"
|
||||
)
|
||||
|
||||
func handler(c *http.Conn, r *http.Request) {
|
||||
fmt.Fprintf(c, "Hello, %s.", r.URL.Path[1:])
|
||||
}
|
||||
|
||||
func main() {
|
||||
http.ListenAndServe(":8080",
|
||||
http.HandlerFunc(handler))
|
||||
}
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<div class="slide">
|
||||
<h1>New</h1>
|
||||
|
||||
<h2>It's about two years old:</h2>
|
||||
<ul>
|
||||
<li>Design started in late 2007</li>
|
||||
<li>Implementation starting to work mid-2008</li>
|
||||
<li>Released as an open source project in November 2009</li>
|
||||
<li>Development continues with an active community</li>
|
||||
</ul>
|
||||
|
||||
<h2>Why invent a new language? Older languages weren't designed for concurrency, but modern software needs it:</h2>
|
||||
<ul>
|
||||
<li>Large scale, networked computing, such as Google web search</li>
|
||||
<li>Multi-core hardware</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="slide">
|
||||
<h1>New</h1>
|
||||
|
||||
<h2>Older languages are also frustrating on a day-to-day basis</h2>
|
||||
<h2>Statically-typed languages (C, C++, Java) have issues:</h2>
|
||||
<ul>
|
||||
<li>Edit-Compile-Run cycle takes far too long</li>
|
||||
<li>Type hierarchy can hurt as much as it helps</li>
|
||||
</ul>
|
||||
<div style="text-align:center">
|
||||
<img src="java-typing.png" width="800px" height="90px"><br>
|
||||
</div>
|
||||
|
||||
<h2>Dynamic languages (Python, JavaScript) fix some issues but introduce others:</h2>
|
||||
<ul>
|
||||
<li>No compilation means slow code</li>
|
||||
<li>Runtime errors that should be caught statically</li>
|
||||
</ul>
|
||||
|
||||
<h2>Go has the lighter feel of a scripting language but is compiled</h2>
|
||||
</div>
|
||||
|
||||
<div class="slide">
|
||||
<h1>New</h1>
|
||||
|
||||
<h2>Large C++ programs (e.g. Firefox, OpenOffice, Chromium) have enormous build times:</h2>
|
||||
<ul>
|
||||
<li>XKCD's #1 Programmer Excuse for Legitimately Slacking Off: "<a href="http://xkcd.com/303/">My Code's Compiling</a>"</li>
|
||||
</ul>
|
||||
|
||||
<h2>On a Mac (OS X 10.5.8, gcc 4.0.1):</h2>
|
||||
<ul>
|
||||
<li>C: <code>#include <stdio.h></code> reads 360 lines from 9 files</li>
|
||||
<li>C++: <code>#include <iostream></code> reads 25,326 lines from 131 files</li>
|
||||
<li>Objective-C: <code>#include <Carbon/Carbon.h></code> reads 124,730 lines from 689 files</li>
|
||||
<li>We haven't done any real work yet!</li>
|
||||
</ul>
|
||||
|
||||
<h2>In Go: <code>import "fmt"</code> reads <i>one</i> file: 184 lines summarizing 7 packages</h2>
|
||||
</div>
|
||||
|
||||
<div class="slide">
|
||||
<h1>New</h1>
|
||||
|
||||
<h2>Compilation demo</h2>
|
||||
</div>
|
||||
|
||||
<div class="slide">
|
||||
<h1>Experimental</h1>
|
||||
|
||||
<h2>Go is still unproven</h2>
|
||||
<h2>Language is still evolving</h2>
|
||||
<h2>Package library is incomplete</h2>
|
||||
<h2>Concurrent garbage collection is an active research problem</h2>
|
||||
<h2>Reviving forgotten concepts:</h2>
|
||||
<ul>
|
||||
<li>Go's concurrency is strongly influenced by <i>Communicating Sequential Processes</i> (Hoare, 1978)</li>
|
||||
<li>Go has types and interfaces, but no inheritance. It is arguably more object-oriented than previously mentioned languages, being closer to the original Smalltalk meaning (1970s)</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="slide">
|
||||
<h1>Concurrent</h1>
|
||||
|
||||
<h2>Unix philosophy: write <i>programs</i> that do one thing and do it well</h2>
|
||||
<h2>Connect them with <i>pipes</i>:</h2>
|
||||
<ul>
|
||||
<li>How many lines of test code are there in the Go standard library?</li>
|
||||
<li><code>find ~/go/src/pkg | grep _test.go$ | xargs wc -l</code></li>
|
||||
</ul>
|
||||
|
||||
<h2>Unlike other languages, Go makes it easy to:</h2>
|
||||
<ul>
|
||||
<li>Launch <i>goroutines</i></li>
|
||||
<li>Connect them with <i>channels</i></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="slide">
|
||||
<h1>Concurrent</h1>
|
||||
|
||||
<h2>Start a new flow of control with the <code>go</code> keyword</h2>
|
||||
<h2>Parallel computation is easy:</h2>
|
||||
<pre>
|
||||
func main() {
|
||||
go expensiveComputation(x, y, z)
|
||||
anotherExpensiveComputation(a, b, c)
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h2>Roughly speaking, a goroutine is like a thread, but lighter weight:</h2>
|
||||
<ul>
|
||||
<li>Goroutines have segmented stacks, and typically smaller stacks</li>
|
||||
<li>This requires compiler support. Goroutines can't just be a C++ library on top of a thread library</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="slide">
|
||||
<h1>Concurrent</h1>
|
||||
|
||||
<h2>Consider web servers ("the C10k problem"):</h2>
|
||||
<ul>
|
||||
<li>"Thread per connection" approach is conceptually neat, but doesn't scale well in practice</li>
|
||||
<li>What does scale well (event-driven callbacks, asynchronous APIs) are harder to understand, maintain, and debug</li>
|
||||
<li>We think "goroutine per connection" can scale well, and is conceptually neat</li>
|
||||
</ul>
|
||||
<pre>
|
||||
for {
|
||||
rw := socket.Accept()
|
||||
conn := newConn(rw, handler)
|
||||
go conn.serve()
|
||||
}
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<div class="slide">
|
||||
<h1>Concurrent</h1>
|
||||
|
||||
<h2>Let's look again at our simple parallel computation:</h2>
|
||||
<pre>
|
||||
func main() {
|
||||
go expensiveComputation(x, y, z)
|
||||
anotherExpensiveComputation(a, b, c)
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h2>This story is incomplete:</h2>
|
||||
<ul>
|
||||
<li>How do we know when the two computations are done?</li>
|
||||
<li>What are their values?</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="slide">
|
||||
<h1>Concurrent</h1>
|
||||
|
||||
<h2>Goroutines communicate with other goroutines via channels</h2>
|
||||
<pre>
|
||||
func computeAndSend(ch chan int, x, y, z int) {
|
||||
ch <- expensiveComputation(x, y, z)
|
||||
}
|
||||
|
||||
func main() {
|
||||
ch := make(chan int)
|
||||
go computeAndSend(ch, x, y, z)
|
||||
v2 := anotherExpensiveComputation(a, b, c)
|
||||
v1 := <-ch
|
||||
fmt.Println(v1, v2)
|
||||
}
|
||||
</pre>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="slide">
|
||||
<h1>Concurrent</h1>
|
||||
|
||||
<h2>In traditional concurrent programs, you <i>communicate by sharing memory</i>. In Go, you <i>share memory by communicating</i>:</h2>
|
||||
<ul>
|
||||
<li>Communication (the <code><-</code> operator) is sharing and synchronization</li>
|
||||
</ul>
|
||||
|
||||
<h2>Threads and locks are concurrency primitives; CSP is a concurrency model:</h2>
|
||||
<ul>
|
||||
<li>Analogy: "Go To Statement Considered Harmful" (Dijsktra, 1968)</li>
|
||||
<li><code>goto</code> is a control flow primitive; structured programming (<code>if</code> statements, <code>for</code> loops, function calls) is a control flow model</li>
|
||||
</ul>
|
||||
|
||||
<h2>Learning CSP changes the way you think about concurrent programming:</h2>
|
||||
<ul>
|
||||
<li>Every language has its grain. If your Go program uses mutexes, you're probably working against the grain</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="slide">
|
||||
<h1>Garbage Collected</h1>
|
||||
|
||||
<h2>Automatic memory management makes writing (and maintaining) programs easier</h2>
|
||||
<h2>Especially in a concurrent world:</h2>
|
||||
<ul>
|
||||
<li>Who "owns" a shared piece of memory, and is responsible for destroying it?</li>
|
||||
</ul>
|
||||
|
||||
<h2>Large C++ programs usually end up with semi-automatic memory management anyway, via "smart pointers"</h2>
|
||||
<h2>Mixing the two models can be problematic:</h2>
|
||||
<ul>
|
||||
<li>Browsers can leak memory easily; DOM elements are C++ objects, but JavaScript is garbage collected</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="slide">
|
||||
<h1>Garbage Collected</h1>
|
||||
|
||||
<h2>Go is also a safer language:</h2>
|
||||
<ul>
|
||||
<li>Pointers but no pointer arithmetic</li>
|
||||
<li>No dangling pointers</li>
|
||||
<li>Variables are zero-initialized</li>
|
||||
<li>Array access is bounds-checked</li>
|
||||
</ul>
|
||||
|
||||
<h2>No buffer overflow exploits</h2>
|
||||
</div>
|
||||
|
||||
<div class="slide">
|
||||
<h1>Systems Language</h1>
|
||||
|
||||
<h2>This just means you could write decently large programs in Go:</h2>
|
||||
<ul>
|
||||
<li>Web servers</li>
|
||||
<li>Web browsers</li>
|
||||
<li>Web crawlers</li>
|
||||
<li>Search indexers</li>
|
||||
<li>Databases</li>
|
||||
<li>Word processors</li>
|
||||
<li>Integrated Development Environments (IDEs)</li>
|
||||
<li>Operating systems</li>
|
||||
<li>...</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="slide">
|
||||
<h1>Systems Language</h1>
|
||||
|
||||
<h2>Garbage collection has a reputation for being "slower"</h2>
|
||||
<h2>We're expecting Go to be slightly slower than optimized C, but faster than Java, depending on the task. Nonetheless:</h2>
|
||||
<ul>
|
||||
<li>Fast and buggy is worse than almost-as-fast and correct</li>
|
||||
<li>It is easier to optimize a correct program than to correct an optimized program</li>
|
||||
<li>Fundamentally, it's simply a trade-off we're willing to make</li>
|
||||
</ul>
|
||||
|
||||
<h2>Memory layout can drastically affect performance. These two designs are equivalent in Go, but significantly different in Java:</h2>
|
||||
<pre>
|
||||
type Point struct { X, Y int }
|
||||
type Rect struct { P0, P1 Point }
|
||||
|
||||
// or ...
|
||||
|
||||
type Rect struct { X0, Y0, X1, Y1 int }
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<div class="slide">
|
||||
<h1>Systems Language</h1>
|
||||
|
||||
<h2>Quote from http://loadcode.blogspot.com/2009/12/go-vs-java.html</h2>
|
||||
|
||||
<h2>
|
||||
"[Git] is known to be very fast. It is written in C. A Java version
|
||||
JGit was made. It was considerably slower. Handling of memory and lack
|
||||
of unsigned types was some of the important reasons.
|
||||
</h2>
|
||||
|
||||
<h2>Shawn O. Pearce wrote on the git mailinglist:</h2>
|
||||
<ul><li>"JGit struggles with not
|
||||
having an efficient way to represent a SHA-1. C can just say "unsigned
|
||||
char[20]" and have it inline into the container's memory allocation. A
|
||||
byte[20] in Java will cost an *additional* 16 bytes of memory, and be
|
||||
slower to access because the bytes themselves are in a different area
|
||||
of memory from the container object. We try to work around it by
|
||||
converting from a byte[20] to 5 ints, but that costs us machine
|
||||
instructions"
|
||||
</li></ul>
|
||||
|
||||
<h2>
|
||||
Like C, Go does allow unsigned types and defining data structures
|
||||
containing other data structures as continuous blocks of memory."
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div class="slide">
|
||||
<h1>Go</h1>
|
||||
|
||||
<h2>New</h2>
|
||||
<h2>Experimental</h2>
|
||||
<h2>Concurrent</h2>
|
||||
<h2>Garbage Collected</h2>
|
||||
<h2>Systems Language</h2>
|
||||
|
||||
<h2>And more:</h2>
|
||||
<ul>
|
||||
<li>I haven't talked about the type system, interfaces, slices, closures, selects, ...</li>
|
||||
<li>Documentation, mailing list, source code all online</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="slide titlepage">
|
||||
<h1>Questions?</h1>
|
||||
<br><br>
|
||||
<center>
|
||||
<img src="../gordon/bumper640x360.png" width="640px" height="360px">
|
||||
</center>
|
||||
</div>
|
||||
|
||||
</body></html>
|
||||
Binary file not shown.
@@ -1,168 +0,0 @@
|
||||
// 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 (
|
||||
"container/heap"
|
||||
"flag"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"time"
|
||||
)
|
||||
|
||||
const nRequester = 100
|
||||
const nWorker = 10
|
||||
|
||||
var roundRobin = flag.Bool("r", false, "use round-robin scheduling")
|
||||
|
||||
// Simulation of some work: just sleep for a while and report how long.
|
||||
func op() int {
|
||||
n := rand.Int63n(1e9)
|
||||
time.Sleep(nWorker * n)
|
||||
return int(n)
|
||||
}
|
||||
|
||||
type Request struct {
|
||||
fn func() int
|
||||
c chan int
|
||||
}
|
||||
|
||||
func requester(work chan Request) {
|
||||
c := make(chan int)
|
||||
for {
|
||||
time.Sleep(rand.Int63n(nWorker * 2e9))
|
||||
work <- Request{op, c}
|
||||
<-c
|
||||
}
|
||||
}
|
||||
|
||||
type Worker struct {
|
||||
i int
|
||||
requests chan Request
|
||||
pending int
|
||||
}
|
||||
|
||||
func (w *Worker) work(done chan *Worker) {
|
||||
for {
|
||||
req := <-w.requests
|
||||
req.c <- req.fn()
|
||||
done <- w
|
||||
}
|
||||
}
|
||||
|
||||
type Pool []*Worker
|
||||
|
||||
func (p Pool) Len() int { return len(p) }
|
||||
|
||||
func (p Pool) Less(i, j int) bool {
|
||||
return p[i].pending < p[j].pending
|
||||
}
|
||||
|
||||
func (p *Pool) Swap(i, j int) {
|
||||
a := *p
|
||||
a[i], a[j] = a[j], a[i]
|
||||
a[i].i = i
|
||||
a[j].i = j
|
||||
}
|
||||
|
||||
func (p *Pool) Push(x interface{}) {
|
||||
a := *p
|
||||
n := len(a)
|
||||
a = a[0 : n+1]
|
||||
w := x.(*Worker)
|
||||
a[n] = w
|
||||
w.i = n
|
||||
*p = a
|
||||
}
|
||||
|
||||
func (p *Pool) Pop() interface{} {
|
||||
a := *p
|
||||
*p = a[0 : len(a)-1]
|
||||
w := a[len(a)-1]
|
||||
w.i = -1 // for safety
|
||||
return w
|
||||
}
|
||||
|
||||
type Balancer struct {
|
||||
pool Pool
|
||||
done chan *Worker
|
||||
i int
|
||||
}
|
||||
|
||||
func NewBalancer() *Balancer {
|
||||
done := make(chan *Worker, nWorker)
|
||||
b := &Balancer{make(Pool, 0, nWorker), done, 0}
|
||||
for i := 0; i < nWorker; i++ {
|
||||
w := &Worker{requests: make(chan Request, nRequester)}
|
||||
heap.Push(&b.pool, w)
|
||||
go w.work(b.done)
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func (b *Balancer) balance(work chan Request) {
|
||||
for {
|
||||
select {
|
||||
case req := <-work:
|
||||
b.dispatch(req)
|
||||
case w := <-b.done:
|
||||
b.completed(w)
|
||||
}
|
||||
b.print()
|
||||
}
|
||||
}
|
||||
|
||||
func (b *Balancer) print() {
|
||||
sum := 0
|
||||
sumsq := 0
|
||||
for _, w := range b.pool {
|
||||
fmt.Printf("%d ", w.pending)
|
||||
sum += w.pending
|
||||
sumsq += w.pending * w.pending
|
||||
}
|
||||
avg := float64(sum) / float64(len(b.pool))
|
||||
variance := float64(sumsq)/float64(len(b.pool)) - avg*avg
|
||||
fmt.Printf(" %.2f %.2f\n", avg, variance)
|
||||
}
|
||||
|
||||
func (b *Balancer) dispatch(req Request) {
|
||||
if *roundRobin {
|
||||
w := b.pool[b.i]
|
||||
w.requests <- req
|
||||
w.pending++
|
||||
b.i++
|
||||
if b.i >= len(b.pool) {
|
||||
b.i = 0
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
w := heap.Pop(&b.pool).(*Worker)
|
||||
w.requests <- req
|
||||
w.pending++
|
||||
// fmt.Printf("started %p; now %d\n", w, w.pending)
|
||||
heap.Push(&b.pool, w)
|
||||
}
|
||||
|
||||
func (b *Balancer) completed(w *Worker) {
|
||||
if *roundRobin {
|
||||
w.pending--
|
||||
return
|
||||
}
|
||||
|
||||
w.pending--
|
||||
// fmt.Printf("finished %p; now %d\n", w, w.pending)
|
||||
heap.Remove(&b.pool, w.i)
|
||||
heap.Push(&b.pool, w)
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
work := make(chan Request)
|
||||
for i := 0; i < nRequester; i++ {
|
||||
go requester(work)
|
||||
}
|
||||
NewBalancer().balance(work)
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
// 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.
|
||||
|
||||
// This code differs from the slides in that it handles errors.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"compress/gzip"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
)
|
||||
|
||||
func EncryptAndGzip(dstfile, srcfile string, key, iv []byte) error {
|
||||
r, err := os.Open(srcfile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var w io.Writer
|
||||
w, err = os.Create(dstfile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
w = cipher.StreamWriter{S: cipher.NewOFB(c, iv), W: w}
|
||||
w2, err := gzip.NewWriter(w)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer w2.Close()
|
||||
_, err = io.Copy(w2, r)
|
||||
return err
|
||||
}
|
||||
|
||||
func DecryptAndGunzip(dstfile, srcfile string, key, iv []byte) error {
|
||||
f, err := os.Open(srcfile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
c, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
r := cipher.StreamReader{S: cipher.NewOFB(c, iv), R: f}
|
||||
r2, err := gzip.NewReader(r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
w, err := os.Create(dstfile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer w.Close()
|
||||
_, err = io.Copy(w, r2)
|
||||
return err
|
||||
}
|
||||
|
||||
func main() {
|
||||
err := EncryptAndGzip(
|
||||
"/tmp/passwd.gz",
|
||||
"/etc/passwd",
|
||||
make([]byte, 16),
|
||||
make([]byte, 16),
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
err = DecryptAndGunzip(
|
||||
"/dev/stdout",
|
||||
"/tmp/passwd.gz",
|
||||
make([]byte, 16),
|
||||
make([]byte, 16),
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
// 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.
|
||||
|
||||
// This code differs from the slides in that it handles errors.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"compress/gzip"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
)
|
||||
|
||||
func EncryptAndGzip(dstfile, srcfile string, key, iv []byte) error {
|
||||
r, err := os.Open(srcfile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var w io.WriteCloser
|
||||
w, err = os.Create(dstfile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer w.Close()
|
||||
w, err = gzip.NewWriter(w)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer w.Close()
|
||||
c, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = io.Copy(cipher.StreamWriter{S: cipher.NewOFB(c, iv), W: w}, r)
|
||||
return err
|
||||
}
|
||||
|
||||
func main() {
|
||||
err := EncryptAndGzip(
|
||||
"/tmp/passwd.gz",
|
||||
"/etc/passwd",
|
||||
make([]byte, 16),
|
||||
make([]byte, 16),
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
@@ -1,227 +0,0 @@
|
||||
// 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 (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Generic expression parser/evaluator
|
||||
|
||||
type Value interface {
|
||||
String() string
|
||||
BinaryOp(op string, y Value) Value
|
||||
}
|
||||
|
||||
type Parser struct {
|
||||
precTab map[string]int
|
||||
newVal func(string) Value
|
||||
src string
|
||||
pos int
|
||||
tok string
|
||||
}
|
||||
|
||||
const alphanum = "_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
||||
|
||||
func (p *Parser) stop(c uint8) bool {
|
||||
switch {
|
||||
case p.pos >= len(p.src):
|
||||
return true
|
||||
case c == '"':
|
||||
if p.src[p.pos] == '"' {
|
||||
p.pos++
|
||||
return true
|
||||
}
|
||||
return false
|
||||
case strings.IndexRune(alphanum, int(c)) >= 0:
|
||||
return strings.IndexRune(alphanum, int(p.src[p.pos])) < 0
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (p *Parser) next() {
|
||||
// skip blanks
|
||||
for ; p.pos < len(p.src) && p.src[p.pos] <= ' '; p.pos++ {
|
||||
}
|
||||
if p.pos >= len(p.src) {
|
||||
p.tok = ""
|
||||
return
|
||||
}
|
||||
start := p.pos
|
||||
c := p.src[p.pos]
|
||||
for p.pos < len(p.src) {
|
||||
p.pos++
|
||||
if p.stop(c) {
|
||||
break
|
||||
}
|
||||
}
|
||||
p.tok = p.src[start:p.pos]
|
||||
}
|
||||
|
||||
func (p *Parser) binaryExpr(prec1 int) Value {
|
||||
x := p.newVal(p.tok)
|
||||
p.next()
|
||||
for prec := p.precTab[p.tok]; prec >= prec1; prec-- {
|
||||
for p.precTab[p.tok] == prec {
|
||||
op := p.tok
|
||||
p.next()
|
||||
y := p.binaryExpr(prec + 1)
|
||||
x = x.BinaryOp(op, y)
|
||||
}
|
||||
}
|
||||
return x
|
||||
}
|
||||
|
||||
func Eval(precTab map[string]int, newVal func(string) Value, src string) Value {
|
||||
var p Parser
|
||||
p.precTab = precTab
|
||||
p.newVal = newVal
|
||||
p.src = src
|
||||
p.next()
|
||||
return p.binaryExpr(1)
|
||||
}
|
||||
|
||||
// Command-line expression evaluator
|
||||
|
||||
func main() {
|
||||
r := bufio.NewReader(os.Stdin)
|
||||
for {
|
||||
fmt.Printf("> ")
|
||||
line, err := r.ReadString('\n')
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
fmt.Printf("%s\n", Eval(precTab, trace(newVal), line))
|
||||
}
|
||||
}
|
||||
|
||||
// Custom grammar and values
|
||||
|
||||
var precTab = map[string]int{
|
||||
"&&": 1,
|
||||
"||": 2,
|
||||
"==": 3,
|
||||
"!=": 3,
|
||||
"<": 3,
|
||||
"<=": 3,
|
||||
">": 3,
|
||||
">=": 3,
|
||||
"+": 4,
|
||||
"-": 4,
|
||||
"*": 5,
|
||||
"/": 5,
|
||||
"%": 5,
|
||||
}
|
||||
|
||||
func newVal(lit string) Value {
|
||||
x, err := strconv.Atoi(lit)
|
||||
if err == nil {
|
||||
return Int(x)
|
||||
}
|
||||
b, err := strconv.ParseBool(lit)
|
||||
if err == nil {
|
||||
return Bool(b)
|
||||
}
|
||||
return Error(fmt.Sprintf("illegal literal '%s'", lit))
|
||||
}
|
||||
|
||||
type Error string
|
||||
|
||||
func (e Error) String() string { return string(e) }
|
||||
func (e Error) BinaryOp(op string, y Value) Value { return e }
|
||||
|
||||
type Int int
|
||||
|
||||
func (x Int) String() string { return strconv.Itoa(int(x)) }
|
||||
func (x Int) BinaryOp(op string, y Value) Value {
|
||||
switch y := y.(type) {
|
||||
case Error:
|
||||
return y
|
||||
case Int:
|
||||
switch op {
|
||||
case "+":
|
||||
return x + y
|
||||
case "-":
|
||||
return x - y
|
||||
case "*":
|
||||
return x * y
|
||||
case "/":
|
||||
return x / y
|
||||
case "%":
|
||||
return x % y
|
||||
case "==":
|
||||
return Bool(x == y)
|
||||
case "!=":
|
||||
return Bool(x != y)
|
||||
case "<":
|
||||
return Bool(x < y)
|
||||
case "<=":
|
||||
return Bool(x <= y)
|
||||
case ">":
|
||||
return Bool(x > y)
|
||||
case ">=":
|
||||
return Bool(x >= y)
|
||||
}
|
||||
}
|
||||
return Error(fmt.Sprintf("illegal operation: '%v %s %v'", x, op, y))
|
||||
}
|
||||
|
||||
type Bool bool
|
||||
|
||||
func (x Bool) String() string { return strconv.FormatBool(bool(x)) }
|
||||
func (x Bool) BinaryOp(op string, y Value) Value {
|
||||
switch y := y.(type) {
|
||||
case Error:
|
||||
return y
|
||||
case Bool:
|
||||
switch op {
|
||||
case "&&":
|
||||
return Bool(x && y)
|
||||
case "||":
|
||||
return Bool(x || y)
|
||||
case "==":
|
||||
return Bool(x == y)
|
||||
case "!=":
|
||||
return Bool(x != y)
|
||||
}
|
||||
}
|
||||
return Error(fmt.Sprintf("illegal operation: '%v %s %v'", x, op, y))
|
||||
}
|
||||
|
||||
func trace(newVal func(string) Value) func(string) Value {
|
||||
return func(s string) Value {
|
||||
v := newVal(s)
|
||||
fmt.Printf("\tnewVal(%q) = %s\n", s, fmtv(v))
|
||||
return &traceValue{v}
|
||||
}
|
||||
}
|
||||
|
||||
type traceValue struct {
|
||||
Value
|
||||
}
|
||||
|
||||
func (x *traceValue) BinaryOp(op string, y Value) Value {
|
||||
z := x.Value.BinaryOp(op, y.(*traceValue).Value)
|
||||
fmt.Printf("\t%s.BinaryOp(%q, %s) = %s\n", fmtv(x.Value), op, fmtv(y.(*traceValue).Value), fmtv(z))
|
||||
return &traceValue{z}
|
||||
}
|
||||
|
||||
func (x *traceValue) String() string {
|
||||
s := x.Value.String()
|
||||
fmt.Printf("\t%s.String() = %#v\n", fmtv(x.Value), s)
|
||||
return s
|
||||
}
|
||||
|
||||
func fmtv(v Value) string {
|
||||
t := fmt.Sprintf("%T", v)
|
||||
if i := strings.LastIndex(t, "."); i >= 0 { // strip package
|
||||
t = t[i+1:]
|
||||
}
|
||||
return fmt.Sprintf("%s(%#v)", t, v)
|
||||
}
|
||||
@@ -1,259 +0,0 @@
|
||||
// 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 (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Generic expression parser/evaluator
|
||||
|
||||
type Value interface {
|
||||
String() string
|
||||
BinaryOp(op string, y Value) Value
|
||||
}
|
||||
|
||||
type Parser struct {
|
||||
precTab map[string]int
|
||||
newVal func(string) Value
|
||||
src string
|
||||
pos int
|
||||
tok string
|
||||
}
|
||||
|
||||
const alphanum = "_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
||||
|
||||
func (p *Parser) stop(c uint8) bool {
|
||||
switch {
|
||||
case p.pos >= len(p.src):
|
||||
return true
|
||||
case c == '"':
|
||||
if p.src[p.pos] == '"' {
|
||||
p.pos++
|
||||
return true
|
||||
}
|
||||
return false
|
||||
case strings.IndexRune(alphanum, int(c)) >= 0:
|
||||
return strings.IndexRune(alphanum, int(p.src[p.pos])) < 0
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (p *Parser) next() {
|
||||
// skip blanks
|
||||
for ; p.pos < len(p.src) && p.src[p.pos] <= ' '; p.pos++ {
|
||||
}
|
||||
if p.pos >= len(p.src) {
|
||||
p.tok = ""
|
||||
return
|
||||
}
|
||||
start := p.pos
|
||||
c := p.src[p.pos]
|
||||
for p.pos < len(p.src) {
|
||||
p.pos++
|
||||
if p.stop(c) {
|
||||
break
|
||||
}
|
||||
}
|
||||
p.tok = p.src[start:p.pos]
|
||||
}
|
||||
|
||||
func (p *Parser) binaryExpr(prec1 int) Value {
|
||||
x := p.newVal(p.tok)
|
||||
p.next()
|
||||
for prec := p.precTab[p.tok]; prec >= prec1; prec-- {
|
||||
for p.precTab[p.tok] == prec {
|
||||
op := p.tok
|
||||
p.next()
|
||||
y := p.binaryExpr(prec + 1)
|
||||
x = x.BinaryOp(op, y)
|
||||
}
|
||||
}
|
||||
return x
|
||||
}
|
||||
|
||||
func Eval(precTab map[string]int, newVal func(string) Value, src string) Value {
|
||||
var p Parser
|
||||
p.precTab = precTab
|
||||
p.newVal = newVal
|
||||
p.src = src
|
||||
p.next()
|
||||
return p.binaryExpr(1)
|
||||
}
|
||||
|
||||
// Command-line expression evaluator
|
||||
|
||||
func main() {
|
||||
r := bufio.NewReader(os.Stdin)
|
||||
for {
|
||||
fmt.Printf("> ")
|
||||
line, err := r.ReadString('\n')
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
fmt.Printf("%s\n", Eval(precTab, trace(newVal), line))
|
||||
}
|
||||
}
|
||||
|
||||
// Custom grammar and values
|
||||
|
||||
var precTab = map[string]int{
|
||||
"&&": 1,
|
||||
"||": 2,
|
||||
"==": 3,
|
||||
"!=": 3,
|
||||
"<": 3,
|
||||
"<=": 3,
|
||||
">": 3,
|
||||
">=": 3,
|
||||
"+": 4,
|
||||
"-": 4,
|
||||
"*": 5,
|
||||
"/": 5,
|
||||
"%": 5,
|
||||
}
|
||||
|
||||
func newVal(lit string) Value {
|
||||
x, err := strconv.Atoi(lit)
|
||||
if err == nil {
|
||||
return Int(x)
|
||||
}
|
||||
b, err := strconv.ParseBool(lit)
|
||||
if err == nil {
|
||||
return Bool(b)
|
||||
}
|
||||
s, err := strconv.Unquote(lit)
|
||||
if err == nil {
|
||||
return String(s)
|
||||
}
|
||||
return Error(fmt.Sprintf("illegal literal '%s'", lit))
|
||||
}
|
||||
|
||||
type Error string
|
||||
|
||||
func (e Error) String() string { return string(e) }
|
||||
func (e Error) BinaryOp(op string, y Value) Value { return e }
|
||||
|
||||
type Int int
|
||||
|
||||
func (x Int) String() string { return strconv.Itoa(int(x)) }
|
||||
func (x Int) BinaryOp(op string, y Value) Value {
|
||||
switch y := y.(type) {
|
||||
case Error:
|
||||
return y
|
||||
case String:
|
||||
switch op {
|
||||
case "*":
|
||||
return String(strings.Repeat(string(y), int(x)))
|
||||
}
|
||||
case Int:
|
||||
switch op {
|
||||
case "+":
|
||||
return x + y
|
||||
case "-":
|
||||
return x - y
|
||||
case "*":
|
||||
return x * y
|
||||
case "/":
|
||||
return x / y
|
||||
case "%":
|
||||
return x % y
|
||||
case "==":
|
||||
return Bool(x == y)
|
||||
case "!=":
|
||||
return Bool(x != y)
|
||||
case "<":
|
||||
return Bool(x < y)
|
||||
case "<=":
|
||||
return Bool(x <= y)
|
||||
case ">":
|
||||
return Bool(x > y)
|
||||
case ">=":
|
||||
return Bool(x >= y)
|
||||
}
|
||||
}
|
||||
return Error(fmt.Sprintf("illegal operation: '%v %s %v'", x, op, y))
|
||||
}
|
||||
|
||||
type Bool bool
|
||||
|
||||
func (x Bool) String() string { return strconv.FormatBool(bool(x)) }
|
||||
func (x Bool) BinaryOp(op string, y Value) Value {
|
||||
switch y := y.(type) {
|
||||
case Error:
|
||||
return y
|
||||
case Bool:
|
||||
switch op {
|
||||
case "&&":
|
||||
return Bool(x && y)
|
||||
case "||":
|
||||
return Bool(x || y)
|
||||
case "==":
|
||||
return Bool(x == y)
|
||||
case "!=":
|
||||
return Bool(x != y)
|
||||
}
|
||||
}
|
||||
return Error(fmt.Sprintf("illegal operation: '%v %s %v'", x, op, y))
|
||||
}
|
||||
|
||||
type String string
|
||||
|
||||
func (x String) String() string { return strconv.Quote(string(x)) }
|
||||
func (x String) BinaryOp(op string, y Value) Value {
|
||||
switch y := y.(type) {
|
||||
case Error:
|
||||
return y
|
||||
case Int:
|
||||
switch op {
|
||||
case "*":
|
||||
return String(strings.Repeat(string(x), int(y)))
|
||||
}
|
||||
case String:
|
||||
switch op {
|
||||
case "+":
|
||||
return x + y
|
||||
case "<":
|
||||
return Bool(x < y)
|
||||
}
|
||||
}
|
||||
return Error(fmt.Sprintf("illegal operation: '%v %s %v'", x, op, y))
|
||||
}
|
||||
|
||||
func trace(newVal func(string) Value) func(string) Value {
|
||||
return func(s string) Value {
|
||||
v := newVal(s)
|
||||
fmt.Printf("\tnewVal(%q) = %s\n", s, fmtv(v))
|
||||
return &traceValue{v}
|
||||
}
|
||||
}
|
||||
|
||||
type traceValue struct {
|
||||
Value
|
||||
}
|
||||
|
||||
func (x *traceValue) BinaryOp(op string, y Value) Value {
|
||||
z := x.Value.BinaryOp(op, y.(*traceValue).Value)
|
||||
fmt.Printf("\t%s.BinaryOp(%q, %s) = %s\n", fmtv(x.Value), op, fmtv(y.(*traceValue).Value), fmtv(z))
|
||||
return &traceValue{z}
|
||||
}
|
||||
|
||||
func (x *traceValue) String() string {
|
||||
s := x.Value.String()
|
||||
fmt.Printf("\t%s.String() = %#v\n", fmtv(x.Value), s)
|
||||
return s
|
||||
}
|
||||
|
||||
func fmtv(v Value) string {
|
||||
t := fmt.Sprintf("%T", v)
|
||||
if i := strings.LastIndex(t, "."); i >= 0 { // strip package
|
||||
t = t[i+1:]
|
||||
}
|
||||
return fmt.Sprintf("%s(%#v)", t, v)
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 19 KiB |
@@ -1,277 +0,0 @@
|
||||
/* http://www.w3.org/Talks/Tools/Slidy/slidy.css
|
||||
|
||||
Copyright (c) 2005 W3C (MIT, ERCIM, Keio), All Rights Reserved.
|
||||
W3C liability, trademark, document use and software licensing
|
||||
rules apply, see:
|
||||
|
||||
http://www.w3.org/Consortium/Legal/copyright-documents
|
||||
http://www.w3.org/Consortium/Legal/copyright-software
|
||||
*/
|
||||
body
|
||||
{
|
||||
margin: 0 0 0 0;
|
||||
padding: 0 0 0 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
color: black;
|
||||
background-color: white;
|
||||
font-family: "Lucida Sans", "Lucida Grande", Lucida, sans-serif;
|
||||
font-size: 14pt;
|
||||
}
|
||||
|
||||
.hidden { display: none; visibility: hidden }
|
||||
|
||||
div.toolbar {
|
||||
position: fixed; z-index: 200;
|
||||
top: auto; bottom: 0; left: 0; right: 0;
|
||||
height: 1.2em; text-align: right;
|
||||
padding-left: 1em;
|
||||
padding-right: 1em;
|
||||
font-size: 60%;
|
||||
color: red; background: rgb(240,240,240);
|
||||
}
|
||||
|
||||
div.background {
|
||||
display: none;
|
||||
}
|
||||
|
||||
div.handout {
|
||||
margin-left: 20px;
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
div.slide.titlepage {
|
||||
color: white;
|
||||
background: black;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
div.slide {
|
||||
z-index: 20;
|
||||
margin: 0 0 0 0;
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
padding-left: 20px;
|
||||
padding-right: 20px;
|
||||
border-width: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
line-height: 120%;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
/* this rule is hidden from IE 6 and below which don't support + selector */
|
||||
div.slide + div[class].slide { page-break-before: always;}
|
||||
|
||||
div.slide h1 {
|
||||
padding-left: 20px;
|
||||
padding-right: 20px;
|
||||
padding-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
margin-top: 0;
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
margin-bottom: 0.5em;
|
||||
border-bottom: 4px solid #36c;
|
||||
display: block;
|
||||
font-size: 160%;
|
||||
line-height: 1.2em;
|
||||
}
|
||||
|
||||
div.slide h2 {
|
||||
font-size:120%;
|
||||
line-height: 1.2em;
|
||||
}
|
||||
|
||||
div.toc {
|
||||
position: absolute;
|
||||
top: auto;
|
||||
bottom: 4em;
|
||||
left: 4em;
|
||||
right: auto;
|
||||
width: 60%;
|
||||
max-width: 30em;
|
||||
height: 30em;
|
||||
border: solid thin black;
|
||||
padding: 1em;
|
||||
background: rgb(240,240,240);
|
||||
color: black;
|
||||
z-index: 300;
|
||||
overflow: auto;
|
||||
display: block;
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
div.toc-heading {
|
||||
width: 100%;
|
||||
border-bottom: solid 1px rgb(180,180,180);
|
||||
margin-bottom: 1em;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
pre {
|
||||
font-size: 120%;
|
||||
font-weight: bold;
|
||||
line-height: 140%;
|
||||
padding-top: 0.2em;
|
||||
padding-bottom: 0.2em;
|
||||
padding-left: 1em;
|
||||
padding-right: 1em;
|
||||
/*
|
||||
border-style: solid;
|
||||
border-left-width: 1em;
|
||||
border-top-width: thin;
|
||||
border-right-width: thin;
|
||||
border-bottom-width: thin;
|
||||
border-color: #95ABD0;
|
||||
*/
|
||||
color: #0F398D;
|
||||
background-color: #fff8f8;
|
||||
}
|
||||
|
||||
@media print {
|
||||
div.slide {
|
||||
display: block;
|
||||
visibility: visible;
|
||||
position: relative;
|
||||
border-top-style: solid;
|
||||
border-top-width: thin;
|
||||
border-top-color: black;
|
||||
}
|
||||
div.slide pre { font-size: 60%; padding-left: 0.5em; }
|
||||
div.handout { display: block; visibility: visible; }
|
||||
}
|
||||
|
||||
blockquote { font-style: italic }
|
||||
|
||||
img { background-color: transparent }
|
||||
|
||||
p.copyright { font-size: smaller }
|
||||
|
||||
.center { text-align: center }
|
||||
.footnote { font-size: smaller; margin-left: 2em; }
|
||||
|
||||
a img { border-width: 0; border-style: none }
|
||||
|
||||
a:visited { color: navy }
|
||||
a:link { color: navy }
|
||||
a:hover { color: red; text-decoration: underline }
|
||||
a:active { color: red; text-decoration: underline }
|
||||
|
||||
a {text-decoration: none}
|
||||
.navbar a:link {color: white}
|
||||
.navbar a:visited {color: yellow}
|
||||
.navbar a:active {color: red}
|
||||
.navbar a:hover {color: red}
|
||||
|
||||
ul { list-style-type: square; }
|
||||
ul ul { list-style-type: disc; }
|
||||
ul ul ul { list-style-type: circle; }
|
||||
ul ul ul ul { list-style-type: disc; }
|
||||
li { margin-left: 2em; margin-top: 0.5em; }
|
||||
li li { font-size: 85%; font-style: italic }
|
||||
li li li { font-size: 85%; font-style: normal }
|
||||
|
||||
div dt
|
||||
{
|
||||
margin-left: 0;
|
||||
margin-top: 1em;
|
||||
margin-bottom: 0.5em;
|
||||
font-weight: bold;
|
||||
}
|
||||
div dd
|
||||
{
|
||||
margin-left: 2em;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
|
||||
p,pre,ul,ol,blockquote,h2,h3,h4,h5,h6,dl,table {
|
||||
margin-left: 1em;
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
||||
p.subhead { font-weight: bold; margin-top: 2em; }
|
||||
|
||||
p.smaller { font-size: smaller }
|
||||
|
||||
td,th { padding: 0.2em }
|
||||
|
||||
ul {
|
||||
margin: 0.5em 1.5em 0.5em 1.5em;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
ol {
|
||||
margin: 0.5em 1.5em 0.5em 1.5em;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
ul { list-style-type: square; }
|
||||
ul ul { list-style-type: disc; }
|
||||
ul ul ul { list-style-type: circle; }
|
||||
ul ul ul ul { list-style-type: disc; }
|
||||
|
||||
ul li {
|
||||
list-style: square;
|
||||
//margin: 0.1em 0em 0.6em 0;
|
||||
padding: 0 0 0 0;
|
||||
line-height: 140%;
|
||||
}
|
||||
|
||||
ol li {
|
||||
margin: 0.1em 0em 0.6em 1.5em;
|
||||
padding: 0 0 0 0px;
|
||||
line-height: 140%;
|
||||
list-style-type: decimal;
|
||||
}
|
||||
|
||||
li ul li {
|
||||
font-size: 85%;
|
||||
font-style: italic;
|
||||
list-style-type: disc;
|
||||
background: transparent;
|
||||
padding: 0 0 0 0;
|
||||
}
|
||||
li li ul li {
|
||||
font-size: 85%;
|
||||
font-style: normal;
|
||||
list-style-type: circle;
|
||||
background: transparent;
|
||||
padding: 0 0 0 0;
|
||||
}
|
||||
li li li ul li {
|
||||
list-style-type: disc;
|
||||
background: transparent;
|
||||
padding: 0 0 0 0;
|
||||
}
|
||||
|
||||
li ol li {
|
||||
list-style-type: decimal;
|
||||
}
|
||||
|
||||
|
||||
li li ol li {
|
||||
list-style-type: decimal;
|
||||
}
|
||||
|
||||
/*
|
||||
setting class="outline on ol or ul makes it behave as an
|
||||
ouline list where blocklevel content in li elements is
|
||||
hidden by default and can be expanded or collapsed with
|
||||
mouse click. Set class="expand" on li to override default
|
||||
*/
|
||||
|
||||
ol.outline li:hover { cursor: pointer }
|
||||
ol.outline li.nofold:hover { cursor: default }
|
||||
|
||||
ul.outline li:hover { cursor: pointer }
|
||||
ul.outline li.nofold:hover { cursor: default }
|
||||
|
||||
ol.outline { list-style:decimal; }
|
||||
ol.outline ol { list-style-type:lower-alpha }
|
||||
|
||||
/* for slides with class "title" in table of contents */
|
||||
a.titleslide { font-weight: bold; font-style: italic }
|
||||
2772
doc/talks/slidy.js
2772
doc/talks/slidy.js
File diff suppressed because it is too large
Load Diff
@@ -57,7 +57,7 @@ the content of this page is licensed under the
|
||||
Creative Commons Attribution 3.0 License,
|
||||
and code is licensed under a <a href="/LICENSE">BSD license</a>.<br>
|
||||
<a href="/doc/tos.html">Terms of Service</a> |
|
||||
<a href="http://www.google.com/intl/en/privacy/privacy-policy.html">Privacy Policy</a>
|
||||
<a href="http://www.google.com/intl/en/policies/privacy/">Privacy Policy</a>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
|
||||
@@ -3,6 +3,12 @@
|
||||
Use of this source code is governed by a BSD-style
|
||||
license that can be found in the LICENSE file.
|
||||
-->
|
||||
<!--
|
||||
Note: Static (i.e., not template-generated) href and id
|
||||
attributes start with "pkg-" to make it impossible for
|
||||
them to conflict with generated attributes (some of which
|
||||
correspond to Go identifiers).
|
||||
-->
|
||||
{{with .PDoc}}
|
||||
{{if $.IsPkg}}
|
||||
<div id="short-nav">
|
||||
@@ -10,18 +16,21 @@
|
||||
<dd><code>import "{{html .ImportPath}}"</code></dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dd><a href="#overview" class="overviewLink">Overview</a></dd>
|
||||
<dd><a href="#index">Index</a></dd>
|
||||
<dd><a href="#pkg-overview" class="overviewLink">Overview</a></dd>
|
||||
<dd><a href="#pkg-index">Index</a></dd>
|
||||
{{if $.Examples}}
|
||||
<dd><a href="#examples">Examples</a></dd>
|
||||
<dd><a href="#pkg-examples">Examples</a></dd>
|
||||
{{end}}
|
||||
{{if $.PList}}
|
||||
<dd><a href="#pkg-other-packages">Other packages</a></dd>
|
||||
{{end}}
|
||||
{{if $.Dirs}}
|
||||
<dd><a href="#subdirectories">Subdirectories</a></dd>
|
||||
<dd><a href="#pkg-subdirectories">Subdirectories</a></dd>
|
||||
{{end}}
|
||||
</dl>
|
||||
</div>
|
||||
<!-- The package's Name is printed as title by the top-level template -->
|
||||
<div id="overview" class="toggleVisible">
|
||||
<div id="pkg-overview" class="toggleVisible">
|
||||
<div class="collapsed">
|
||||
<h2 class="toggleButton" title="Click to show Overview section">Overview ▹</h2>
|
||||
</div>
|
||||
@@ -32,15 +41,15 @@
|
||||
</div>
|
||||
{{example_html "" $.Examples $.FSet}}
|
||||
|
||||
<h2 id="index">Index</h2>
|
||||
<h2 id="pkg-index">Index</h2>
|
||||
<!-- Table of contents for API; must be named manual-nav to turn off auto nav. -->
|
||||
<div id="manual-nav">
|
||||
<dl>
|
||||
{{if .Consts}}
|
||||
<dd><a href="#constants">Constants</a></dd>
|
||||
<dd><a href="#pkg-constants">Constants</a></dd>
|
||||
{{end}}
|
||||
{{if .Vars}}
|
||||
<dd><a href="#variables">Variables</a></dd>
|
||||
<dd><a href="#pkg-variables">Variables</a></dd>
|
||||
{{end}}
|
||||
{{range .Funcs}}
|
||||
{{$name_html := html .Name}}
|
||||
@@ -59,12 +68,12 @@
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{if .Bugs}}
|
||||
<dd><a href="#bugs">Bugs</a></dd>
|
||||
<dd><a href="#pkg-bugs">Bugs</a></dd>
|
||||
{{end}}
|
||||
</dl>
|
||||
|
||||
{{if $.Examples}}
|
||||
<h4 id="examples">Examples</h4>
|
||||
<h4 id="pkg-examples">Examples</h4>
|
||||
<dl>
|
||||
{{range $.Examples}}
|
||||
<dd><a class="exampleLink" href="#example_{{.Name}}">{{example_name .Name}}</a></dd>
|
||||
@@ -84,14 +93,14 @@
|
||||
{{end}}
|
||||
|
||||
{{with .Consts}}
|
||||
<h2 id="constants">Constants</h2>
|
||||
<h2 id="pkg-constants">Constants</h2>
|
||||
{{range .}}
|
||||
<pre>{{node_html .Decl $.FSet}}</pre>
|
||||
{{comment_html .Doc}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{with .Vars}}
|
||||
<h2 id="variables">Variables</h2>
|
||||
<h2 id="pkg-variables">Variables</h2>
|
||||
{{range .}}
|
||||
<pre>{{node_html .Decl $.FSet}}</pre>
|
||||
{{comment_html .Doc}}
|
||||
@@ -147,7 +156,7 @@
|
||||
{{end}}
|
||||
|
||||
{{with .Bugs}}
|
||||
<h2 id="bugs">Bugs</h2>
|
||||
<h2 id="pkg-bugs">Bugs</h2>
|
||||
{{range .}}
|
||||
{{comment_html .}}
|
||||
{{end}}
|
||||
@@ -159,7 +168,7 @@
|
||||
{{end}}
|
||||
|
||||
{{with .PList}}
|
||||
<h2>Other packages</h2>
|
||||
<h2 id="pkg-other-packages">Other packages</h2>
|
||||
<p>
|
||||
{{/* PList entries are strings - no need for FSet */}}
|
||||
{{range .}}
|
||||
@@ -171,7 +180,7 @@
|
||||
{{with .Dirs}}
|
||||
{{/* DirList entries are numbers and strings - no need for FSet */}}
|
||||
{{if $.PDoc}}
|
||||
<h2 id="subdirectories">Subdirectories</h2>
|
||||
<h2 id="pkg-subdirectories">Subdirectories</h2>
|
||||
{{else}}
|
||||
<div class="pkgGopher">
|
||||
<img class="gopher" src="/doc/gopher/pkg.png"/>
|
||||
@@ -192,14 +201,14 @@
|
||||
{{if $.DirFlat}}
|
||||
{{if .HasPkg}}
|
||||
<tr>
|
||||
<td><a href="{{html .Path}}">{{html .Path}}</a></td>
|
||||
<td class="name"><a href="{{html .Path}}/">{{html .Path}}</a></td>
|
||||
<td> </td>
|
||||
<td style="width: auto">{{html .Synopsis}}</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
{{else}}
|
||||
<tr>
|
||||
<td>{{repeat ` ` .Depth}}<a href="{{html .Path}}">{{html .Name}}</a></td>
|
||||
<td class="name">{{repeat ` ` .Depth}}<a href="{{html .Path}}/">{{html .Name}}</a></td>
|
||||
<td> </td>
|
||||
<td style="width: auto">{{html .Synopsis}}</td>
|
||||
</tr>
|
||||
|
||||
@@ -27,5 +27,7 @@ func Test1328(t *testing.T) { test1328(t) }
|
||||
func TestParallelSleep(t *testing.T) { testParallelSleep(t) }
|
||||
func TestSetEnv(t *testing.T) { testSetEnv(t) }
|
||||
func TestHelpers(t *testing.T) { testHelpers(t) }
|
||||
func Test1635(t *testing.T) { test1635(t) }
|
||||
func TestPrintf(t *testing.T) { testPrintf(t) }
|
||||
|
||||
func BenchmarkCgoCall(b *testing.B) { benchCgoCall(b) }
|
||||
|
||||
33
misc/cgo/test/issue1635.go
Normal file
33
misc/cgo/test/issue1635.go
Normal file
@@ -0,0 +1,33 @@
|
||||
// Copyright 2012 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 cgotest
|
||||
|
||||
/*
|
||||
// Mac OS X's gcc will generate scattered relocation 2/1 for
|
||||
// this function on Darwin/386, and 8l couldn't handle it.
|
||||
// this example is in issue 1635
|
||||
#include <stdio.h>
|
||||
void scatter() {
|
||||
void *p = scatter;
|
||||
printf("scatter = %p\n", p);
|
||||
}
|
||||
|
||||
// this example is in issue 3253
|
||||
int hola = 0;
|
||||
int testHola() { return hola; }
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import "testing"
|
||||
|
||||
func test1635(t *testing.T) {
|
||||
C.scatter()
|
||||
if v := C.hola; v != 0 {
|
||||
t.Fatalf("C.hola is %d, should be 0", v)
|
||||
}
|
||||
if v := C.testHola(); v != 0 {
|
||||
t.Fatalf("C.testHola() is %d, should be 0", v)
|
||||
}
|
||||
}
|
||||
22
misc/cgo/test/issue3945.go
Normal file
22
misc/cgo/test/issue3945.go
Normal file
@@ -0,0 +1,22 @@
|
||||
// Copyright 2012 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 cgotest
|
||||
|
||||
// Test that cgo reserves enough stack space during cgo call.
|
||||
// See http://golang.org/issue/3945 for details.
|
||||
|
||||
// #include <stdio.h>
|
||||
//
|
||||
// void say() {
|
||||
// printf("%s from C\n", "hello");
|
||||
// }
|
||||
//
|
||||
import "C"
|
||||
|
||||
import "testing"
|
||||
|
||||
func testPrintf(t *testing.T) {
|
||||
C.say()
|
||||
}
|
||||
@@ -1,11 +1,14 @@
|
||||
{
|
||||
"name": "Hacking Gopher",
|
||||
"version": "1.0",
|
||||
"manifest_version": 2,
|
||||
"description": "Go Hacking utility",
|
||||
"background_page": "background.html",
|
||||
"background": {
|
||||
"page": "background.html"
|
||||
},
|
||||
"browser_action": {
|
||||
"default_icon": "gopher.png",
|
||||
"popup": "popup.html"
|
||||
"default_popup": "popup.html"
|
||||
},
|
||||
"omnibox": { "keyword": "golang" },
|
||||
"icons": {
|
||||
|
||||
@@ -33,8 +33,8 @@
|
||||
;; Operators (punctuation)
|
||||
(modify-syntax-entry ?+ "." st)
|
||||
(modify-syntax-entry ?- "." st)
|
||||
(modify-syntax-entry ?* "." st)
|
||||
(modify-syntax-entry ?/ "." st)
|
||||
(modify-syntax-entry ?* ". 23" st) ; also part of comments
|
||||
(modify-syntax-entry ?/ (if (featurep 'xemacs) ". 1456" ". 124b") st) ; ditto
|
||||
(modify-syntax-entry ?% "." st)
|
||||
(modify-syntax-entry ?& "." st)
|
||||
(modify-syntax-entry ?| "." st)
|
||||
@@ -50,6 +50,9 @@
|
||||
(modify-syntax-entry ?` "." st)
|
||||
(modify-syntax-entry ?\\ "." st)
|
||||
|
||||
;; Newline is a comment-ender.
|
||||
(modify-syntax-entry ?\n "> b" st)
|
||||
|
||||
st)
|
||||
"Syntax table for Go mode.")
|
||||
|
||||
@@ -179,6 +182,10 @@ to and including character (1- go-mode-mark-comment-end)).")
|
||||
marked from the beginning up to this point.")
|
||||
(make-variable-buffer-local 'go-mode-mark-nesting-end)
|
||||
|
||||
(defun go-mode-mark-clear-cs (b e l)
|
||||
"An after-change-function that removes the go-mode-cs text property"
|
||||
(remove-text-properties b e '(go-mode-cs)))
|
||||
|
||||
(defun go-mode-mark-clear-cache (b e)
|
||||
"A before-change-function that clears the comment/string and
|
||||
nesting caches from the modified point on."
|
||||
@@ -210,7 +217,7 @@ nesting caches from the modified point on."
|
||||
(remove-text-properties
|
||||
b (min go-mode-mark-string-end (point-max)) '(go-mode-comment nil))
|
||||
(setq go-mode-mark-comment-end b)))
|
||||
|
||||
|
||||
(when (< b go-mode-mark-nesting-end)
|
||||
(remove-text-properties b (min go-mode-mark-nesting-end (point-max)) '(go-mode-nesting nil))
|
||||
(setq go-mode-mark-nesting-end b))))
|
||||
@@ -243,8 +250,8 @@ comment or string."
|
||||
|
||||
(unless pos
|
||||
(setq pos (point)))
|
||||
(when (> pos go-mode-mark-cs-end)
|
||||
(go-mode-mark-cs pos))
|
||||
(when (>= pos go-mode-mark-cs-end)
|
||||
(go-mode-mark-cs (1+ pos)))
|
||||
(get-text-property pos 'go-mode-cs))
|
||||
|
||||
(defun go-mode-mark-cs (end)
|
||||
@@ -257,7 +264,7 @@ directly; use `go-mode-cs'."
|
||||
;; Back up to the last known state.
|
||||
(let ((last-cs
|
||||
(and (> go-mode-mark-cs-end 1)
|
||||
(get-text-property (1- go-mode-mark-cs-end)
|
||||
(get-text-property (1- go-mode-mark-cs-end)
|
||||
'go-mode-cs))))
|
||||
(if last-cs
|
||||
(car last-cs)
|
||||
@@ -325,7 +332,7 @@ comment or string."
|
||||
;; Back up to the last known state.
|
||||
(let ((last-comment
|
||||
(and (> go-mode-mark-comment-end 1)
|
||||
(get-text-property (1- go-mode-mark-comment-end)
|
||||
(get-text-property (1- go-mode-mark-comment-end)
|
||||
'go-mode-comment))))
|
||||
(if last-comment
|
||||
(car last-comment)
|
||||
@@ -374,7 +381,7 @@ directly; use `go-mode-in-string'."
|
||||
;; Back up to the last known state.
|
||||
(let ((last-cs
|
||||
(and (> go-mode-mark-string-end 1)
|
||||
(get-text-property (1- go-mode-mark-string-end)
|
||||
(get-text-property (1- go-mode-mark-string-end)
|
||||
'go-mode-string))))
|
||||
(if last-cs
|
||||
(car last-cs)
|
||||
@@ -382,7 +389,7 @@ directly; use `go-mode-in-string'."
|
||||
(while (< pos end)
|
||||
(goto-char pos)
|
||||
(let ((cs-end ; end of the text property
|
||||
(cond
|
||||
(cond
|
||||
((looking-at "\"")
|
||||
(goto-char (1+ pos))
|
||||
(if (looking-at "[^\"\n\\\\]*\\(\\\\.[^\"\n\\\\]*\\)*\"")
|
||||
@@ -435,7 +442,7 @@ if no further tokens of the type exist."
|
||||
(when (search-forward "\n" (cdr cs) t)
|
||||
(put-text-property
|
||||
(car cs) (cdr cs) 'font-lock-multline t))
|
||||
(set-match-data (list (car cs) (cdr cs) (current-buffer)))
|
||||
(set-match-data (list (car cs) (copy-marker (cdr cs))))
|
||||
(goto-char (cdr cs))
|
||||
(setq result t))
|
||||
;; Wrong type. Look for next comment/string after this one.
|
||||
@@ -545,8 +552,9 @@ token on the line."
|
||||
(not (looking-at go-mode-non-terminating-keywords-regexp)))))))
|
||||
|
||||
(defun go-mode-whitespace-p (char)
|
||||
"Is char whitespace in the syntax table for go."
|
||||
(eq 32 (char-syntax char)))
|
||||
"Is newline, or char whitespace in the syntax table for go."
|
||||
(or (eq char ?\n)
|
||||
(= (char-syntax char) ?\ )))
|
||||
|
||||
(defun go-mode-backward-skip-comments ()
|
||||
"Skip backward over comments and whitespace."
|
||||
@@ -589,7 +597,7 @@ indented one level."
|
||||
(cond
|
||||
((and cs (save-excursion
|
||||
(goto-char (car cs))
|
||||
(looking-at "\\s\"")))
|
||||
(looking-at "`")))
|
||||
;; Inside a multi-line string. Don't mess with indentation.
|
||||
nil)
|
||||
(cs
|
||||
@@ -698,13 +706,18 @@ functions, and some types. It also provides indentation that is
|
||||
;; Remove stale text properties
|
||||
(save-restriction
|
||||
(widen)
|
||||
(remove-text-properties 1 (point-max)
|
||||
'(go-mode-cs nil go-mode-nesting nil)))
|
||||
(let ((modified (buffer-modified-p)))
|
||||
(remove-text-properties 1 (point-max)
|
||||
'(go-mode-cs nil go-mode-nesting nil))
|
||||
;; remove-text-properties marks the buffer modified. undo that if it
|
||||
;; wasn't originally marked modified.
|
||||
(set-buffer-modified-p modified)))
|
||||
|
||||
;; Reset the syntax mark caches
|
||||
(setq go-mode-mark-cs-end 1
|
||||
go-mode-mark-nesting-end 1)
|
||||
(add-hook 'before-change-functions #'go-mode-mark-clear-cache nil t)
|
||||
(add-hook 'after-change-functions #'go-mode-mark-clear-cs nil t)
|
||||
|
||||
;; Indentation
|
||||
(set (make-local-variable 'indent-line-function)
|
||||
@@ -716,7 +729,20 @@ functions, and some types. It also provides indentation that is
|
||||
(set (make-local-variable 'comment-end) "")
|
||||
|
||||
;; Go style
|
||||
(setq indent-tabs-mode t))
|
||||
(setq indent-tabs-mode t)
|
||||
|
||||
;; Handle unit test failure output in compilation-mode
|
||||
;;
|
||||
;; Note the final t argument to add-to-list for append, ie put these at the
|
||||
;; *ends* of compilation-error-regexp-alist[-alist]. We want go-test to be
|
||||
;; handled first, otherwise other elements will match that don't work, and
|
||||
;; those alists are traversed in *reverse* order:
|
||||
;; http://lists.gnu.org/archive/html/bug-gnu-emacs/2001-12/msg00674.html
|
||||
(when (and (boundp 'compilation-error-regexp-alist)
|
||||
(boundp 'compilation-error-regexp-alist-alist))
|
||||
(add-to-list 'compilation-error-regexp-alist 'go-test t)
|
||||
(add-to-list 'compilation-error-regexp-alist-alist
|
||||
'(go-test . ("^\t+\\([^()\t\n]+\\):\\([0-9]+\\):? .*$" 1 2)) t)))
|
||||
|
||||
;;;###autoload
|
||||
(add-to-list 'auto-mode-alist (cons "\\.go$" #'go-mode))
|
||||
@@ -737,36 +763,84 @@ Replace the current buffer on success; display errors on failure."
|
||||
|
||||
(interactive)
|
||||
(let ((currconf (current-window-configuration)))
|
||||
(let ((srcbuf (current-buffer)))
|
||||
(with-temp-buffer
|
||||
(let ((outbuf (current-buffer))
|
||||
(errbuf (get-buffer-create "*Gofmt Errors*"))
|
||||
(coding-system-for-read 'utf-8) ;; use utf-8 with subprocesses
|
||||
(coding-system-for-write 'utf-8))
|
||||
(with-current-buffer errbuf (erase-buffer))
|
||||
(with-current-buffer srcbuf
|
||||
(save-restriction
|
||||
(let (deactivate-mark)
|
||||
(widen)
|
||||
(if (= 0 (shell-command-on-region (point-min) (point-max) "gofmt"
|
||||
outbuf nil errbuf))
|
||||
;; restore window config
|
||||
;; gofmt succeeded: replace the current buffer with outbuf,
|
||||
;; restore the mark and point, and discard errbuf.
|
||||
(let ((old-mark (mark t)) (old-point (point)))
|
||||
(set-window-configuration currconf)
|
||||
(erase-buffer)
|
||||
(insert-buffer-substring outbuf)
|
||||
(goto-char (min old-point (point-max)))
|
||||
(if old-mark (push-mark (min old-mark (point-max)) t))
|
||||
(kill-buffer errbuf))
|
||||
(let ((srcbuf (current-buffer))
|
||||
(filename buffer-file-name)
|
||||
(patchbuf (get-buffer-create "*Gofmt patch*")))
|
||||
(with-current-buffer patchbuf
|
||||
(let ((errbuf (get-buffer-create "*Gofmt Errors*"))
|
||||
(coding-system-for-read 'utf-8) ;; use utf-8 with subprocesses
|
||||
(coding-system-for-write 'utf-8))
|
||||
(with-current-buffer errbuf
|
||||
(toggle-read-only 0)
|
||||
(erase-buffer))
|
||||
(with-current-buffer srcbuf
|
||||
(save-restriction
|
||||
(let (deactivate-mark)
|
||||
(widen)
|
||||
; If this is a new file, diff-mode can't apply a
|
||||
; patch to a non-exisiting file, so replace the buffer
|
||||
; completely with the output of 'gofmt'.
|
||||
; If the file exists, patch it to keep the 'undo' list happy.
|
||||
(let* ((newfile (not (file-exists-p filename)))
|
||||
(flag (if newfile "" " -d")))
|
||||
(if (= 0 (shell-command-on-region (point-min) (point-max)
|
||||
(concat "gofmt" flag)
|
||||
patchbuf nil errbuf))
|
||||
; gofmt succeeded: replace buffer or apply patch hunks.
|
||||
(let ((old-point (point))
|
||||
(old-mark (mark t)))
|
||||
(kill-buffer errbuf)
|
||||
(if newfile
|
||||
; New file, replace it (diff-mode won't work)
|
||||
(gofmt-replace-buffer srcbuf patchbuf)
|
||||
; Existing file, patch it
|
||||
(gofmt-apply-patch filename srcbuf patchbuf))
|
||||
(goto-char (min old-point (point-max)))
|
||||
;; Restore the mark and point
|
||||
(if old-mark (push-mark (min old-mark (point-max)) t))
|
||||
(set-window-configuration currconf))
|
||||
|
||||
;; gofmt failed: display the errors
|
||||
(display-buffer errbuf)))))
|
||||
;; gofmt failed: display the errors
|
||||
(gofmt-process-errors filename errbuf))))))
|
||||
|
||||
;; Collapse any window opened on outbuf if shell-command-on-region
|
||||
;; displayed it.
|
||||
(delete-windows-on outbuf))))))
|
||||
;; Collapse any window opened on outbuf if shell-command-on-region
|
||||
;; displayed it.
|
||||
(delete-windows-on patchbuf)))
|
||||
(kill-buffer patchbuf))))
|
||||
|
||||
(defun gofmt-replace-buffer (srcbuf patchbuf)
|
||||
(with-current-buffer srcbuf
|
||||
(erase-buffer)
|
||||
(insert-buffer-substring patchbuf)))
|
||||
|
||||
(defconst gofmt-stdin-tag "<standard input>")
|
||||
|
||||
(defun gofmt-apply-patch (filename srcbuf patchbuf)
|
||||
(require 'diff-mode)
|
||||
;; apply all the patch hunks
|
||||
(with-current-buffer patchbuf
|
||||
(goto-char (point-min))
|
||||
;; The .* is for TMPDIR, but to avoid dealing with TMPDIR
|
||||
;; having a trailing / or not, it's easier to just search for .*
|
||||
;; especially as we're only replacing the first instance.
|
||||
(if (re-search-forward "^--- \\(.*/gofmt[0-9]*\\)" nil t)
|
||||
(replace-match filename nil nil nil 1))
|
||||
(condition-case nil
|
||||
(while t
|
||||
(diff-hunk-next)
|
||||
(diff-apply-hunk))
|
||||
;; When there's no more hunks, diff-hunk-next signals an error, ignore it
|
||||
(error nil))))
|
||||
|
||||
(defun gofmt-process-errors (filename errbuf)
|
||||
;; Convert the gofmt stderr to something understood by the compilation mode.
|
||||
(with-current-buffer errbuf
|
||||
(goto-char (point-min))
|
||||
(insert "gofmt errors:\n")
|
||||
(if (search-forward gofmt-stdin-tag nil t)
|
||||
(replace-match (file-name-nondirectory filename) nil t))
|
||||
(display-buffer errbuf)
|
||||
(compilation-mode)))
|
||||
|
||||
;;;###autoload
|
||||
(defun gofmt-before-save ()
|
||||
|
||||
16
misc/pprof
16
misc/pprof
@@ -4595,6 +4595,7 @@ sub ConfigureObjTools {
|
||||
# in the same directory as pprof.
|
||||
$obj_tool_map{"nm_pdb"} = "nm-pdb";
|
||||
$obj_tool_map{"addr2line_pdb"} = "addr2line-pdb";
|
||||
$obj_tool_map{"is_windows"} = "true";
|
||||
}
|
||||
|
||||
if ($file_type =~ /Mach-O/) {
|
||||
@@ -4802,16 +4803,13 @@ sub GetProcedureBoundaries {
|
||||
" $image 2>/dev/null $cppfilt_flag",
|
||||
"$nm -D -n $flatten_flag $demangle_flag" .
|
||||
" $image 2>/dev/null $cppfilt_flag",
|
||||
# 6nm is for Go binaries
|
||||
"6nm $image 2>/dev/null | sort");
|
||||
# go tool nm is for Go binaries
|
||||
"go tool nm $image 2>/dev/null | sort");
|
||||
|
||||
# If the executable is an MS Windows PDB-format executable, we'll
|
||||
# have set up obj_tool_map("nm_pdb"). In this case, we actually
|
||||
# want to use both unix nm and windows-specific nm_pdb, since
|
||||
# PDB-format executables can apparently include dwarf .o files.
|
||||
if (exists $obj_tool_map{"nm_pdb"}) {
|
||||
my $nm_pdb = $obj_tool_map{"nm_pdb"};
|
||||
push(@nm_commands, "$nm_pdb --demangle $image 2>/dev/null");
|
||||
# If the executable is an MS Windows Go executable, we'll
|
||||
# have set up obj_tool_map("is_windows").
|
||||
if (exists $obj_tool_map{"is_windows"}) {
|
||||
@nm_commands = ("go tool nm $image 2>/dev/null | sort");
|
||||
}
|
||||
|
||||
foreach my $nm_command (@nm_commands) {
|
||||
|
||||
@@ -29,21 +29,43 @@ if len(s:goarch) == 0
|
||||
endif
|
||||
|
||||
function! go#complete#Package(ArgLead, CmdLine, CursorPos)
|
||||
let goroot = $GOROOT
|
||||
if len(goroot) == 0
|
||||
" should not occur.
|
||||
return []
|
||||
let dirs = []
|
||||
|
||||
if executable('go')
|
||||
let goroot = substitute(system('go env GOROOT'), '\n', '', 'g')
|
||||
if v:shell_error
|
||||
echo '\'go env GOROOT\' failed'
|
||||
endif
|
||||
else
|
||||
let goroot = $GOROOT
|
||||
endif
|
||||
|
||||
if len(goroot) != 0 && isdirectory(goroot)
|
||||
let dirs += [ goroot ]
|
||||
endif
|
||||
|
||||
let workspaces = split($GOPATH, ':')
|
||||
if workspaces != []
|
||||
let dirs += workspaces
|
||||
endif
|
||||
|
||||
if len(dirs) == 0
|
||||
" should not happen
|
||||
return []
|
||||
endif
|
||||
|
||||
let ret = {}
|
||||
let root = expand(goroot.'/pkg/'.s:goos.'_'.s:goarch)
|
||||
for i in split(globpath(root, a:ArgLead.'*'), "\n")
|
||||
if isdirectory(i)
|
||||
let i .= '/'
|
||||
elseif i !~ '\.a$'
|
||||
continue
|
||||
endif
|
||||
let i = substitute(substitute(i[len(root)+1:], '[\\]', '/', 'g'), '\.a$', '', 'g')
|
||||
let ret[i] = i
|
||||
for dir in dirs
|
||||
let root = expand(dir . '/pkg/' . s:goos . '_' . s:goarch)
|
||||
for i in split(globpath(root, a:ArgLead.'*'), "\n")
|
||||
if isdirectory(i)
|
||||
let i .= '/'
|
||||
elseif i !~ '\.a$'
|
||||
continue
|
||||
endif
|
||||
let i = substitute(substitute(i[len(root)+1:], '[\\]', '/', 'g'), '\.a$', '', 'g')
|
||||
let ret[i] = i
|
||||
endfor
|
||||
endfor
|
||||
return sort(keys(ret))
|
||||
endfunction
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
" in the current Go buffer, using proper style and ordering.
|
||||
" If {path} is already being imported, an error will be
|
||||
" displayed and the buffer will be untouched.
|
||||
"
|
||||
"
|
||||
" :ImportAs {localname} {path}
|
||||
"
|
||||
" Same as Import, but uses a custom local name for the package.
|
||||
@@ -58,6 +58,12 @@ function! s:SwitchImport(enabled, localname, path)
|
||||
return
|
||||
endif
|
||||
|
||||
" Extract any site prefix (e.g. github.com/).
|
||||
" If other imports with the same prefix are grouped separately,
|
||||
" we will add this new import with them.
|
||||
" Only up to and including the first slash is used.
|
||||
let siteprefix = matchstr(path, "^[^/]*/")
|
||||
|
||||
let qpath = '"' . path . '"'
|
||||
if a:localname != ''
|
||||
let qlocalpath = a:localname . ' ' . qpath
|
||||
@@ -83,16 +89,31 @@ function! s:SwitchImport(enabled, localname, path)
|
||||
let appendstr = qlocalpath
|
||||
let indentstr = 1
|
||||
let appendline = line
|
||||
let firstblank = -1
|
||||
let lastprefix = ""
|
||||
while line <= line("$")
|
||||
let line = line + 1
|
||||
let linestr = getline(line)
|
||||
let m = matchlist(getline(line), '^\()\|\(\s\+\)\(\S*\s*\)"\(.\+\)"\)')
|
||||
if empty(m)
|
||||
if siteprefix == ""
|
||||
" must be in the first group
|
||||
break
|
||||
endif
|
||||
" record this position, but keep looking
|
||||
if firstblank < 0
|
||||
let firstblank = line
|
||||
endif
|
||||
continue
|
||||
endif
|
||||
if m[1] == ')'
|
||||
" if there's no match, add it to the first group
|
||||
if appendline < 0 && firstblank >= 0
|
||||
let appendline = firstblank
|
||||
endif
|
||||
break
|
||||
endif
|
||||
let lastprefix = matchstr(m[4], "^[^/]*/")
|
||||
if a:localname != '' && m[3] != ''
|
||||
let qlocalpath = printf('%-' . (len(m[3])-1) . 's %s', a:localname, qpath)
|
||||
endif
|
||||
@@ -103,7 +124,16 @@ function! s:SwitchImport(enabled, localname, path)
|
||||
let deleteline = line
|
||||
break
|
||||
elseif m[4] < path
|
||||
let appendline = line
|
||||
" don't set candidate position if we have a site prefix,
|
||||
" we've passed a blank line, and this doesn't share the same
|
||||
" site prefix.
|
||||
if siteprefix == "" || firstblank < 0 || match(m[4], "^" . siteprefix) >= 0
|
||||
let appendline = line
|
||||
endif
|
||||
elseif siteprefix != "" && match(m[4], "^" . siteprefix) >= 0
|
||||
" first entry of site group
|
||||
let appendline = line - 1
|
||||
break
|
||||
endif
|
||||
endwhile
|
||||
break
|
||||
|
||||
61
misc/vim/ftplugin/go/test.sh
Executable file
61
misc/vim/ftplugin/go/test.sh
Executable file
@@ -0,0 +1,61 @@
|
||||
#!/bin/bash -e
|
||||
#
|
||||
# Copyright 2012 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.
|
||||
#
|
||||
# Tests for import.vim.
|
||||
|
||||
cd $(dirname $0)
|
||||
|
||||
cat > base.go <<EOF
|
||||
package test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"net"
|
||||
|
||||
"mycorp/foo"
|
||||
)
|
||||
EOF
|
||||
|
||||
fail=0
|
||||
|
||||
# usage: test_one new_import pattern
|
||||
# Pattern is a PCRE expression that will match across lines.
|
||||
test_one() {
|
||||
echo 2>&1 -n "Import $1: "
|
||||
vim -e -s -u /dev/null -U /dev/null --noplugin -c "source import.vim" \
|
||||
-c "Import $1" -c 'wq! test.go' base.go
|
||||
# ensure blank lines are treated correctly
|
||||
if ! gofmt test.go | cmp test.go; then
|
||||
echo 2>&1 "gofmt conflict"
|
||||
gofmt test.go | diff -u test.go - | sed "s/^/\t/" 2>&1
|
||||
fail=1
|
||||
return
|
||||
fi
|
||||
if ! grep -P -q "(?s)$2" test.go; then
|
||||
echo 2>&1 "$2 did not match"
|
||||
cat test.go | sed "s/^/\t/" 2>&1
|
||||
fail=1
|
||||
return
|
||||
fi
|
||||
echo 2>&1 "ok"
|
||||
}
|
||||
|
||||
test_one baz '"baz".*"bytes"'
|
||||
test_one io/ioutil '"io".*"io/ioutil".*"net"'
|
||||
test_one myc '"io".*"myc".*"net"' # prefix of a site prefix
|
||||
test_one nat '"io".*"nat".*"net"'
|
||||
test_one net/http '"net".*"net/http".*"mycorp/foo"'
|
||||
test_one zoo '"net".*"zoo".*"mycorp/foo"'
|
||||
test_one mycorp/bar '"net".*"mycorp/bar".*"mycorp/foo"'
|
||||
test_one mycorp/goo '"net".*"mycorp/foo".*"mycorp/goo"'
|
||||
|
||||
rm -f base.go test.go
|
||||
if [ $fail -gt 0 ]; then
|
||||
echo 2>&1 "FAIL"
|
||||
exit 1
|
||||
fi
|
||||
echo 2>&1 "PASS"
|
||||
@@ -72,7 +72,7 @@ function! s:Godoc(...)
|
||||
if !len(word)
|
||||
let word = expand('<cword>')
|
||||
endif
|
||||
let word = substitute(word, '[^a-zA-Z0-9\/]', '', 'g')
|
||||
let word = substitute(word, '[^a-zA-Z0-9\\/._~-]', '', 'g')
|
||||
if !len(word)
|
||||
return
|
||||
endif
|
||||
|
||||
@@ -8,6 +8,8 @@ if [ ! -f make.bash ]; then
|
||||
echo 'all.bash must be run from $GOROOT/src' 1>&2
|
||||
exit 1
|
||||
fi
|
||||
OLDPATH="$PATH"
|
||||
. ./make.bash --no-banner
|
||||
bash run.bash --no-rebuild --banner
|
||||
bash run.bash --no-rebuild
|
||||
PATH="$OLDPATH"
|
||||
$GOTOOLDIR/dist banner # print build info
|
||||
|
||||
@@ -11,11 +11,16 @@ echo all.bat must be run from go\src
|
||||
goto end
|
||||
:ok
|
||||
|
||||
set OLDPATH=%PATH%
|
||||
call make.bat --no-banner --no-local
|
||||
if %GOBUILDFAIL%==1 goto end
|
||||
call run.bat --no-rebuild --no-local
|
||||
if %GOBUILDFAIL%==1 goto end
|
||||
go tool dist banner
|
||||
:: we must restore %PATH% before running "dist banner" so that the latter
|
||||
:: can get the original %PATH% and give suggestion to add %GOROOT%/bin
|
||||
:: to %PATH% if necessary.
|
||||
set PATH=%OLDPATH%
|
||||
%GOTOOLDIR%/dist banner
|
||||
|
||||
:end
|
||||
if x%GOBUILDEXIT%==x1 exit %GOBUILDFAIL%
|
||||
|
||||
@@ -641,11 +641,37 @@ outhist(void)
|
||||
Hist *h;
|
||||
char *p, *q, *op, c;
|
||||
int n;
|
||||
|
||||
char *tofree;
|
||||
static int first = 1;
|
||||
static char *goroot, *goroot_final;
|
||||
|
||||
if(first) {
|
||||
// Decide whether we need to rewrite paths from $GOROOT to $GOROOT_FINAL.
|
||||
first = 0;
|
||||
goroot = getenv("GOROOT");
|
||||
goroot_final = getenv("GOROOT_FINAL");
|
||||
if(goroot == nil)
|
||||
goroot = "";
|
||||
if(goroot_final == nil)
|
||||
goroot_final = goroot;
|
||||
if(strcmp(goroot, goroot_final) == 0) {
|
||||
goroot = nil;
|
||||
goroot_final = nil;
|
||||
}
|
||||
}
|
||||
|
||||
tofree = nil;
|
||||
g = nullgen;
|
||||
c = '/';
|
||||
for(h = hist; h != H; h = h->link) {
|
||||
p = h->name;
|
||||
if(p != nil && goroot != nil) {
|
||||
n = strlen(goroot);
|
||||
if(strncmp(p, goroot, strlen(goroot)) == 0 && p[n] == '/') {
|
||||
tofree = smprint("%s%s", goroot_final, p+n);
|
||||
p = tofree;
|
||||
}
|
||||
}
|
||||
op = 0;
|
||||
if(systemtype(Windows) && p && p[1] == ':'){
|
||||
c = p[2];
|
||||
@@ -697,6 +723,11 @@ outhist(void)
|
||||
Bputc(&obuf, h->line>>24);
|
||||
zaddr(&nullgen, 0);
|
||||
zaddr(&g, 0);
|
||||
|
||||
if(tofree) {
|
||||
free(tofree);
|
||||
tofree = nil;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -140,7 +140,7 @@ Dconv(Fmt *fp)
|
||||
{
|
||||
char str[STRINGSZ];
|
||||
Adr *a;
|
||||
char *op;
|
||||
const char *op;
|
||||
int v;
|
||||
|
||||
a = va_arg(fp->args, Adr*);
|
||||
@@ -169,7 +169,7 @@ Dconv(Fmt *fp)
|
||||
|
||||
case D_SHIFT:
|
||||
v = a->offset;
|
||||
op = "<<>>->@>" + (((v>>5) & 3) << 1);
|
||||
op = &"<<>>->@>"[(((v>>5) & 3) << 1)];
|
||||
if(v & (1<<4))
|
||||
sprint(str, "R%d%c%cR%d", v&15, op[0], op[1], (v>>8)&15);
|
||||
else
|
||||
|
||||
@@ -472,12 +472,38 @@ outhist(Biobuf *b)
|
||||
char *p, *q, *op, c;
|
||||
Prog pg;
|
||||
int n;
|
||||
char *tofree;
|
||||
static int first = 1;
|
||||
static char *goroot, *goroot_final;
|
||||
|
||||
if(first) {
|
||||
// Decide whether we need to rewrite paths from $GOROOT to $GOROOT_FINAL.
|
||||
first = 0;
|
||||
goroot = getenv("GOROOT");
|
||||
goroot_final = getenv("GOROOT_FINAL");
|
||||
if(goroot == nil)
|
||||
goroot = "";
|
||||
if(goroot_final == nil)
|
||||
goroot_final = goroot;
|
||||
if(strcmp(goroot, goroot_final) == 0) {
|
||||
goroot = nil;
|
||||
goroot_final = nil;
|
||||
}
|
||||
}
|
||||
|
||||
tofree = nil;
|
||||
pg = zprog;
|
||||
pg.as = AHISTORY;
|
||||
c = pathchar();
|
||||
for(h = hist; h != H; h = h->link) {
|
||||
p = h->name;
|
||||
if(p != nil && goroot != nil) {
|
||||
n = strlen(goroot);
|
||||
if(strncmp(p, goroot, strlen(goroot)) == 0 && p[n] == '/') {
|
||||
tofree = smprint("%s%s", goroot_final, p+n);
|
||||
p = tofree;
|
||||
}
|
||||
}
|
||||
op = 0;
|
||||
if(systemtype(Windows) && p && p[1] == ':'){
|
||||
c = p[2];
|
||||
@@ -525,6 +551,11 @@ outhist(Biobuf *b)
|
||||
pg.to.type = D_CONST;
|
||||
|
||||
zwrite(b, &pg, 0, 0);
|
||||
|
||||
if(tofree) {
|
||||
free(tofree);
|
||||
tofree = nil;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -198,7 +198,8 @@ dumpfuncs(void)
|
||||
if(isblank(pl->name))
|
||||
continue;
|
||||
|
||||
if(debug['S']) {
|
||||
// -S prints code; -SS prints code and data
|
||||
if(debug['S'] && (pl->name || debug['S']>1)) {
|
||||
s = S;
|
||||
if(pl->name != N)
|
||||
s = pl->name->sym;
|
||||
|
||||
@@ -83,7 +83,7 @@ int
|
||||
Dconv(Fmt *fp)
|
||||
{
|
||||
char str[STRINGSZ];
|
||||
char *op;
|
||||
const char *op;
|
||||
Addr *a;
|
||||
int i;
|
||||
int32 v;
|
||||
@@ -119,7 +119,7 @@ Dconv(Fmt *fp)
|
||||
|
||||
case D_SHIFT:
|
||||
v = a->offset;
|
||||
op = "<<>>->@>" + (((v>>5) & 3) << 1);
|
||||
op = &"<<>>->@>"[(((v>>5) & 3) << 1)];
|
||||
if(v & (1<<4))
|
||||
sprint(str, "R%d%c%cR%d", v&15, op[0], op[1], (v>>8)&15);
|
||||
else
|
||||
|
||||
@@ -695,8 +695,8 @@ brk:
|
||||
}
|
||||
}
|
||||
}
|
||||
if(r1 != R) {
|
||||
r1->link = freer;
|
||||
if(lastr != R) {
|
||||
lastr->link = freer;
|
||||
freer = firstr;
|
||||
}
|
||||
|
||||
|
||||
@@ -161,7 +161,7 @@ int
|
||||
Dconv(Fmt *fp)
|
||||
{
|
||||
char str[STRINGSZ];
|
||||
char *op;
|
||||
const char *op;
|
||||
Adr *a;
|
||||
int32 v;
|
||||
|
||||
@@ -191,7 +191,7 @@ Dconv(Fmt *fp)
|
||||
|
||||
case D_SHIFT:
|
||||
v = a->offset;
|
||||
op = "<<>>->@>" + (((v>>5) & 3) << 1);
|
||||
op = &"<<>>->@>"[(((v>>5) & 3) << 1)];
|
||||
if(v & (1<<4))
|
||||
snprint(str, sizeof str, "R%d%c%cR%d", v&15, op[0], op[1], (v>>8)&15);
|
||||
else
|
||||
|
||||
@@ -1250,11 +1250,38 @@ outhist(void)
|
||||
Hist *h;
|
||||
char *p, *q, *op, c;
|
||||
int n;
|
||||
char *tofree;
|
||||
static int first = 1;
|
||||
static char *goroot, *goroot_final;
|
||||
|
||||
if(first) {
|
||||
// Decide whether we need to rewrite paths from $GOROOT to $GOROOT_FINAL.
|
||||
first = 0;
|
||||
goroot = getenv("GOROOT");
|
||||
goroot_final = getenv("GOROOT_FINAL");
|
||||
if(goroot == nil)
|
||||
goroot = "";
|
||||
if(goroot_final == nil)
|
||||
goroot_final = goroot;
|
||||
if(strcmp(goroot, goroot_final) == 0) {
|
||||
goroot = nil;
|
||||
goroot_final = nil;
|
||||
}
|
||||
}
|
||||
|
||||
tofree = nil;
|
||||
|
||||
g = nullgen;
|
||||
c = pathchar();
|
||||
for(h = hist; h != H; h = h->link) {
|
||||
p = h->name;
|
||||
if(p != nil && goroot != nil) {
|
||||
n = strlen(goroot);
|
||||
if(strncmp(p, goroot, strlen(goroot)) == 0 && p[n] == '/') {
|
||||
tofree = smprint("%s%s", goroot_final, p+n);
|
||||
p = tofree;
|
||||
}
|
||||
}
|
||||
op = 0;
|
||||
if(systemtype(Windows) && p && p[1] == ':'){
|
||||
c = p[2];
|
||||
@@ -1306,6 +1333,11 @@ outhist(void)
|
||||
Bputc(&obuf, h->line>>24);
|
||||
zaddr(&nullgen, 0);
|
||||
zaddr(&g, 0);
|
||||
|
||||
if(tofree) {
|
||||
free(tofree);
|
||||
tofree = nil;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -339,12 +339,38 @@ outhist(Biobuf *b)
|
||||
char *p, *q, *op, c;
|
||||
Prog pg;
|
||||
int n;
|
||||
char *tofree;
|
||||
static int first = 1;
|
||||
static char *goroot, *goroot_final;
|
||||
|
||||
if(first) {
|
||||
// Decide whether we need to rewrite paths from $GOROOT to $GOROOT_FINAL.
|
||||
first = 0;
|
||||
goroot = getenv("GOROOT");
|
||||
goroot_final = getenv("GOROOT_FINAL");
|
||||
if(goroot == nil)
|
||||
goroot = "";
|
||||
if(goroot_final == nil)
|
||||
goroot_final = goroot;
|
||||
if(strcmp(goroot, goroot_final) == 0) {
|
||||
goroot = nil;
|
||||
goroot_final = nil;
|
||||
}
|
||||
}
|
||||
|
||||
tofree = nil;
|
||||
pg = zprog;
|
||||
pg.as = AHISTORY;
|
||||
c = pathchar();
|
||||
for(h = hist; h != H; h = h->link) {
|
||||
p = h->name;
|
||||
if(p != nil && goroot != nil) {
|
||||
n = strlen(goroot);
|
||||
if(strncmp(p, goroot, strlen(goroot)) == 0 && p[n] == '/') {
|
||||
tofree = smprint("%s%s", goroot_final, p+n);
|
||||
p = tofree;
|
||||
}
|
||||
}
|
||||
op = 0;
|
||||
if(systemtype(Windows) && p && p[1] == ':'){
|
||||
c = p[2];
|
||||
@@ -400,6 +426,11 @@ outhist(Biobuf *b)
|
||||
Bputc(b, pg.lineno>>24);
|
||||
zaddr(b, &pg.from, 0);
|
||||
zaddr(b, &pg.to, 0);
|
||||
|
||||
if(tofree) {
|
||||
free(tofree);
|
||||
tofree = nil;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -244,7 +244,8 @@ dumpfuncs(void)
|
||||
if(isblank(pl->name))
|
||||
continue;
|
||||
|
||||
if(debug['S']) {
|
||||
// -S prints code; -SS prints code and data
|
||||
if(debug['S'] && (pl->name || debug['S']>1)) {
|
||||
s = S;
|
||||
if(pl->name != N)
|
||||
s = pl->name->sym;
|
||||
|
||||
@@ -822,9 +822,9 @@ gmove(Node *f, Node *t)
|
||||
// algorithm is:
|
||||
// if small enough, use native float64 -> int64 conversion.
|
||||
// otherwise, subtract 2^63, convert, and add it back.
|
||||
a = ACVTSS2SQ;
|
||||
a = ACVTTSS2SQ;
|
||||
if(ft == TFLOAT64)
|
||||
a = ACVTSD2SQ;
|
||||
a = ACVTTSD2SQ;
|
||||
bignodes();
|
||||
regalloc(&r1, types[ft], N);
|
||||
regalloc(&r2, types[tt], t);
|
||||
|
||||
@@ -780,8 +780,8 @@ brk:
|
||||
p->to.branch = p->to.branch->link;
|
||||
}
|
||||
|
||||
if(r1 != R) {
|
||||
r1->link = freer;
|
||||
if(lastr != R) {
|
||||
lastr->link = freer;
|
||||
freer = firstr;
|
||||
}
|
||||
|
||||
|
||||
@@ -915,11 +915,38 @@ outhist(void)
|
||||
Hist *h;
|
||||
char *p, *q, *op, c;
|
||||
int n;
|
||||
char *tofree;
|
||||
static int first = 1;
|
||||
static char *goroot, *goroot_final;
|
||||
|
||||
if(first) {
|
||||
// Decide whether we need to rewrite paths from $GOROOT to $GOROOT_FINAL.
|
||||
first = 0;
|
||||
goroot = getenv("GOROOT");
|
||||
goroot_final = getenv("GOROOT_FINAL");
|
||||
if(goroot == nil)
|
||||
goroot = "";
|
||||
if(goroot_final == nil)
|
||||
goroot_final = goroot;
|
||||
if(strcmp(goroot, goroot_final) == 0) {
|
||||
goroot = nil;
|
||||
goroot_final = nil;
|
||||
}
|
||||
}
|
||||
|
||||
tofree = nil;
|
||||
|
||||
g = nullgen;
|
||||
c = pathchar();
|
||||
for(h = hist; h != H; h = h->link) {
|
||||
p = h->name;
|
||||
if(p != nil && goroot != nil) {
|
||||
n = strlen(goroot);
|
||||
if(strncmp(p, goroot, strlen(goroot)) == 0 && p[n] == '/') {
|
||||
tofree = smprint("%s%s", goroot_final, p+n);
|
||||
p = tofree;
|
||||
}
|
||||
}
|
||||
op = 0;
|
||||
if(systemtype(Windows) && p && p[1] == ':'){
|
||||
c = p[2];
|
||||
@@ -971,6 +998,11 @@ outhist(void)
|
||||
Bputc(&obuf, h->line>>24);
|
||||
zaddr(&nullgen, 0);
|
||||
zaddr(&g, 0);
|
||||
|
||||
if(tofree) {
|
||||
free(tofree);
|
||||
tofree = nil;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -343,12 +343,38 @@ outhist(Biobuf *b)
|
||||
char *p, *q, *op, c;
|
||||
Prog pg;
|
||||
int n;
|
||||
char *tofree;
|
||||
static int first = 1;
|
||||
static char *goroot, *goroot_final;
|
||||
|
||||
if(first) {
|
||||
// Decide whether we need to rewrite paths from $GOROOT to $GOROOT_FINAL.
|
||||
first = 0;
|
||||
goroot = getenv("GOROOT");
|
||||
goroot_final = getenv("GOROOT_FINAL");
|
||||
if(goroot == nil)
|
||||
goroot = "";
|
||||
if(goroot_final == nil)
|
||||
goroot_final = goroot;
|
||||
if(strcmp(goroot, goroot_final) == 0) {
|
||||
goroot = nil;
|
||||
goroot_final = nil;
|
||||
}
|
||||
}
|
||||
|
||||
tofree = nil;
|
||||
pg = zprog;
|
||||
pg.as = AHISTORY;
|
||||
c = pathchar();
|
||||
for(h = hist; h != H; h = h->link) {
|
||||
p = h->name;
|
||||
if(p != nil && goroot != nil) {
|
||||
n = strlen(goroot);
|
||||
if(strncmp(p, goroot, strlen(goroot)) == 0 && p[n] == '/') {
|
||||
tofree = smprint("%s%s", goroot_final, p+n);
|
||||
p = tofree;
|
||||
}
|
||||
}
|
||||
op = 0;
|
||||
if(systemtype(Windows) && p && p[1] == ':'){
|
||||
c = p[2];
|
||||
@@ -404,6 +430,11 @@ outhist(Biobuf *b)
|
||||
Bputc(b, pg.lineno>>24);
|
||||
zaddr(b, &pg.from, 0);
|
||||
zaddr(b, &pg.to, 0);
|
||||
|
||||
if(tofree) {
|
||||
free(tofree);
|
||||
tofree = nil;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -242,7 +242,8 @@ dumpfuncs(void)
|
||||
if(isblank(pl->name))
|
||||
continue;
|
||||
|
||||
if(debug['S']) {
|
||||
// -S prints code; -SS prints code and data
|
||||
if(debug['S'] && (pl->name || debug['S']>1)) {
|
||||
s = S;
|
||||
if(pl->name != N)
|
||||
s = pl->name->sym;
|
||||
|
||||
@@ -1847,6 +1847,7 @@ naddr(Node *n, Addr *a, int canemitcode)
|
||||
a->width = 0;
|
||||
if(n->type != T) {
|
||||
a->etype = simtype[n->type->etype];
|
||||
dowidth(n->type);
|
||||
a->width = n->type->width;
|
||||
a->gotype = ngotype(n);
|
||||
}
|
||||
|
||||
@@ -677,8 +677,8 @@ brk:
|
||||
p->to.branch = p->to.branch->link;
|
||||
}
|
||||
|
||||
if(r1 != R) {
|
||||
r1->link = freer;
|
||||
if(lastr != R) {
|
||||
lastr->link = freer;
|
||||
freer = firstr;
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ import (
|
||||
"os/exec"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -35,27 +36,31 @@ import (
|
||||
|
||||
// Flags
|
||||
var (
|
||||
// TODO(bradfitz): once Go 1.1 comes out, allow the -c flag to take a comma-separated
|
||||
// list of files, rather than just one.
|
||||
checkFile = flag.String("c", "", "optional filename to check API against")
|
||||
verbose = flag.Bool("v", false, "Verbose debugging")
|
||||
allowNew = flag.Bool("allow_new", true, "allow API additions")
|
||||
nextFile = flag.String("next", "", "optional filename of tentative upcoming API features for the next release. This file can be lazily maintained. It only affects the delta warnings from the -c file printed on success.")
|
||||
verbose = flag.Bool("v", false, "verbose debugging")
|
||||
forceCtx = flag.String("contexts", "", "optional comma-separated list of <goos>-<goarch>[-cgo] to override default contexts.")
|
||||
)
|
||||
|
||||
// contexts are the default contexts which are scanned, unless
|
||||
// overridden by the -contexts flag.
|
||||
var contexts = []*build.Context{
|
||||
{GOOS: "linux", GOARCH: "386", CgoEnabled: true},
|
||||
{GOOS: "linux", GOARCH: "386"},
|
||||
{GOOS: "linux", GOARCH: "amd64", CgoEnabled: true},
|
||||
{GOOS: "linux", GOARCH: "amd64"},
|
||||
{GOOS: "linux", GOARCH: "arm"},
|
||||
{GOOS: "darwin", GOARCH: "386", CgoEnabled: true},
|
||||
{GOOS: "darwin", GOARCH: "386"},
|
||||
{GOOS: "darwin", GOARCH: "amd64", CgoEnabled: true},
|
||||
{GOOS: "darwin", GOARCH: "amd64"},
|
||||
{GOOS: "windows", GOARCH: "amd64"},
|
||||
{GOOS: "windows", GOARCH: "386"},
|
||||
}
|
||||
|
||||
func init() {
|
||||
for _, c := range contexts {
|
||||
c.Compiler = build.Default.Compiler
|
||||
}
|
||||
{GOOS: "freebsd", GOARCH: "amd64"},
|
||||
{GOOS: "freebsd", GOARCH: "386"},
|
||||
}
|
||||
|
||||
func contextName(c *build.Context) string {
|
||||
@@ -66,9 +71,49 @@ func contextName(c *build.Context) string {
|
||||
return s
|
||||
}
|
||||
|
||||
func parseContext(c string) *build.Context {
|
||||
parts := strings.Split(c, "-")
|
||||
if len(parts) < 2 {
|
||||
log.Fatalf("bad context: %q", c)
|
||||
}
|
||||
bc := &build.Context{
|
||||
GOOS: parts[0],
|
||||
GOARCH: parts[1],
|
||||
}
|
||||
if len(parts) == 3 {
|
||||
if parts[2] == "cgo" {
|
||||
bc.CgoEnabled = true
|
||||
} else {
|
||||
log.Fatalf("bad context: %q", c)
|
||||
}
|
||||
}
|
||||
return bc
|
||||
}
|
||||
|
||||
func setContexts() {
|
||||
contexts = []*build.Context{}
|
||||
for _, c := range strings.Split(*forceCtx, ",") {
|
||||
contexts = append(contexts, parseContext(c))
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
|
||||
if !strings.Contains(runtime.Version(), "weekly") {
|
||||
if *nextFile != "" {
|
||||
fmt.Printf("Go version is %q, ignoring -next %s\n", runtime.Version(), *nextFile)
|
||||
*nextFile = ""
|
||||
}
|
||||
}
|
||||
|
||||
if *forceCtx != "" {
|
||||
setContexts()
|
||||
}
|
||||
for _, c := range contexts {
|
||||
c.Compiler = build.Default.Compiler
|
||||
}
|
||||
|
||||
var pkgs []string
|
||||
if flag.NArg() > 0 {
|
||||
pkgs = flag.Args()
|
||||
@@ -123,45 +168,86 @@ func main() {
|
||||
}
|
||||
sort.Strings(features)
|
||||
|
||||
fail := false
|
||||
defer func() {
|
||||
if fail {
|
||||
os.Exit(1)
|
||||
}
|
||||
}()
|
||||
|
||||
bw := bufio.NewWriter(os.Stdout)
|
||||
defer bw.Flush()
|
||||
|
||||
if *checkFile != "" {
|
||||
bs, err := ioutil.ReadFile(*checkFile)
|
||||
if err != nil {
|
||||
log.Fatalf("Error reading file %s: %v", *checkFile, err)
|
||||
}
|
||||
v1 := strings.Split(strings.TrimSpace(string(bs)), "\n")
|
||||
sort.Strings(v1)
|
||||
v2 := features
|
||||
take := func(sl *[]string) string {
|
||||
s := (*sl)[0]
|
||||
*sl = (*sl)[1:]
|
||||
return s
|
||||
}
|
||||
changes := false
|
||||
for len(v1) > 0 || len(v2) > 0 {
|
||||
switch {
|
||||
case len(v2) == 0 || v1[0] < v2[0]:
|
||||
fmt.Fprintf(bw, "-%s\n", take(&v1))
|
||||
changes = true
|
||||
case len(v1) == 0 || v1[0] > v2[0]:
|
||||
fmt.Fprintf(bw, "+%s\n", take(&v2))
|
||||
changes = true
|
||||
default:
|
||||
take(&v1)
|
||||
take(&v2)
|
||||
}
|
||||
}
|
||||
if changes {
|
||||
bw.Flush()
|
||||
os.Exit(1)
|
||||
}
|
||||
} else {
|
||||
if *checkFile == "" {
|
||||
for _, f := range features {
|
||||
fmt.Fprintf(bw, "%s\n", f)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
var required []string
|
||||
for _, filename := range []string{*checkFile} {
|
||||
required = append(required, fileFeatures(filename)...)
|
||||
}
|
||||
sort.Strings(required)
|
||||
|
||||
var optional = make(map[string]bool) // feature => true
|
||||
if *nextFile != "" {
|
||||
for _, feature := range fileFeatures(*nextFile) {
|
||||
optional[feature] = true
|
||||
}
|
||||
}
|
||||
|
||||
take := func(sl *[]string) string {
|
||||
s := (*sl)[0]
|
||||
*sl = (*sl)[1:]
|
||||
return s
|
||||
}
|
||||
|
||||
for len(required) > 0 || len(features) > 0 {
|
||||
switch {
|
||||
case len(features) == 0 || required[0] < features[0]:
|
||||
fmt.Fprintf(bw, "-%s\n", take(&required))
|
||||
fail = true // broke compatibility
|
||||
case len(required) == 0 || required[0] > features[0]:
|
||||
newFeature := take(&features)
|
||||
if optional[newFeature] {
|
||||
// Known added feature to the upcoming release.
|
||||
// Delete it from the map so we can detect any upcoming features
|
||||
// which were never seen. (so we can clean up the nextFile)
|
||||
delete(optional, newFeature)
|
||||
} else {
|
||||
fmt.Fprintf(bw, "+%s\n", newFeature)
|
||||
if !*allowNew {
|
||||
fail = true // we're in lock-down mode for next release
|
||||
}
|
||||
}
|
||||
default:
|
||||
take(&required)
|
||||
take(&features)
|
||||
}
|
||||
}
|
||||
|
||||
var missing []string
|
||||
for feature := range optional {
|
||||
missing = append(missing, feature)
|
||||
}
|
||||
sort.Strings(missing)
|
||||
for _, feature := range missing {
|
||||
fmt.Fprintf(bw, "(in next file, but not in API) -%s\n", feature)
|
||||
}
|
||||
}
|
||||
|
||||
func fileFeatures(filename string) []string {
|
||||
bs, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
log.Fatalf("Error reading file %s: %v", filename, err)
|
||||
}
|
||||
text := strings.TrimSpace(string(bs))
|
||||
if text == "" {
|
||||
return nil
|
||||
}
|
||||
return strings.Split(text, "\n")
|
||||
}
|
||||
|
||||
// pkgSymbol represents a symbol in a package
|
||||
|
||||
@@ -175,7 +175,10 @@ evconst(Node *n)
|
||||
break;
|
||||
|
||||
case OLSHR:
|
||||
v = (uvlong)l->vconst >> r->vconst;
|
||||
if(l->type->width != sizeof(uvlong))
|
||||
v = ((uvlong)l->vconst & 0xffffffffULL) >> r->vconst;
|
||||
else
|
||||
v = (uvlong)l->vconst >> r->vconst;
|
||||
break;
|
||||
|
||||
case OASHR:
|
||||
|
||||
@@ -508,7 +508,12 @@ func (p *Package) loadDWARF(f *File, names []*Name) {
|
||||
fmt.Fprintf(&b, "\t0,\n")
|
||||
}
|
||||
}
|
||||
fmt.Fprintf(&b, "\t0\n")
|
||||
// for the last entry, we can not use 0, otherwise
|
||||
// in case all __cgodebug_data is zero initialized,
|
||||
// LLVM-based gcc will place the it in the __DATA.__common
|
||||
// zero-filled section (our debug/macho doesn't support
|
||||
// this)
|
||||
fmt.Fprintf(&b, "\t1\n")
|
||||
fmt.Fprintf(&b, "};\n")
|
||||
|
||||
d, bo, debugData := p.gccDebug(b.Bytes())
|
||||
|
||||
@@ -22,6 +22,7 @@ import (
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
@@ -33,9 +34,8 @@ type Package struct {
|
||||
GccOptions []string
|
||||
CgoFlags map[string]string // #cgo flags (CFLAGS, LDFLAGS)
|
||||
Written map[string]bool
|
||||
Name map[string]*Name // accumulated Name from Files
|
||||
Typedef map[string]ast.Expr // accumulated Typedef from Files
|
||||
ExpFunc []*ExpFunc // accumulated ExpFunc from Files
|
||||
Name map[string]*Name // accumulated Name from Files
|
||||
ExpFunc []*ExpFunc // accumulated ExpFunc from Files
|
||||
Decl []ast.Decl
|
||||
GoFiles []string // list of Go files
|
||||
GccFiles []string // list of gcc output files
|
||||
@@ -51,7 +51,15 @@ type File struct {
|
||||
Ref []*Ref // all references to C.xxx in AST
|
||||
ExpFunc []*ExpFunc // exported functions for this file
|
||||
Name map[string]*Name // map from Go name to Name
|
||||
Typedef map[string]ast.Expr // translations of all necessary types from C
|
||||
}
|
||||
|
||||
func nameKeys(m map[string]*Name) []string {
|
||||
var ks []string
|
||||
for k := range m {
|
||||
ks = append(ks, k)
|
||||
}
|
||||
sort.Strings(ks)
|
||||
return ks
|
||||
}
|
||||
|
||||
// A Ref refers to an expression of the form C.xxx in the AST.
|
||||
@@ -136,7 +144,8 @@ var cdefs = flag.Bool("cdefs", false, "for bootstrap: write C definitions for C
|
||||
var objDir = flag.String("objdir", "", "object directory")
|
||||
|
||||
var gccgo = flag.Bool("gccgo", false, "generate files for use with gccgo")
|
||||
var gccgoprefix = flag.String("gccgoprefix", "go", "prefix of symbols generated by gccgo")
|
||||
var gccgoprefix = flag.String("gccgoprefix", "", "-fgo-prefix option used with gccgo")
|
||||
var gccgopkgpath = flag.String("gccgopkgpath", "", "-fgo-pkgpath option used with gccgo")
|
||||
var importRuntimeCgo = flag.Bool("import_runtime_cgo", true, "import runtime/cgo in generated code")
|
||||
var goarch, goos string
|
||||
|
||||
|
||||
@@ -71,7 +71,8 @@ func (p *Package) writeDefs() {
|
||||
}
|
||||
|
||||
cVars := make(map[string]bool)
|
||||
for _, n := range p.Name {
|
||||
for _, key := range nameKeys(p.Name) {
|
||||
n := p.Name[key]
|
||||
if n.Kind != "var" {
|
||||
continue
|
||||
}
|
||||
@@ -94,14 +95,16 @@ func (p *Package) writeDefs() {
|
||||
}
|
||||
fmt.Fprintf(fc, "\n")
|
||||
|
||||
for _, n := range p.Name {
|
||||
for _, key := range nameKeys(p.Name) {
|
||||
n := p.Name[key]
|
||||
if n.Const != "" {
|
||||
fmt.Fprintf(fgo2, "const _Cconst_%s = %s\n", n.Go, n.Const)
|
||||
}
|
||||
}
|
||||
fmt.Fprintf(fgo2, "\n")
|
||||
|
||||
for _, n := range p.Name {
|
||||
for _, key := range nameKeys(p.Name) {
|
||||
n := p.Name[key]
|
||||
if n.FuncType != nil {
|
||||
p.writeDefsFunc(fc, fgo2, n)
|
||||
}
|
||||
@@ -372,7 +375,8 @@ func (p *Package) writeOutput(f *File, srcfile string) {
|
||||
fmt.Fprintf(fgcc, "%s\n", f.Preamble)
|
||||
fmt.Fprintf(fgcc, "%s\n", gccProlog)
|
||||
|
||||
for _, n := range f.Name {
|
||||
for _, key := range nameKeys(f.Name) {
|
||||
n := f.Name[key]
|
||||
if n.FuncType != nil {
|
||||
p.writeOutputFunc(fgcc, n)
|
||||
}
|
||||
@@ -457,6 +461,8 @@ func (p *Package) writeExports(fgo2, fc, fm *os.File) {
|
||||
fmt.Fprintf(fgcc, "/* Created by cgo - DO NOT EDIT. */\n")
|
||||
fmt.Fprintf(fgcc, "#include \"_cgo_export.h\"\n")
|
||||
|
||||
fmt.Fprintf(fgcc, "\nextern void crosscall2(void (*fn)(void *, int), void *, int);\n\n")
|
||||
|
||||
for _, exp := range p.ExpFunc {
|
||||
fn := exp.Func
|
||||
|
||||
@@ -548,7 +554,7 @@ func (p *Package) writeExports(fgo2, fc, fm *os.File) {
|
||||
s += ")"
|
||||
fmt.Fprintf(fgcch, "\nextern %s;\n", s)
|
||||
|
||||
fmt.Fprintf(fgcc, "extern _cgoexp%s_%s(void *, int);\n", cPrefix, exp.ExpName)
|
||||
fmt.Fprintf(fgcc, "extern void _cgoexp%s_%s(void *, int);\n", cPrefix, exp.ExpName)
|
||||
fmt.Fprintf(fgcc, "\n%s\n", s)
|
||||
fmt.Fprintf(fgcc, "{\n")
|
||||
fmt.Fprintf(fgcc, "\t%s __attribute__((packed)) a;\n", ctype)
|
||||
@@ -652,7 +658,21 @@ func (p *Package) writeGccgoExports(fgo2, fc, fm *os.File) {
|
||||
}
|
||||
return '_'
|
||||
}
|
||||
gccgoSymbolPrefix := strings.Map(clean, *gccgoprefix)
|
||||
|
||||
var gccgoSymbolPrefix string
|
||||
if *gccgopkgpath != "" {
|
||||
gccgoSymbolPrefix = strings.Map(clean, *gccgopkgpath)
|
||||
} else {
|
||||
if *gccgoprefix == "" && p.PackageName == "main" {
|
||||
gccgoSymbolPrefix = "main"
|
||||
} else {
|
||||
prefix := strings.Map(clean, *gccgoprefix)
|
||||
if prefix == "" {
|
||||
prefix = "go"
|
||||
}
|
||||
gccgoSymbolPrefix = prefix + "." + p.PackageName
|
||||
}
|
||||
}
|
||||
|
||||
for _, exp := range p.ExpFunc {
|
||||
// TODO: support functions with receivers.
|
||||
@@ -690,7 +710,7 @@ func (p *Package) writeGccgoExports(fgo2, fc, fm *os.File) {
|
||||
|
||||
// The function name.
|
||||
fmt.Fprintf(cdeclBuf, " "+exp.ExpName)
|
||||
gccgoSymbol := fmt.Sprintf("%s.%s.%s", gccgoSymbolPrefix, p.PackageName, exp.Func.Name)
|
||||
gccgoSymbol := fmt.Sprintf("%s.%s", gccgoSymbolPrefix, exp.Func.Name)
|
||||
fmt.Fprintf(cdeclBuf, " (")
|
||||
// Function parameters.
|
||||
forFieldList(fntype.Params,
|
||||
@@ -736,25 +756,23 @@ func c(repr string, args ...interface{}) *TypeRepr {
|
||||
|
||||
// Map predeclared Go types to Type.
|
||||
var goTypes = map[string]*Type{
|
||||
"bool": {Size: 1, Align: 1, C: c("uchar")},
|
||||
"byte": {Size: 1, Align: 1, C: c("uchar")},
|
||||
"int": {Size: 4, Align: 4, C: c("int")},
|
||||
"uint": {Size: 4, Align: 4, C: c("uint")},
|
||||
"rune": {Size: 4, Align: 4, C: c("int")},
|
||||
"int8": {Size: 1, Align: 1, C: c("schar")},
|
||||
"uint8": {Size: 1, Align: 1, C: c("uchar")},
|
||||
"int16": {Size: 2, Align: 2, C: c("short")},
|
||||
"uint16": {Size: 2, Align: 2, C: c("ushort")},
|
||||
"int32": {Size: 4, Align: 4, C: c("int")},
|
||||
"uint32": {Size: 4, Align: 4, C: c("uint")},
|
||||
"int64": {Size: 8, Align: 8, C: c("int64")},
|
||||
"uint64": {Size: 8, Align: 8, C: c("uint64")},
|
||||
"float": {Size: 4, Align: 4, C: c("float")},
|
||||
"float32": {Size: 4, Align: 4, C: c("float")},
|
||||
"float64": {Size: 8, Align: 8, C: c("double")},
|
||||
"complex": {Size: 8, Align: 8, C: c("__complex float")},
|
||||
"complex64": {Size: 8, Align: 8, C: c("__complex float")},
|
||||
"complex128": {Size: 16, Align: 16, C: c("__complex double")},
|
||||
"bool": {Size: 1, Align: 1, C: c("GoUint8")},
|
||||
"byte": {Size: 1, Align: 1, C: c("GoUint8")},
|
||||
"int": {Size: 4, Align: 4, C: c("GoInt")},
|
||||
"uint": {Size: 4, Align: 4, C: c("GoUint")},
|
||||
"rune": {Size: 4, Align: 4, C: c("GoInt32")},
|
||||
"int8": {Size: 1, Align: 1, C: c("GoInt8")},
|
||||
"uint8": {Size: 1, Align: 1, C: c("GoUint8")},
|
||||
"int16": {Size: 2, Align: 2, C: c("GoInt16")},
|
||||
"uint16": {Size: 2, Align: 2, C: c("GoUint16")},
|
||||
"int32": {Size: 4, Align: 4, C: c("GoInt32")},
|
||||
"uint32": {Size: 4, Align: 4, C: c("GoUint32")},
|
||||
"int64": {Size: 8, Align: 8, C: c("GoInt64")},
|
||||
"uint64": {Size: 8, Align: 8, C: c("GoUint64")},
|
||||
"float32": {Size: 4, Align: 4, C: c("GoFloat32")},
|
||||
"float64": {Size: 8, Align: 8, C: c("GoFloat64")},
|
||||
"complex64": {Size: 8, Align: 8, C: c("GoComplex64")},
|
||||
"complex128": {Size: 16, Align: 16, C: c("GoComplex128")},
|
||||
}
|
||||
|
||||
// Map an ast type to a Type.
|
||||
@@ -799,7 +817,7 @@ func (p *Package) cgoType(e ast.Expr) *Type {
|
||||
return def
|
||||
}
|
||||
if t.Name == "uintptr" {
|
||||
return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("uintptr")}
|
||||
return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("GoUintptr")}
|
||||
}
|
||||
if t.Name == "string" {
|
||||
return &Type{Size: p.PtrSize + 4, Align: p.PtrSize, C: c("GoString")}
|
||||
@@ -930,13 +948,21 @@ Slice GoBytes(char *p, int n) {
|
||||
`
|
||||
|
||||
const gccExportHeaderProlog = `
|
||||
typedef unsigned int uint;
|
||||
typedef signed char schar;
|
||||
typedef unsigned char uchar;
|
||||
typedef unsigned short ushort;
|
||||
typedef long long int64;
|
||||
typedef unsigned long long uint64;
|
||||
typedef __SIZE_TYPE__ uintptr;
|
||||
typedef int GoInt;
|
||||
typedef unsigned int GoUint;
|
||||
typedef signed char GoInt8;
|
||||
typedef unsigned char GoUint8;
|
||||
typedef short GoInt16;
|
||||
typedef unsigned short GoUint16;
|
||||
typedef int GoInt32;
|
||||
typedef unsigned int GoUint32;
|
||||
typedef long long GoInt64;
|
||||
typedef unsigned long long GoUint64;
|
||||
typedef __SIZE_TYPE__ GoUintptr;
|
||||
typedef float GoFloat32;
|
||||
typedef double GoFloat64;
|
||||
typedef __complex float GoComplex64;
|
||||
typedef __complex double GoComplex128;
|
||||
|
||||
typedef struct { char *p; int n; } GoString;
|
||||
typedef void *GoMap;
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
# Copyright 2012 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.
|
||||
|
||||
include ../../Make.dist
|
||||
@@ -1,34 +0,0 @@
|
||||
// Copyright 2009 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.
|
||||
|
||||
/*
|
||||
|
||||
Cov is a rudimentary code coverage tool.
|
||||
|
||||
Usage:
|
||||
go tool cov [-lsv] [-g substring] [-m minlines] [6.out args]
|
||||
|
||||
Given a command to run, it runs the command while tracking which
|
||||
sections of code have been executed. When the command finishes,
|
||||
cov prints the line numbers of sections of code in the binary that
|
||||
were not executed. With no arguments it assumes the command "6.out".
|
||||
|
||||
|
||||
The options are:
|
||||
|
||||
-l
|
||||
print full path names instead of paths relative to the current directory
|
||||
-s
|
||||
show the source code that didn't execute, in addition to the line numbers.
|
||||
-v
|
||||
print debugging information during the run.
|
||||
-g substring
|
||||
restrict the coverage analysis to functions or files whose names contain substring
|
||||
-m minlines
|
||||
only report uncovered sections of code larger than minlines lines
|
||||
|
||||
The program is the same for all architectures: 386, amd64, and arm.
|
||||
|
||||
*/
|
||||
package documentation
|
||||
@@ -1,480 +0,0 @@
|
||||
// Copyright 2009 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.
|
||||
|
||||
/*
|
||||
* code coverage
|
||||
*/
|
||||
|
||||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <bio.h>
|
||||
#include "tree.h"
|
||||
|
||||
#include <ureg_amd64.h>
|
||||
#include <mach.h>
|
||||
typedef struct Ureg Ureg;
|
||||
|
||||
void
|
||||
usage(void)
|
||||
{
|
||||
fprint(2, "usage: cov [-lsv] [-g substring] [-m minlines] [6.out args...]\n");
|
||||
fprint(2, "-g specifies pattern of interesting functions or files\n");
|
||||
exits("usage");
|
||||
}
|
||||
|
||||
typedef struct Range Range;
|
||||
struct Range
|
||||
{
|
||||
uvlong pc;
|
||||
uvlong epc;
|
||||
};
|
||||
|
||||
int chatty;
|
||||
int fd;
|
||||
int longnames;
|
||||
int pid;
|
||||
int doshowsrc;
|
||||
Map *mem;
|
||||
Map *text;
|
||||
Fhdr fhdr;
|
||||
char *substring;
|
||||
char cwd[1000];
|
||||
int ncwd;
|
||||
int minlines = -1000;
|
||||
|
||||
Tree breakpoints; // code ranges not run
|
||||
|
||||
/*
|
||||
* comparison for Range structures
|
||||
* they are "equal" if they overlap, so
|
||||
* that a search for [pc, pc+1) finds the
|
||||
* Range containing pc.
|
||||
*/
|
||||
int
|
||||
rangecmp(void *va, void *vb)
|
||||
{
|
||||
Range *a = va, *b = vb;
|
||||
if(a->epc <= b->pc)
|
||||
return 1;
|
||||
if(b->epc <= a->pc)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* remember that we ran the section of code [pc, epc).
|
||||
*/
|
||||
void
|
||||
ran(uvlong pc, uvlong epc)
|
||||
{
|
||||
Range key;
|
||||
Range *r;
|
||||
uvlong oldepc;
|
||||
|
||||
if(chatty)
|
||||
print("run %#llux-%#llux\n", pc, epc);
|
||||
|
||||
key.pc = pc;
|
||||
key.epc = pc+1;
|
||||
r = treeget(&breakpoints, &key);
|
||||
if(r == nil)
|
||||
sysfatal("unchecked breakpoint at %#llux+%d", pc, (int)(epc-pc));
|
||||
|
||||
// Might be that the tail of the sequence
|
||||
// was run already, so r->epc is before the end.
|
||||
// Adjust len.
|
||||
if(epc > r->epc)
|
||||
epc = r->epc;
|
||||
|
||||
if(r->pc == pc) {
|
||||
r->pc = epc;
|
||||
} else {
|
||||
// Chop r to before pc;
|
||||
// add new entry for after if needed.
|
||||
// Changing r->epc does not affect r's position in the tree.
|
||||
oldepc = r->epc;
|
||||
r->epc = pc;
|
||||
if(epc < oldepc) {
|
||||
Range *n;
|
||||
n = malloc(sizeof *n);
|
||||
n->pc = epc;
|
||||
n->epc = oldepc;
|
||||
treeput(&breakpoints, n, n);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
showsrc(char *file, int line1, int line2)
|
||||
{
|
||||
Biobuf *b;
|
||||
char *p;
|
||||
int n, stop;
|
||||
|
||||
if((b = Bopen(file, OREAD)) == nil) {
|
||||
print("\topen %s: %r\n", file);
|
||||
return;
|
||||
}
|
||||
|
||||
for(n=1; n<line1 && (p = Brdstr(b, '\n', 1)) != nil; n++)
|
||||
free(p);
|
||||
|
||||
// print up to five lines (this one and 4 more).
|
||||
// if there are more than five lines, print 4 and "..."
|
||||
stop = n+4;
|
||||
if(stop > line2)
|
||||
stop = line2;
|
||||
if(stop < line2)
|
||||
stop--;
|
||||
for(; n<=stop && (p = Brdstr(b, '\n', 1)) != nil; n++) {
|
||||
print(" %d %s\n", n, p);
|
||||
free(p);
|
||||
}
|
||||
if(n < line2)
|
||||
print(" ...\n");
|
||||
Bterm(b);
|
||||
}
|
||||
|
||||
/*
|
||||
* if s is in the current directory or below,
|
||||
* return the relative path.
|
||||
*/
|
||||
char*
|
||||
shortname(char *s)
|
||||
{
|
||||
if(!longnames && strlen(s) > ncwd && memcmp(s, cwd, ncwd) == 0 && s[ncwd] == '/')
|
||||
return s+ncwd+1;
|
||||
return s;
|
||||
}
|
||||
|
||||
/*
|
||||
* we've decided that [pc, epc) did not run.
|
||||
* do something about it.
|
||||
*/
|
||||
void
|
||||
missing(uvlong pc, uvlong epc)
|
||||
{
|
||||
char file[1000];
|
||||
int line1, line2;
|
||||
char buf[100];
|
||||
Symbol s;
|
||||
char *p;
|
||||
uvlong uv;
|
||||
|
||||
if(!findsym(pc, CTEXT, &s) || !fileline(file, sizeof file, pc)) {
|
||||
notfound:
|
||||
print("%#llux-%#llux\n", pc, epc);
|
||||
return;
|
||||
}
|
||||
p = strrchr(file, ':');
|
||||
*p++ = 0;
|
||||
line1 = atoi(p);
|
||||
for(uv=pc; uv<epc; ) {
|
||||
if(!fileline(file, sizeof file, epc-2))
|
||||
goto notfound;
|
||||
uv += machdata->instsize(text, uv);
|
||||
}
|
||||
p = strrchr(file, ':');
|
||||
*p++ = 0;
|
||||
line2 = atoi(p);
|
||||
|
||||
if(line2+1-line2 < minlines)
|
||||
return;
|
||||
|
||||
if(pc == s.value) {
|
||||
// never entered function
|
||||
print("%s:%d %s never called (%#llux-%#llux)\n", shortname(file), line1, s.name, pc, epc);
|
||||
return;
|
||||
}
|
||||
if(pc <= s.value+13) {
|
||||
// probably stub for stack growth.
|
||||
// check whether last instruction is call to morestack.
|
||||
// the -5 below is the length of
|
||||
// CALL sys.morestack.
|
||||
buf[0] = 0;
|
||||
machdata->das(text, epc-5, 0, buf, sizeof buf);
|
||||
if(strstr(buf, "morestack"))
|
||||
return;
|
||||
}
|
||||
|
||||
if(epc - pc == 5) {
|
||||
// check for CALL sys.panicindex
|
||||
buf[0] = 0;
|
||||
machdata->das(text, pc, 0, buf, sizeof buf);
|
||||
if(strstr(buf, "panicindex"))
|
||||
return;
|
||||
}
|
||||
|
||||
if(epc - pc == 2 || epc -pc == 3) {
|
||||
// check for XORL inside shift.
|
||||
// (on x86 have to implement large left or unsigned right shift with explicit zeroing).
|
||||
// f+90 0x00002c9f CMPL CX,$20
|
||||
// f+93 0x00002ca2 JCS f+97(SB)
|
||||
// f+95 0x00002ca4 XORL AX,AX <<<
|
||||
// f+97 0x00002ca6 SHLL CL,AX
|
||||
// f+99 0x00002ca8 MOVL $1,CX
|
||||
//
|
||||
// f+c8 0x00002cd7 CMPL CX,$40
|
||||
// f+cb 0x00002cda JCS f+d0(SB)
|
||||
// f+cd 0x00002cdc XORQ AX,AX <<<
|
||||
// f+d0 0x00002cdf SHLQ CL,AX
|
||||
// f+d3 0x00002ce2 MOVQ $1,CX
|
||||
buf[0] = 0;
|
||||
machdata->das(text, pc, 0, buf, sizeof buf);
|
||||
if(strncmp(buf, "XOR", 3) == 0) {
|
||||
machdata->das(text, epc, 0, buf, sizeof buf);
|
||||
if(strncmp(buf, "SHL", 3) == 0 || strncmp(buf, "SHR", 3) == 0)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(epc - pc == 3) {
|
||||
// check for SAR inside shift.
|
||||
// (on x86 have to implement large signed right shift as >>31).
|
||||
// f+36 0x00016216 CMPL CX,$20
|
||||
// f+39 0x00016219 JCS f+3e(SB)
|
||||
// f+3b 0x0001621b SARL $1f,AX <<<
|
||||
// f+3e 0x0001621e SARL CL,AX
|
||||
// f+40 0x00016220 XORL CX,CX
|
||||
// f+42 0x00016222 CMPL CX,AX
|
||||
buf[0] = 0;
|
||||
machdata->das(text, pc, 0, buf, sizeof buf);
|
||||
if(strncmp(buf, "SAR", 3) == 0) {
|
||||
machdata->das(text, epc, 0, buf, sizeof buf);
|
||||
if(strncmp(buf, "SAR", 3) == 0)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// show first instruction to make clear where we were.
|
||||
machdata->das(text, pc, 0, buf, sizeof buf);
|
||||
|
||||
if(line1 != line2)
|
||||
print("%s:%d,%d %#llux-%#llux %s\n",
|
||||
shortname(file), line1, line2, pc, epc, buf);
|
||||
else
|
||||
print("%s:%d %#llux-%#llux %s\n",
|
||||
shortname(file), line1, pc, epc, buf);
|
||||
if(doshowsrc)
|
||||
showsrc(file, line1, line2);
|
||||
}
|
||||
|
||||
/*
|
||||
* walk the tree, calling missing for each non-empty
|
||||
* section of missing code.
|
||||
*/
|
||||
void
|
||||
walktree(TreeNode *t)
|
||||
{
|
||||
Range *n;
|
||||
|
||||
if(t == nil)
|
||||
return;
|
||||
walktree(t->left);
|
||||
n = t->key;
|
||||
if(n->pc < n->epc)
|
||||
missing(n->pc, n->epc);
|
||||
walktree(t->right);
|
||||
}
|
||||
|
||||
/*
|
||||
* set a breakpoint all over [pc, epc)
|
||||
* and remember that we did.
|
||||
*/
|
||||
void
|
||||
breakpoint(uvlong pc, uvlong epc)
|
||||
{
|
||||
Range *r;
|
||||
|
||||
r = malloc(sizeof *r);
|
||||
r->pc = pc;
|
||||
r->epc = epc;
|
||||
treeput(&breakpoints, r, r);
|
||||
|
||||
for(; pc < epc; pc+=machdata->bpsize)
|
||||
put1(mem, pc, machdata->bpinst, machdata->bpsize);
|
||||
}
|
||||
|
||||
/*
|
||||
* install breakpoints over all text symbols
|
||||
* that match the pattern.
|
||||
*/
|
||||
void
|
||||
cover(void)
|
||||
{
|
||||
Symbol s;
|
||||
char *lastfn;
|
||||
uvlong lastpc;
|
||||
int i;
|
||||
char buf[200];
|
||||
|
||||
lastfn = nil;
|
||||
lastpc = 0;
|
||||
for(i=0; textsym(&s, i); i++) {
|
||||
switch(s.type) {
|
||||
case 'T':
|
||||
case 't':
|
||||
if(lastpc != 0) {
|
||||
breakpoint(lastpc, s.value);
|
||||
lastpc = 0;
|
||||
}
|
||||
// Ignore second entry for a given name;
|
||||
// that's the debugging blob.
|
||||
if(lastfn && strcmp(s.name, lastfn) == 0)
|
||||
break;
|
||||
lastfn = s.name;
|
||||
buf[0] = 0;
|
||||
fileline(buf, sizeof buf, s.value);
|
||||
if(substring == nil || strstr(buf, substring) || strstr(s.name, substring))
|
||||
lastpc = s.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uvlong
|
||||
rgetzero(Map *map, char *reg)
|
||||
{
|
||||
USED(map);
|
||||
USED(reg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* remove the breakpoints at pc and successive instructions,
|
||||
* up to and including the first jump or other control flow transfer.
|
||||
*/
|
||||
void
|
||||
uncover(uvlong pc)
|
||||
{
|
||||
uchar buf[1000];
|
||||
int n, n1, n2;
|
||||
uvlong foll[2];
|
||||
|
||||
// Double-check that we stopped at a breakpoint.
|
||||
if(get1(mem, pc, buf, machdata->bpsize) < 0)
|
||||
sysfatal("read mem inst at %#llux: %r", pc);
|
||||
if(memcmp(buf, machdata->bpinst, machdata->bpsize) != 0)
|
||||
sysfatal("stopped at %#llux; not at breakpoint %d", pc, machdata->bpsize);
|
||||
|
||||
// Figure out how many bytes of straight-line code
|
||||
// there are in the text starting at pc.
|
||||
n = 0;
|
||||
while(n < sizeof buf) {
|
||||
n1 = machdata->instsize(text, pc+n);
|
||||
if(n+n1 > sizeof buf)
|
||||
break;
|
||||
n2 = machdata->foll(text, pc+n, rgetzero, foll);
|
||||
n += n1;
|
||||
if(n2 != 1 || foll[0] != pc+n)
|
||||
break;
|
||||
}
|
||||
|
||||
// Record that this section of code ran.
|
||||
ran(pc, pc+n);
|
||||
|
||||
// Put original instructions back.
|
||||
if(get1(text, pc, buf, n) < 0)
|
||||
sysfatal("get1: %r");
|
||||
if(put1(mem, pc, buf, n) < 0)
|
||||
sysfatal("put1: %r");
|
||||
}
|
||||
|
||||
int
|
||||
startprocess(char **argv)
|
||||
{
|
||||
int pid;
|
||||
|
||||
if((pid = fork()) < 0)
|
||||
sysfatal("fork: %r");
|
||||
if(pid == 0) {
|
||||
pid = getpid();
|
||||
if(ctlproc(pid, "hang") < 0)
|
||||
sysfatal("ctlproc hang: %r");
|
||||
exec(argv[0], argv);
|
||||
sysfatal("exec %s: %r", argv[0]);
|
||||
}
|
||||
if(ctlproc(pid, "attached") < 0 || ctlproc(pid, "waitstop") < 0)
|
||||
sysfatal("attach %d %s: %r", pid, argv[0]);
|
||||
return pid;
|
||||
}
|
||||
|
||||
int
|
||||
go(void)
|
||||
{
|
||||
uvlong pc;
|
||||
char buf[100];
|
||||
int n;
|
||||
|
||||
for(n = 0;; n++) {
|
||||
ctlproc(pid, "startstop");
|
||||
if(get8(mem, offsetof(Ureg, ip), &pc) < 0) {
|
||||
rerrstr(buf, sizeof buf);
|
||||
if(strstr(buf, "exited") || strstr(buf, "No such process"))
|
||||
return n;
|
||||
sysfatal("cannot read pc: %r");
|
||||
}
|
||||
pc--;
|
||||
if(put8(mem, offsetof(Ureg, ip), pc) < 0)
|
||||
sysfatal("cannot write pc: %r");
|
||||
uncover(pc);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int n;
|
||||
|
||||
ARGBEGIN{
|
||||
case 'g':
|
||||
substring = EARGF(usage());
|
||||
break;
|
||||
case 'l':
|
||||
longnames++;
|
||||
break;
|
||||
case 'n':
|
||||
minlines = atoi(EARGF(usage()));
|
||||
break;
|
||||
case 's':
|
||||
doshowsrc = 1;
|
||||
break;
|
||||
case 'v':
|
||||
chatty++;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}ARGEND
|
||||
|
||||
getwd(cwd, sizeof cwd);
|
||||
ncwd = strlen(cwd);
|
||||
|
||||
if(argc == 0) {
|
||||
*--argv = "6.out";
|
||||
}
|
||||
fd = open(argv[0], OREAD);
|
||||
if(fd < 0)
|
||||
sysfatal("open %s: %r", argv[0]);
|
||||
if(crackhdr(fd, &fhdr) <= 0)
|
||||
sysfatal("crackhdr: %r");
|
||||
machbytype(fhdr.type);
|
||||
if(syminit(fd, &fhdr) <= 0)
|
||||
sysfatal("syminit: %r");
|
||||
text = loadmap(nil, fd, &fhdr);
|
||||
if(text == nil)
|
||||
sysfatal("loadmap: %r");
|
||||
pid = startprocess(argv);
|
||||
mem = attachproc(pid, &fhdr);
|
||||
if(mem == nil)
|
||||
sysfatal("attachproc: %r");
|
||||
breakpoints.cmp = rangecmp;
|
||||
cover();
|
||||
n = go();
|
||||
walktree(breakpoints.root);
|
||||
if(chatty)
|
||||
print("%d breakpoints\n", n);
|
||||
detachproc(mem);
|
||||
exits(0);
|
||||
}
|
||||
|
||||
@@ -1,243 +0,0 @@
|
||||
// Renamed from Map to Tree to avoid conflict with libmach.
|
||||
|
||||
/*
|
||||
Copyright (c) 2003-2007 Russ Cox, Tom Bergan, Austin Clements,
|
||||
Massachusetts Institute of Technology
|
||||
Portions Copyright (c) 2009 The Go Authors. All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
// Mutable map structure, but still based on
|
||||
// Okasaki, Red Black Trees in a Functional Setting, JFP 1999,
|
||||
// which is a lot easier than the traditional red-black
|
||||
// and plenty fast enough for me. (Also I could copy
|
||||
// and edit fmap.c.)
|
||||
|
||||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include "tree.h"
|
||||
|
||||
enum
|
||||
{
|
||||
Red = 0,
|
||||
Black = 1
|
||||
};
|
||||
|
||||
|
||||
// Red-black trees are binary trees with this property:
|
||||
// 1. No red node has a red parent.
|
||||
// 2. Every path from the root to a leaf contains the
|
||||
// same number of black nodes.
|
||||
|
||||
static TreeNode*
|
||||
rwTreeNode(TreeNode *p, int color, TreeNode *left, void *key, void *value, TreeNode *right)
|
||||
{
|
||||
if(p == nil)
|
||||
p = malloc(sizeof *p);
|
||||
p->color = color;
|
||||
p->left = left;
|
||||
p->key = key;
|
||||
p->value = value;
|
||||
p->right = right;
|
||||
return p;
|
||||
}
|
||||
|
||||
static TreeNode*
|
||||
balance(TreeNode *m0)
|
||||
{
|
||||
void *xk, *xv, *yk, *yv, *zk, *zv;
|
||||
TreeNode *a, *b, *c, *d;
|
||||
TreeNode *m1, *m2;
|
||||
int color;
|
||||
TreeNode *left, *right;
|
||||
void *key, *value;
|
||||
|
||||
color = m0->color;
|
||||
left = m0->left;
|
||||
key = m0->key;
|
||||
value = m0->value;
|
||||
right = m0->right;
|
||||
|
||||
// Okasaki notation: (T is mkTreeNode, B is Black, R is Red, x, y, z are key-value.
|
||||
//
|
||||
// balance B (T R (T R a x b) y c) z d
|
||||
// balance B (T R a x (T R b y c)) z d
|
||||
// balance B a x (T R (T R b y c) z d)
|
||||
// balance B a x (T R b y (T R c z d))
|
||||
//
|
||||
// = T R (T B a x b) y (T B c z d)
|
||||
|
||||
if(color == Black){
|
||||
if(left && left->color == Red){
|
||||
if(left->left && left->left->color == Red){
|
||||
a = left->left->left;
|
||||
xk = left->left->key;
|
||||
xv = left->left->value;
|
||||
b = left->left->right;
|
||||
yk = left->key;
|
||||
yv = left->value;
|
||||
c = left->right;
|
||||
zk = key;
|
||||
zv = value;
|
||||
d = right;
|
||||
m1 = left;
|
||||
m2 = left->left;
|
||||
goto hard;
|
||||
}else if(left->right && left->right->color == Red){
|
||||
a = left->left;
|
||||
xk = left->key;
|
||||
xv = left->value;
|
||||
b = left->right->left;
|
||||
yk = left->right->key;
|
||||
yv = left->right->value;
|
||||
c = left->right->right;
|
||||
zk = key;
|
||||
zv = value;
|
||||
d = right;
|
||||
m1 = left;
|
||||
m2 = left->right;
|
||||
goto hard;
|
||||
}
|
||||
}else if(right && right->color == Red){
|
||||
if(right->left && right->left->color == Red){
|
||||
a = left;
|
||||
xk = key;
|
||||
xv = value;
|
||||
b = right->left->left;
|
||||
yk = right->left->key;
|
||||
yv = right->left->value;
|
||||
c = right->left->right;
|
||||
zk = right->key;
|
||||
zv = right->value;
|
||||
d = right->right;
|
||||
m1 = right;
|
||||
m2 = right->left;
|
||||
goto hard;
|
||||
}else if(right->right && right->right->color == Red){
|
||||
a = left;
|
||||
xk = key;
|
||||
xv = value;
|
||||
b = right->left;
|
||||
yk = right->key;
|
||||
yv = right->value;
|
||||
c = right->right->left;
|
||||
zk = right->right->key;
|
||||
zv = right->right->value;
|
||||
d = right->right->right;
|
||||
m1 = right;
|
||||
m2 = right->right;
|
||||
goto hard;
|
||||
}
|
||||
}
|
||||
}
|
||||
return rwTreeNode(m0, color, left, key, value, right);
|
||||
|
||||
hard:
|
||||
return rwTreeNode(m0, Red, rwTreeNode(m1, Black, a, xk, xv, b),
|
||||
yk, yv, rwTreeNode(m2, Black, c, zk, zv, d));
|
||||
}
|
||||
|
||||
static TreeNode*
|
||||
ins0(TreeNode *p, void *k, void *v, TreeNode *rw)
|
||||
{
|
||||
if(p == nil)
|
||||
return rwTreeNode(rw, Red, nil, k, v, nil);
|
||||
if(p->key == k){
|
||||
if(rw)
|
||||
return rwTreeNode(rw, p->color, p->left, k, v, p->right);
|
||||
p->value = v;
|
||||
return p;
|
||||
}
|
||||
if(p->key < k)
|
||||
p->left = ins0(p->left, k, v, rw);
|
||||
else
|
||||
p->right = ins0(p->right, k, v, rw);
|
||||
return balance(p);
|
||||
}
|
||||
|
||||
static TreeNode*
|
||||
ins1(Tree *m, TreeNode *p, void *k, void *v, TreeNode *rw)
|
||||
{
|
||||
int i;
|
||||
|
||||
if(p == nil)
|
||||
return rwTreeNode(rw, Red, nil, k, v, nil);
|
||||
i = m->cmp(p->key, k);
|
||||
if(i == 0){
|
||||
if(rw)
|
||||
return rwTreeNode(rw, p->color, p->left, k, v, p->right);
|
||||
p->value = v;
|
||||
return p;
|
||||
}
|
||||
if(i < 0)
|
||||
p->left = ins1(m, p->left, k, v, rw);
|
||||
else
|
||||
p->right = ins1(m, p->right, k, v, rw);
|
||||
return balance(p);
|
||||
}
|
||||
|
||||
void
|
||||
treeputelem(Tree *m, void *key, void *val, TreeNode *rw)
|
||||
{
|
||||
if(m->cmp)
|
||||
m->root = ins1(m, m->root, key, val, rw);
|
||||
else
|
||||
m->root = ins0(m->root, key, val, rw);
|
||||
}
|
||||
|
||||
void
|
||||
treeput(Tree *m, void *key, void *val)
|
||||
{
|
||||
treeputelem(m, key, val, nil);
|
||||
}
|
||||
|
||||
void*
|
||||
treeget(Tree *m, void *key)
|
||||
{
|
||||
int i;
|
||||
TreeNode *p;
|
||||
|
||||
p = m->root;
|
||||
if(m->cmp){
|
||||
for(;;){
|
||||
if(p == nil)
|
||||
return nil;
|
||||
i = m->cmp(p->key, key);
|
||||
if(i < 0)
|
||||
p = p->left;
|
||||
else if(i > 0)
|
||||
p = p->right;
|
||||
else
|
||||
return p->value;
|
||||
}
|
||||
}else{
|
||||
for(;;){
|
||||
if(p == nil)
|
||||
return nil;
|
||||
if(p->key == key)
|
||||
return p->value;
|
||||
if(p->key < key)
|
||||
p = p->left;
|
||||
else
|
||||
p = p->right;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
// Renamed from Map to Tree to avoid conflict with libmach.
|
||||
|
||||
/*
|
||||
Copyright (c) 2003-2007 Russ Cox, Tom Bergan, Austin Clements,
|
||||
Massachusetts Institute of Technology
|
||||
Portions Copyright (c) 2009 The Go Authors. All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
typedef struct Tree Tree;
|
||||
typedef struct TreeNode TreeNode;
|
||||
struct Tree
|
||||
{
|
||||
int (*cmp)(void*, void*);
|
||||
TreeNode *root;
|
||||
};
|
||||
|
||||
struct TreeNode
|
||||
{
|
||||
int color;
|
||||
TreeNode *left;
|
||||
void *key;
|
||||
void *value;
|
||||
TreeNode *right;
|
||||
};
|
||||
|
||||
void *treeget(Tree*, void*);
|
||||
void treeput(Tree*, void*, void*);
|
||||
void treeputelem(Tree*, void*, void*, TreeNode*);
|
||||
24
src/cmd/dist/build.c
vendored
24
src/cmd/dist/build.c
vendored
@@ -19,7 +19,7 @@ char *goos;
|
||||
char *goroot = GOROOT_FINAL;
|
||||
char *goroot_final = GOROOT_FINAL;
|
||||
char *workdir;
|
||||
char *tooldir;
|
||||
char *tooldir;
|
||||
char *gochar;
|
||||
char *goversion;
|
||||
char *slash; // / for unix, \ for windows
|
||||
@@ -1230,6 +1230,15 @@ clean(void)
|
||||
xremove(bpathf(&b, "%s/%s", bstr(&path), cleantab[i]+4));
|
||||
}
|
||||
|
||||
// remove src/pkg/runtime/z* unconditionally
|
||||
vreset(&dir);
|
||||
bpathf(&path, "%s/src/pkg/runtime", goroot);
|
||||
xreaddir(&dir, bstr(&path));
|
||||
for(j=0; j<dir.len; j++) {
|
||||
if(hasprefix(dir.p[j], "z"))
|
||||
xremove(bpathf(&b, "%s/%s", bstr(&path), dir.p[j]));
|
||||
}
|
||||
|
||||
if(rebuildall) {
|
||||
// Remove object tree.
|
||||
xremoveall(bpathf(&b, "%s/pkg/obj/%s_%s", goroot, gohostos, gohostarch));
|
||||
@@ -1292,7 +1301,7 @@ cmdenv(int argc, char **argv)
|
||||
vflag++;
|
||||
break;
|
||||
case 'w':
|
||||
format = "set %s=%s\n";
|
||||
format = "set %s=%s\r\n";
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
@@ -1462,7 +1471,7 @@ void
|
||||
cmdbanner(int argc, char **argv)
|
||||
{
|
||||
char *pathsep;
|
||||
Buf b, b1, search;
|
||||
Buf b, b1, search, path;
|
||||
|
||||
ARGBEGIN{
|
||||
case 'v':
|
||||
@@ -1478,6 +1487,7 @@ cmdbanner(int argc, char **argv)
|
||||
binit(&b);
|
||||
binit(&b1);
|
||||
binit(&search);
|
||||
binit(&path);
|
||||
|
||||
xprintf("\n");
|
||||
xprintf("---\n");
|
||||
@@ -1495,9 +1505,10 @@ cmdbanner(int argc, char **argv)
|
||||
xprintf("*** You need to add %s to your PATH.\n", gobin);
|
||||
|
||||
if(streq(gohostos, "darwin")) {
|
||||
xprintf("\n"
|
||||
"On OS X the debuggers must be installed setgid procmod.\n"
|
||||
"Read and run ./sudo.bash to install the debuggers.\n");
|
||||
if(isfile(bpathf(&path, "%s/cov", tooldir)))
|
||||
xprintf("\n"
|
||||
"On OS X the debuggers must be installed setgid procmod.\n"
|
||||
"Read and run ./sudo.bash to install the debuggers.\n");
|
||||
}
|
||||
|
||||
if(!streq(goroot_final, goroot)) {
|
||||
@@ -1509,6 +1520,7 @@ cmdbanner(int argc, char **argv)
|
||||
bfree(&b);
|
||||
bfree(&b1);
|
||||
bfree(&search);
|
||||
bfree(&path);
|
||||
}
|
||||
|
||||
// Version prints the Go version.
|
||||
|
||||
18
src/cmd/dist/windows.c
vendored
18
src/cmd/dist/windows.c
vendored
@@ -121,6 +121,22 @@ errstr(void)
|
||||
return bstr(&b); // leak but we're dying anyway
|
||||
}
|
||||
|
||||
static void
|
||||
errprintf(char *fmt, ...) {
|
||||
va_list arg;
|
||||
char *p;
|
||||
DWORD n, w;
|
||||
|
||||
va_start(arg, fmt);
|
||||
n = vsnprintf(NULL, 0, fmt, arg);
|
||||
p = xmalloc(n+1);
|
||||
vsnprintf(p, n+1, fmt, arg);
|
||||
va_end(arg);
|
||||
w = 0;
|
||||
WriteFile(GetStdHandle(STD_ERROR_HANDLE), p, n, &w, 0);
|
||||
xfree(p);
|
||||
}
|
||||
|
||||
void
|
||||
xgetenv(Buf *b, char *name)
|
||||
{
|
||||
@@ -707,7 +723,7 @@ fatal(char *msg, ...)
|
||||
vsnprintf(buf1, sizeof buf1, msg, arg);
|
||||
va_end(arg);
|
||||
|
||||
xprintf("go tool dist: %s\n", buf1);
|
||||
errprintf("go tool dist: %s\n", buf1);
|
||||
|
||||
bgwait();
|
||||
ExitProcess(1);
|
||||
|
||||
@@ -1012,12 +1012,13 @@ defaultlit(Node **np, Type *t)
|
||||
}
|
||||
n->type = t;
|
||||
return;
|
||||
case OCOM:
|
||||
case ONOT:
|
||||
defaultlit(&n->left, t);
|
||||
n->type = n->left->type;
|
||||
return;
|
||||
default:
|
||||
if(n->left == N) {
|
||||
if(n->left == N || n->right == N) {
|
||||
dump("defaultlit", n);
|
||||
fatal("defaultlit");
|
||||
}
|
||||
|
||||
@@ -432,21 +432,6 @@ oldname(Sym *s)
|
||||
return n;
|
||||
}
|
||||
|
||||
/*
|
||||
* same for types
|
||||
*/
|
||||
Type*
|
||||
newtype(Sym *s)
|
||||
{
|
||||
Type *t;
|
||||
|
||||
t = typ(TFORW);
|
||||
t->sym = s;
|
||||
t->type = T;
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* := declarations
|
||||
*/
|
||||
@@ -479,7 +464,7 @@ colasdefn(NodeList *left, Node *defn)
|
||||
if(isblank(n))
|
||||
continue;
|
||||
if(!colasname(n)) {
|
||||
yyerror("non-name %N on left side of :=", n);
|
||||
yyerrorl(defn->lineno, "non-name %N on left side of :=", n);
|
||||
nerr++;
|
||||
continue;
|
||||
}
|
||||
@@ -494,11 +479,11 @@ colasdefn(NodeList *left, Node *defn)
|
||||
l->n = n;
|
||||
}
|
||||
if(nnew == 0 && nerr == 0)
|
||||
yyerror("no new variables on left side of :=");
|
||||
yyerrorl(defn->lineno, "no new variables on left side of :=");
|
||||
}
|
||||
|
||||
Node*
|
||||
colas(NodeList *left, NodeList *right)
|
||||
colas(NodeList *left, NodeList *right, int32 lno)
|
||||
{
|
||||
Node *as;
|
||||
|
||||
@@ -506,6 +491,7 @@ colas(NodeList *left, NodeList *right)
|
||||
as->list = left;
|
||||
as->rlist = right;
|
||||
as->colas = 1;
|
||||
as->lineno = lno;
|
||||
colasdefn(left, as);
|
||||
|
||||
// make the tree prettier; not necessary
|
||||
@@ -1311,7 +1297,7 @@ addmethod(Sym *sf, Type *t, int local)
|
||||
}
|
||||
// Should have picked off all the reasons above,
|
||||
// but just in case, fall back to generic error.
|
||||
yyerror("invalid receiver type %T", pa);
|
||||
yyerror("invalid receiver type %T (%lT / %lT)", pa, pa, t);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -47,7 +47,9 @@ Flags:
|
||||
-N
|
||||
disable optimizations
|
||||
-S
|
||||
write assembly language text to standard output
|
||||
write assembly language text to standard output (code only)
|
||||
-SS
|
||||
write assembly language text to standard output (code and data)
|
||||
-u
|
||||
disallow importing packages not marked as safe
|
||||
-V
|
||||
|
||||
@@ -131,13 +131,21 @@ escfunc(Node *func)
|
||||
}
|
||||
|
||||
// walk will take the address of cvar->closure later and assign it to cvar.
|
||||
// handle that here by linking a fake oaddr node directly to the closure.
|
||||
// linking a fake oaddr node directly to the closure handles the case
|
||||
// of the closure itself leaking. Following the flow of the value to th
|
||||
// paramref is done in escflow, because if we did that here, it would look
|
||||
// like the original is assigned out of its loop depth, whereas it's just
|
||||
// assigned to something in an inner function. A paramref itself is never
|
||||
// moved to the heap, only its original.
|
||||
for(ll=curfn->cvars; ll; ll=ll->next) {
|
||||
if(ll->n->op == OXXX) // see dcl.c:398
|
||||
continue;
|
||||
|
||||
n = nod(OADDR, ll->n->closure, N);
|
||||
n->lineno = ll->n->lineno;
|
||||
// n belongs to the outer scope.
|
||||
n->escloopdepth = saveld;
|
||||
n->curfn = savefn;
|
||||
typecheck(&n, Erv);
|
||||
escassign(curfn, n);
|
||||
}
|
||||
@@ -221,16 +229,19 @@ esc(Node *n)
|
||||
if(n->op == OFOR || n->op == ORANGE)
|
||||
loopdepth++;
|
||||
|
||||
esc(n->left);
|
||||
esc(n->right);
|
||||
esc(n->ntest);
|
||||
esc(n->nincr);
|
||||
esclist(n->ninit);
|
||||
esclist(n->nbody);
|
||||
esclist(n->nelse);
|
||||
esclist(n->list);
|
||||
esclist(n->rlist);
|
||||
|
||||
if(n->op == OCLOSURE) {
|
||||
escfunc(n);
|
||||
} else {
|
||||
esc(n->left);
|
||||
esc(n->right);
|
||||
esc(n->ntest);
|
||||
esc(n->nincr);
|
||||
esclist(n->ninit);
|
||||
esclist(n->nbody);
|
||||
esclist(n->nelse);
|
||||
esclist(n->list);
|
||||
esclist(n->rlist);
|
||||
}
|
||||
if(n->op == OFOR || n->op == ORANGE)
|
||||
loopdepth--;
|
||||
|
||||
@@ -379,8 +390,8 @@ esc(Node *n)
|
||||
}
|
||||
break;
|
||||
|
||||
case OADDR:
|
||||
case OCLOSURE:
|
||||
case OADDR:
|
||||
case OMAKECHAN:
|
||||
case OMAKEMAP:
|
||||
case OMAKESLICE:
|
||||
@@ -407,8 +418,8 @@ escassign(Node *dst, Node *src)
|
||||
return;
|
||||
|
||||
if(debug['m'] > 1)
|
||||
print("%L:[%d] %S escassign: %hN = %hN\n", lineno, loopdepth,
|
||||
(curfn && curfn->nname) ? curfn->nname->sym : S, dst, src);
|
||||
print("%L:[%d] %S escassign: %hN(%hJ) = %hN(%hJ)\n", lineno, loopdepth,
|
||||
(curfn && curfn->nname) ? curfn->nname->sym : S, dst, dst, src, src);
|
||||
|
||||
setlineno(dst);
|
||||
|
||||
@@ -467,7 +478,11 @@ escassign(Node *dst, Node *src)
|
||||
case OARRAYLIT:
|
||||
case OMAPLIT:
|
||||
case OSTRUCTLIT:
|
||||
// loopdepth was set in the defining statement or function header
|
||||
case OMAKECHAN:
|
||||
case OMAKEMAP:
|
||||
case OMAKESLICE:
|
||||
case ONEW:
|
||||
case OCLOSURE:
|
||||
escflows(dst, src);
|
||||
break;
|
||||
|
||||
@@ -500,18 +515,6 @@ escassign(Node *dst, Node *src)
|
||||
escassign(dst, src->left);
|
||||
break;
|
||||
|
||||
case OMAKECHAN:
|
||||
case OMAKEMAP:
|
||||
case OMAKESLICE:
|
||||
case ONEW:
|
||||
escflows(dst, src);
|
||||
break;
|
||||
|
||||
case OCLOSURE:
|
||||
escflows(dst, src);
|
||||
escfunc(src);
|
||||
break;
|
||||
|
||||
case OADD:
|
||||
case OSUB:
|
||||
case OOR:
|
||||
@@ -543,7 +546,7 @@ escassign(Node *dst, Node *src)
|
||||
// This is a bit messier than fortunate, pulled out of escassign's big
|
||||
// switch for clarity. We either have the paramnodes, which may be
|
||||
// connected to other things throug flows or we have the parameter type
|
||||
// nodes, which may be marked 'n(ofloworescape)'. Navigating the ast is slightly
|
||||
// nodes, which may be marked "noescape". Navigating the ast is slightly
|
||||
// different for methods vs plain functions and for imported vs
|
||||
// this-package
|
||||
static void
|
||||
@@ -711,8 +714,8 @@ escwalk(int level, Node *dst, Node *src)
|
||||
src->walkgen = walkgen;
|
||||
|
||||
if(debug['m']>1)
|
||||
print("escwalk: level:%d depth:%d %.*s %hN scope:%S[%d]\n",
|
||||
level, pdepth, pdepth, "\t\t\t\t\t\t\t\t\t\t", src,
|
||||
print("escwalk: level:%d depth:%d %.*s %hN(%hJ) scope:%S[%d]\n",
|
||||
level, pdepth, pdepth, "\t\t\t\t\t\t\t\t\t\t", src, src,
|
||||
(src->curfn && src->curfn->nname) ? src->curfn->nname->sym : S, src->escloopdepth);
|
||||
|
||||
pdepth++;
|
||||
@@ -726,6 +729,16 @@ escwalk(int level, Node *dst, Node *src)
|
||||
if(debug['m'])
|
||||
warnl(src->lineno, "leaking param: %hN", src);
|
||||
}
|
||||
// handle the missing flow ref <- orig
|
||||
// a paramref is automagically dereferenced, and taking its
|
||||
// address produces the address of the original, so all we have to do here
|
||||
// is keep track of the value flow, so level is unchanged.
|
||||
// alternatively, we could have substituted PPARAMREFs with their ->closure in esc/escassign/flow,
|
||||
if(src->class == PPARAMREF) {
|
||||
if(leaks && debug['m'])
|
||||
warnl(src->lineno, "leaking closure reference %hN", src);
|
||||
escwalk(level, dst, src->closure);
|
||||
}
|
||||
break;
|
||||
|
||||
case OPTRLIT:
|
||||
|
||||
@@ -962,7 +962,6 @@ static int opprec[] = {
|
||||
[OPAREN] = 8,
|
||||
[OPRINTN] = 8,
|
||||
[OPRINT] = 8,
|
||||
[ORECV] = 8,
|
||||
[ORUNESTR] = 8,
|
||||
[OSTRARRAYBYTE] = 8,
|
||||
[OSTRARRAYRUNE] = 8,
|
||||
@@ -994,6 +993,7 @@ static int opprec[] = {
|
||||
[OMINUS] = 7,
|
||||
[OADDR] = 7,
|
||||
[OIND] = 7,
|
||||
[ORECV] = 7,
|
||||
|
||||
[OMUL] = 6,
|
||||
[ODIV] = 6,
|
||||
|
||||
@@ -647,6 +647,9 @@ cgen_as(Node *nl, Node *nr)
|
||||
dump("cgen_as = ", nr);
|
||||
}
|
||||
|
||||
while(nr != N && nr->op == OCONVNOP)
|
||||
nr = nr->left;
|
||||
|
||||
if(nl == N || isblank(nl)) {
|
||||
cgen_discard(nr);
|
||||
return;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user