Commit 163ecdac authored by Rob Pike's avatar Rob Pike

new semicolon rule in effective_go.html.

eliminate all tab characters while we're here.

R=rsc
CC=golang-dev
https://golang.org/cl/180055
parent f64bb56b
...@@ -77,8 +77,8 @@ declaration ...@@ -77,8 +77,8 @@ declaration
<pre> <pre>
type T struct { type T struct {
name string; // name of the object name string // name of the object
value int; // its value value int // its value
} }
</pre> </pre>
...@@ -88,8 +88,8 @@ type T struct { ...@@ -88,8 +88,8 @@ type T struct {
<pre> <pre>
type T struct { type T struct {
name string; // name of the object name string // name of the object
value int; // its value value int // its value
} }
</pre> </pre>
...@@ -228,9 +228,9 @@ Since the whole declaration is presented, such a comment can often be perfunctor ...@@ -228,9 +228,9 @@ Since the whole declaration is presented, such a comment can often be perfunctor
<pre> <pre>
// Error codes returned by failures to parse an expression. // Error codes returned by failures to parse an expression.
var ( var (
ErrInternal = os.NewError("internal error"); ErrInternal = os.NewError("internal error")
ErrUnmatchedLpar = os.NewError("unmatched '('"); ErrUnmatchedLpar = os.NewError("unmatched '('")
ErrUnmatchedRpar = os.NewError("unmatched ')'"); ErrUnmatchedRpar = os.NewError("unmatched ')'")
... ...
) )
</pre> </pre>
...@@ -242,10 +242,10 @@ such as the fact that a set of variables is protected by a mutex. ...@@ -242,10 +242,10 @@ such as the fact that a set of variables is protected by a mutex.
<pre> <pre>
var ( var (
countLock sync.Mutex; countLock sync.Mutex
inputCount uint32; inputCount uint32
outputCount uint32; outputCount uint32
errorCount uint32; errorCount uint32
) )
</pre> </pre>
...@@ -360,50 +360,65 @@ multiword names. ...@@ -360,50 +360,65 @@ multiword names.
<h2 id="semicolons">Semicolons</h2> <h2 id="semicolons">Semicolons</h2>
<p> <p>
Go needs fewer semicolons between statements than do other C variants. Like C, Go's formal grammar uses semicolons to terminate statements;
Semicolons are never required at the top level. unlike C, those semicolons do not appear in the source.
And they are separators, not terminators, so they Instead the lexer uses a simple rule to insert semicolons automatically
can be left off the last element of a statement or declaration list, as it scans, so the input text is mostly free of them.
a convenience
for one-line <code>funcs</code> and the like.
</p> </p>
<p>
The rule is this. If the last token before a newline is an identifier
(which includes words like <code>int</code> and <code>float64</code>),
a basic literal such as a number or string constant, or one of the
tokens
</p>
<pre>
break continue fallthrough return ++ -- ) }
</pre>
<p>
the lexer always inserts a semicolon after the token.
This could be summarized as, &ldquo;if the newline comes
after a token that could end a statement, add a semicolon&rdquo;.
</p>
<p>
A semicolon can also be omitted immediately before a closing brace,
so a statement such as
</p>
<pre> <pre>
func CopyInBackground(dst, src chan Item) {
go func() { for { dst &lt;- &lt;-src } }() go func() { for { dst &lt;- &lt;-src } }()
}
</pre> </pre>
<p>
needs no semicolons.
Idiomatic Go programs have semicolons only in places such as
<code>for</code> loop clauses, to separate the initializer, condition, and
continuation elements. They are also necessary to separate multiple
statements on a line, should you write code that way.
</p>
<p> <p>
In fact, semicolons can be omitted at the end of any "StatementList" in the One caveat. You should never put the opening brace of a
grammar, which includes things like cases in <code>switch</code> control structure (<code>if</code>, <code>for</code>, <code>switch</code>,
statements. or <code>select</code>) on the next line. If you do, a semicolon
will be inserted before the brace, which could cause unwanted
effects. Write them like this
</p> </p>
<pre> <pre>
switch { if i < f() {
case a &lt; b: g()
return -1
case a == b:
return 0
case a &gt; b:
return 1
} }
</pre> </pre>
<p> <p>
The grammar accepts an empty statement after any statement list, which not like this
means a terminal semicolon is always OK. As a result,
it's fine to put semicolons everywhere you'd put them in a
C program—they would be fine after those return statements,
for instance—but they can often be omitted.
By convention, they're always left off top-level declarations (for
instance, they don't appear after the closing brace of <code>struct</code>
declarations, or of <code>funcs</code> for that matter)
and often left off one-liners. But within functions, place them
as you see fit.
</p> </p>
<pre>
if i < f() // wrong!
{ // wrong!
g()
}
</pre>
<h2 id="control-structures">Control structures</h2> <h2 id="control-structures">Control structures</h2>
...@@ -448,8 +463,8 @@ statement, it's common to see one used to set up a local variable. ...@@ -448,8 +463,8 @@ statement, it's common to see one used to set up a local variable.
<pre> <pre>
if err := file.Chmod(0664); err != nil { if err := file.Chmod(0664); err != nil {
log.Stderr(err); log.Stderr(err)
return err; return err
} }
</pre> </pre>
...@@ -462,11 +477,11 @@ the body ends in <code>break</code>, <code>continue</code>, ...@@ -462,11 +477,11 @@ the body ends in <code>break</code>, <code>continue</code>,
</p> </p>
<pre> <pre>
f, err := os.Open(name, os.O_RDONLY, 0); f, err := os.Open(name, os.O_RDONLY, 0)
if err != nil { if err != nil {
return err; return err
} }
codeUsing(f); codeUsing(f)
</pre> </pre>
<p> <p>
...@@ -478,15 +493,15 @@ statements, the resulting code needs no <code>else</code> statements. ...@@ -478,15 +493,15 @@ statements, the resulting code needs no <code>else</code> statements.
</p> </p>
<pre> <pre>
f, err := os.Open(name, os.O_RDONLY, 0); f, err := os.Open(name, os.O_RDONLY, 0)
if err != nil { if err != nil {
return err; return err
} }
d, err := f.Stat(); d, err := f.Stat()
if err != nil { if err != nil {
return err; return err
} }
codeUsing(f, d); codeUsing(f, d)
</pre> </pre>
...@@ -513,7 +528,7 @@ for { } ...@@ -513,7 +528,7 @@ for { }
Short declarations make it easy to declare the index variable right in the loop. Short declarations make it easy to declare the index variable right in the loop.
</p> </p>
<pre> <pre>
sum := 0; sum := 0
for i := 0; i < 10; i++ { for i := 0; i < 10; i++ {
sum += i sum += i
} }
...@@ -525,8 +540,8 @@ or reading from a channel, a <code>range</code> clause can ...@@ -525,8 +540,8 @@ or reading from a channel, a <code>range</code> clause can
manage the loop for you. manage the loop for you.
</p> </p>
<pre> <pre>
var m map[string]int; var m map[string]int
sum := 0; sum := 0
for _, value := range m { // key is unused for _, value := range m { // key is unused
sum += value sum += value
} }
...@@ -639,15 +654,15 @@ have the corresponding type in each clause. ...@@ -639,15 +654,15 @@ have the corresponding type in each clause.
<pre> <pre>
switch t := interfaceValue.(type) { switch t := interfaceValue.(type) {
default: default:
fmt.Printf("unexpected type %T", t); // %T prints type fmt.Printf("unexpected type %T", t) // %T prints type
case bool: case bool:
fmt.Printf("boolean %t\n", t); fmt.Printf("boolean %t\n", t)
case int: case int:
fmt.Printf("integer %d\n", t); fmt.Printf("integer %d\n", t)
case *bool: case *bool:
fmt.Printf("pointer to boolean %t\n", *t); fmt.Printf("pointer to boolean %t\n", *t)
case *int: case *int:
fmt.Printf("pointer to integer %d\n", *t); fmt.Printf("pointer to integer %d\n", *t)
} }
</pre> </pre>
...@@ -695,11 +710,11 @@ and the next position. ...@@ -695,11 +710,11 @@ and the next position.
func nextInt(b []byte, i int) (int, int) { func nextInt(b []byte, i int) (int, int) {
for ; i < len(b) &amp;&amp; !isDigit(b[i]); i++ { for ; i < len(b) &amp;&amp; !isDigit(b[i]); i++ {
} }
x := 0; x := 0
for ; i < len(b) &amp;&amp; isDigit(b[i]); i++ { for ; i < len(b) &amp;&amp; isDigit(b[i]); i++ {
x = x*10 + int(b[i])-'0' x = x*10 + int(b[i])-'0'
} }
return x, i; return x, i
} }
</pre> </pre>
...@@ -709,8 +724,8 @@ You could use it to scan the numbers in an input array <code>a</code> like this: ...@@ -709,8 +724,8 @@ You could use it to scan the numbers in an input array <code>a</code> like this:
<pre> <pre>
for i := 0; i < len(a); { for i := 0; i < len(a); {
x, i = nextInt(a, i); x, i = nextInt(a, i)
fmt.Println(x); fmt.Println(x)
} }
</pre> </pre>
...@@ -746,12 +761,12 @@ of <code>io.ReadFull</code> that uses them well: ...@@ -746,12 +761,12 @@ of <code>io.ReadFull</code> that uses them well:
<pre> <pre>
func ReadFull(r Reader, buf []byte) (n int, err os.Error) { func ReadFull(r Reader, buf []byte) (n int, err os.Error) {
for len(buf) > 0 &amp;&amp; err == nil { for len(buf) > 0 &amp;&amp; err == nil {
var nr int; var nr int
nr, err = r.Read(buf); nr, err = r.Read(buf)
n += nr; n += nr
buf = buf[nr:len(buf)]; buf = buf[nr:len(buf)]
} }
return; return
} }
</pre> </pre>
...@@ -790,8 +805,8 @@ The zero-value-is-useful property works transitively. Consider this type declara ...@@ -790,8 +805,8 @@ The zero-value-is-useful property works transitively. Consider this type declara
<pre> <pre>
type SyncedBuffer struct { type SyncedBuffer struct {
lock sync.Mutex; lock sync.Mutex
buffer bytes.Buffer; buffer bytes.Buffer
} }
</pre> </pre>
...@@ -802,8 +817,8 @@ correctly without further arrangement. ...@@ -802,8 +817,8 @@ correctly without further arrangement.
</p> </p>
<pre> <pre>
p := new(SyncedBuffer); // type *SyncedBuffer p := new(SyncedBuffer) // type *SyncedBuffer
var v SyncedBuffer; // type SyncedBuffer var v SyncedBuffer // type SyncedBuffer
</pre> </pre>
<h3 id="composite_literals">Constructors and composite literals</h3> <h3 id="composite_literals">Constructors and composite literals</h3>
...@@ -819,12 +834,12 @@ func NewFile(fd int, name string) *File { ...@@ -819,12 +834,12 @@ func NewFile(fd int, name string) *File {
if fd &lt; 0 { if fd &lt; 0 {
return nil return nil
} }
f := new(File); f := new(File)
f.fd = fd; f.fd = fd
f.name = name; f.name = name
f.dirinfo = nil; f.dirinfo = nil
f.nepipe = 0; f.nepipe = 0
return f; return f
} }
</pre> </pre>
...@@ -841,8 +856,8 @@ func NewFile(fd int, name string) *File { ...@@ -841,8 +856,8 @@ func NewFile(fd int, name string) *File {
if fd &lt; 0 { if fd &lt; 0 {
return nil return nil
} }
f := File{fd, name, nil, 0}; f := File{fd, name, nil, 0}
return &amp;f; return &amp;f
} }
</pre> </pre>
...@@ -856,7 +871,7 @@ so we can combine these last two lines. ...@@ -856,7 +871,7 @@ so we can combine these last two lines.
</p> </p>
<pre> <pre>
return &amp;File{fd, name, nil, 0}; return &amp;File{fd, name, nil, 0}
</pre> </pre>
<p> <p>
...@@ -883,9 +898,9 @@ In these examples, the initializations work regardless of the values of <code>En ...@@ -883,9 +898,9 @@ In these examples, the initializations work regardless of the values of <code>En
</p> </p>
<pre> <pre>
a := [...]string {Enone: "no error", Eio: "Eio", Einval: "invalid argument"}; a := [...]string {Enone: "no error", Eio: "Eio", Einval: "invalid argument"}
s := []string {Enone: "no error", Eio: "Eio", Einval: "invalid argument"}; s := []string {Enone: "no error", Eio: "Eio", Einval: "invalid argument"}
m := map[int]string{Enone: "no error", Eio: "Eio", Einval: "invalid argument"}; m := map[int]string{Enone: "no error", Eio: "Eio", Einval: "invalid argument"}
</pre> </pre>
<h3 id="allocation_make">Allocation with <code>make()</code></h3> <h3 id="allocation_make">Allocation with <code>make()</code></h3>
...@@ -927,15 +942,15 @@ These examples illustrate the difference between <code>new()</code> and ...@@ -927,15 +942,15 @@ These examples illustrate the difference between <code>new()</code> and
</p> </p>
<pre> <pre>
var p *[]int = new([]int); // allocates slice structure; *p == nil; rarely useful var p *[]int = new([]int) // allocates slice structure; *p == nil; rarely useful
var v []int = make([]int, 100); // v now refers to a new array of 100 ints var v []int = make([]int, 100) // v now refers to a new array of 100 ints
// Unnecessarily complex: // Unnecessarily complex:
var p *[]int = new([]int); var p *[]int = new([]int)
*p = make([]int, 100, 100); *p = make([]int, 100, 100)
// Idiomatic: // Idiomatic:
v := make([]int, 100); v := make([]int, 100)
</pre> </pre>
<p> <p>
...@@ -983,8 +998,8 @@ func Sum(a *[3]float) (sum float) { ...@@ -983,8 +998,8 @@ func Sum(a *[3]float) (sum float) {
return return
} }
array := [...]float{7.0, 8.5, 9.1}; array := [...]float{7.0, 8.5, 9.1}
x := Sum(&amp;array); // Note the explicit address-of operator x := Sum(&amp;array) // Note the explicit address-of operator
</pre> </pre>
<p> <p>
...@@ -1020,22 +1035,22 @@ any. To read into the first 32 bytes of a larger buffer ...@@ -1020,22 +1035,22 @@ any. To read into the first 32 bytes of a larger buffer
<code>b</code>, <i>slice</i> (here used as a verb) the buffer. <code>b</code>, <i>slice</i> (here used as a verb) the buffer.
</p> </p>
<pre> <pre>
n, err := f.Read(buf[0:32]); n, err := f.Read(buf[0:32])
</pre> </pre>
<p> <p>
Such slicing is common and efficient. In fact, leaving efficiency aside for Such slicing is common and efficient. In fact, leaving efficiency aside for
the moment, this snippet would also read the first 32 bytes of the buffer. the moment, this snippet would also read the first 32 bytes of the buffer.
</p> </p>
<pre> <pre>
var n int; var n int
var err os.Error; var err os.Error
for i := 0; i < 32; i++ { for i := 0; i < 32; i++ {
nbytes, e := f.Read(buf[i:i+1]); // Read one byte. nbytes, e := f.Read(buf[i:i+1]) // Read one byte.
if nbytes == 0 || e != nil { if nbytes == 0 || e != nil {
err = e; err = e
break; break
} }
n += nbytes; n += nbytes
} }
</pre> </pre>
<p> <p>
...@@ -1051,21 +1066,21 @@ resulting slice is returned. The function uses the fact that ...@@ -1051,21 +1066,21 @@ resulting slice is returned. The function uses the fact that
</p> </p>
<pre> <pre>
func Append(slice, data[]byte) []byte { func Append(slice, data[]byte) []byte {
l := len(slice); l := len(slice)
if l + len(data) > cap(slice) { // reallocate if l + len(data) > cap(slice) { // reallocate
// Allocate double what's needed, for future growth. // Allocate double what's needed, for future growth.
newSlice := make([]byte, (l+len(data))*2); newSlice := make([]byte, (l+len(data))*2)
// Copy data (could use bytes.Copy()). // Copy data (could use bytes.Copy()).
for i, c := range slice { for i, c := range slice {
newSlice[i] = c newSlice[i] = c
} }
slice = newSlice; slice = newSlice
} }
slice = slice[0:l+len(data)]; slice = slice[0:l+len(data)]
for i, c := range data { for i, c := range data {
slice[l+i] = c slice[l+i] = c
} }
return slice; return slice
} }
</pre> </pre>
<p> <p>
...@@ -1111,8 +1126,8 @@ is not present in the map will cause the program to crash, but ...@@ -1111,8 +1126,8 @@ is not present in the map will cause the program to crash, but
there is a way to do so safely using a multiple assignment. there is a way to do so safely using a multiple assignment.
</p> </p>
<pre> <pre>
var seconds int; var seconds int
var ok bool; var ok bool
seconds, ok = timeZone[tz] seconds, ok = timeZone[tz]
</pre> </pre>
<p> <p>
...@@ -1128,8 +1143,8 @@ func offset(tz string) int { ...@@ -1128,8 +1143,8 @@ func offset(tz string) int {
if seconds, ok := timeZone[tz]; ok { if seconds, ok := timeZone[tz]; ok {
return seconds return seconds
} }
log.Stderr("unknown time zone", tz); log.Stderr("unknown time zone", tz)
return 0; return 0
} }
</pre> </pre>
<p> <p>
...@@ -1140,7 +1155,7 @@ value discarded harmlessly. For testing presence in a map, use the blank ...@@ -1140,7 +1155,7 @@ value discarded harmlessly. For testing presence in a map, use the blank
identifier in place of the usual variable for the value. identifier in place of the usual variable for the value.
</p> </p>
<pre> <pre>
_, present := timeZone[tz]; _, present := timeZone[tz]
</pre> </pre>
<p> <p>
To delete a map entry, turn the multiple assignment around by placing To delete a map entry, turn the multiple assignment around by placing
...@@ -1149,7 +1164,7 @@ is deleted. It's safe to do this even if the key is already absent ...@@ -1149,7 +1164,7 @@ is deleted. It's safe to do this even if the key is already absent
from the map. from the map.
</p> </p>
<pre> <pre>
timeZone["PDT"] = 0, false; // Now on Standard Time timeZone["PDT"] = 0, false // Now on Standard Time
</pre> </pre>
<h3 id="printing">Printing</h3> <h3 id="printing">Printing</h3>
...@@ -1170,9 +1185,9 @@ between arguments if neither is a string and appends a newline to the output. ...@@ -1170,9 +1185,9 @@ between arguments if neither is a string and appends a newline to the output.
In this example each line produces the same output. In this example each line produces the same output.
</p> </p>
<pre> <pre>
fmt.Printf("Hello %d\n", 23); fmt.Printf("Hello %d\n", 23)
fmt.Fprint(os.Stdout, "Hello ", 23, "\n"); fmt.Fprint(os.Stdout, "Hello ", 23, "\n")
fmt.Println(fmt.Sprint("Hello ", 23)); fmt.Println(fmt.Sprint("Hello ", 23))
</pre> </pre>
<p> <p>
As mentioned in As mentioned in
...@@ -1187,8 +1202,8 @@ do not take flags for signedness or size; instead, the printing routines use the ...@@ -1187,8 +1202,8 @@ do not take flags for signedness or size; instead, the printing routines use the
type of the argument to decide these properties. type of the argument to decide these properties.
</p> </p>
<pre> <pre>
var x uint64 = 1<<64 - 1; var x uint64 = 1<<64 - 1
fmt.Printf("%d %x; %d %x\n", x, x, int64(x), int64(x)); fmt.Printf("%d %x; %d %x\n", x, x, int64(x), int64(x))
</pre> </pre>
<p> <p>
prints prints
...@@ -1204,7 +1219,7 @@ Moreover, that format can print <em>any</em> value, even arrays, structs, and ...@@ -1204,7 +1219,7 @@ Moreover, that format can print <em>any</em> value, even arrays, structs, and
maps. Here is a print statement for the time zone map defined in the previous section. maps. Here is a print statement for the time zone map defined in the previous section.
</p> </p>
<pre> <pre>
fmt.Printf("%v\n", timeZone); // or just fmt.Println(timeZone); fmt.Printf("%v\n", timeZone) // or just fmt.Println(timeZone)
</pre> </pre>
<p> <p>
which gives output which gives output
...@@ -1220,15 +1235,15 @@ format <code>%#v</code> prints the value in full Go syntax. ...@@ -1220,15 +1235,15 @@ format <code>%#v</code> prints the value in full Go syntax.
</p> </p>
<pre> <pre>
type T struct { type T struct {
a int; a int
b float; b float
c string; c string
} }
t := &amp;T{ 7, -2.35, "abc\tdef" }; t := &amp;T{ 7, -2.35, "abc\tdef" }
fmt.Printf("%v\n", t); fmt.Printf("%v\n", t)
fmt.Printf("%+v\n", t); fmt.Printf("%+v\n", t)
fmt.Printf("%#v\n", t); fmt.Printf("%#v\n", t)
fmt.Printf("%#v\n", timeZone); fmt.Printf("%#v\n", timeZone)
</pre> </pre>
<p> <p>
prints prints
...@@ -1251,7 +1266,7 @@ a space in the format (<code>%&nbsp;x</code>) it puts spaces between the bytes. ...@@ -1251,7 +1266,7 @@ a space in the format (<code>%&nbsp;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. Another handy format is <code>%T</code>, which prints the <em>type</em> of a value.
<pre> <pre>
fmt.Printf(&quot;%T\n&quot;, timeZone); fmt.Printf(&quot;%T\n&quot;, timeZone)
</pre> </pre>
<p> <p>
prints prints
...@@ -1266,9 +1281,9 @@ For our simple type <code>T</code>, that might look like this. ...@@ -1266,9 +1281,9 @@ For our simple type <code>T</code>, that might look like this.
</p> </p>
<pre> <pre>
func (t *T) String() string { func (t *T) String() string {
return fmt.Sprintf("%d/%g/%q", t.a, t.b, t.c); return fmt.Sprintf("%d/%g/%q", t.a, t.b, t.c)
} }
fmt.Printf("%v\n", t); fmt.Printf("%v\n", t)
</pre> </pre>
<p> <p>
to print in the format to print in the format
...@@ -1296,7 +1311,7 @@ function <code>log.Stderr</code> we used above. It passes its arguments directly ...@@ -1296,7 +1311,7 @@ function <code>log.Stderr</code> we used above. It passes its arguments directly
<pre> <pre>
// Stderr is a helper function for easy logging to stderr. It is analogous to Fprint(os.Stderr). // Stderr is a helper function for easy logging to stderr. It is analogous to Fprint(os.Stderr).
func Stderr(v ...) { func Stderr(v ...) {
stderr.Output(2, fmt.Sprintln(v)); // Output takes parameters (int, string) stderr.Output(2, fmt.Sprintln(v)) // Output takes parameters (int, string)
} }
</pre> </pre>
<p> <p>
...@@ -1339,13 +1354,13 @@ sets of values. ...@@ -1339,13 +1354,13 @@ sets of values.
<pre> <pre>
type ByteSize float64 type ByteSize float64
const ( const (
_ = iota; // ignore first value by assigning to blank identifier _ = iota // ignore first value by assigning to blank identifier
KB ByteSize = 1<<(10*iota); KB ByteSize = 1<<(10*iota)
MB; MB
GB; GB
TB; TB
PB; PB
YB; YB
) )
</pre> </pre>
<p> <p>
...@@ -1385,9 +1400,9 @@ initializer can be a general expression computed at run time. ...@@ -1385,9 +1400,9 @@ initializer can be a general expression computed at run time.
</p> </p>
<pre> <pre>
var ( var (
HOME = os.Getenv("HOME"); HOME = os.Getenv("HOME")
USER = os.Getenv("USER"); USER = os.Getenv("USER")
GOROOT = os.Getenv("GOROOT"); GOROOT = os.Getenv("GOROOT")
) )
</pre> </pre>
...@@ -1453,9 +1468,9 @@ method can overwrite the caller's slice. ...@@ -1453,9 +1468,9 @@ method can overwrite the caller's slice.
</p> </p>
<pre> <pre>
func (p *ByteSlice) Append(data []byte) { func (p *ByteSlice) Append(data []byte) {
slice := *p; slice := *p
// Body as above, without the return. // Body as above, without the return.
*p = slice; *p = slice
} }
</pre> </pre>
<p> <p>
...@@ -1464,10 +1479,10 @@ like a standard <code>Write</code> method, like this, ...@@ -1464,10 +1479,10 @@ like a standard <code>Write</code> method, like this,
</p> </p>
<pre> <pre>
func (p *ByteSlice) Write(data []byte) (n int, err os.Error) { func (p *ByteSlice) Write(data []byte) (n int, err os.Error) {
slice := *p; slice := *p
// Again as above. // Again as above.
*p = slice; *p = slice
return len(data), nil; return len(data), nil
} }
</pre> </pre>
<p> <p>
...@@ -1476,8 +1491,8 @@ then the type <code>*ByteSlice</code> satisfies the standard interface ...@@ -1476,8 +1491,8 @@ then the type <code>*ByteSlice</code> satisfies the standard interface
print into one. print into one.
</p> </p>
<pre> <pre>
var b ByteSlice; var b ByteSlice
fmt.Fprintf(&amp;b, "This hour has %d days\n", 7); fmt.Fprintf(&amp;b, "This hour has %d days\n", 7)
</pre> </pre>
<p> <p>
We pass the address of a <code>ByteSlice</code> We pass the address of a <code>ByteSlice</code>
...@@ -1532,15 +1547,15 @@ func (s Sequence) Swap(i, j int) { ...@@ -1532,15 +1547,15 @@ func (s Sequence) Swap(i, j int) {
// Method for printing - sorts the elements before printing. // Method for printing - sorts the elements before printing.
func (s Sequence) String() string { func (s Sequence) String() string {
sort.Sort(s); sort.Sort(s)
str := "["; str := "["
for i, elem := range s { for i, elem := range s {
if i > 0 { if i > 0 {
str += " " str += " "
} }
str += fmt.Sprint(elem); str += fmt.Sprint(elem)
} }
return str + "]"; return str + "]"
} }
</pre> </pre>
...@@ -1554,8 +1569,8 @@ effort if we convert the <code>Sequence</code> to a plain ...@@ -1554,8 +1569,8 @@ effort if we convert the <code>Sequence</code> to a plain
</p> </p>
<pre> <pre>
func (s Sequence) String() string { func (s Sequence) String() string {
sort.Sort(s); sort.Sort(s)
return fmt.Sprint([]int(s)); return fmt.Sprint([]int(s))
} }
</pre> </pre>
<p> <p>
...@@ -1582,7 +1597,7 @@ type Sequence []int ...@@ -1582,7 +1597,7 @@ type Sequence []int
// Method for printing - sorts the elements before printing // Method for printing - sorts the elements before printing
func (s Sequence) String() string { func (s Sequence) String() string {
sort.IntArray(s).Sort(); sort.IntArray(s).Sort()
return fmt.Sprint([]int(s)) return fmt.Sprint([]int(s))
} }
</pre> </pre>
...@@ -1631,9 +1646,9 @@ The interface to <code>crypto/block</code> includes: ...@@ -1631,9 +1646,9 @@ The interface to <code>crypto/block</code> includes:
</p> </p>
<pre> <pre>
type Cipher interface { type Cipher interface {
BlockSize() int; BlockSize() int
Encrypt(src, dst []byte); Encrypt(src, dst []byte)
Decrypt(src, dst []byte); Decrypt(src, dst []byte)
} }
// NewECBDecrypter returns a reader that reads data // NewECBDecrypter returns a reader that reads data
...@@ -1665,7 +1680,7 @@ that implements <code>Handler</code> can serve HTTP requests. ...@@ -1665,7 +1680,7 @@ that implements <code>Handler</code> can serve HTTP requests.
</p> </p>
<pre> <pre>
type Handler interface { type Handler interface {
ServeHTTP(*Conn, *Request); ServeHTTP(*Conn, *Request)
} }
</pre> </pre>
<p> <p>
...@@ -1678,12 +1693,12 @@ page is visited. ...@@ -1678,12 +1693,12 @@ page is visited.
<pre> <pre>
// Simple counter server. // Simple counter server.
type Counter struct { type Counter struct {
n int; n int
} }
func (ctr *Counter) ServeHTTP(c *http.Conn, req *http.Request) { func (ctr *Counter) ServeHTTP(c *http.Conn, req *http.Request) {
ctr.n++; ctr.n++
fmt.Fprintf(c, "counter = %d\n", ctr.n); fmt.Fprintf(c, "counter = %d\n", ctr.n)
} }
</pre> </pre>
<p> <p>
...@@ -1692,8 +1707,8 @@ For reference, here's how to attach such a server to a node on the URL tree. ...@@ -1692,8 +1707,8 @@ For reference, here's how to attach such a server to a node on the URL tree.
<pre> <pre>
import "http" import "http"
... ...
ctr := new(Counter); ctr := new(Counter)
http.Handle("/counter", ctr); http.Handle("/counter", ctr)
</pre> </pre>
<p> <p>
But why make <code>Counter</code> a struct? An integer is all that's needed. But why make <code>Counter</code> a struct? An integer is all that's needed.
...@@ -1704,8 +1719,8 @@ But why make <code>Counter</code> a struct? An integer is all that's needed. ...@@ -1704,8 +1719,8 @@ But why make <code>Counter</code> a struct? An integer is all that's needed.
type Counter int type Counter int
func (ctr *Counter) ServeHTTP(c *http.Conn, req *http.Request) { func (ctr *Counter) ServeHTTP(c *http.Conn, req *http.Request) {
*ctr++; *ctr++
fmt.Fprintf(c, "counter = %d\n", *ctr); fmt.Fprintf(c, "counter = %d\n", *ctr)
} }
</pre> </pre>
<p> <p>
...@@ -1718,8 +1733,8 @@ has been visited? Tie a channel to the web page. ...@@ -1718,8 +1733,8 @@ has been visited? Tie a channel to the web page.
type Chan chan *http.Request type Chan chan *http.Request
func (ch Chan) ServeHTTP(c *http.Conn, req *http.Request) { func (ch Chan) ServeHTTP(c *http.Conn, req *http.Request) {
ch <- req; ch <- req
fmt.Fprint(c, "notification sent"); fmt.Fprint(c, "notification sent")
} }
</pre> </pre>
<p> <p>
...@@ -1730,7 +1745,7 @@ It's easy to write a function to print the arguments. ...@@ -1730,7 +1745,7 @@ It's easy to write a function to print the arguments.
<pre> <pre>
func ArgServer() { func ArgServer() {
for i, s := range os.Args { for i, s := range os.Args {
fmt.Println(s); fmt.Println(s)
} }
} }
</pre> </pre>
...@@ -1750,7 +1765,7 @@ type HandlerFunc func(*Conn, *Request) ...@@ -1750,7 +1765,7 @@ type HandlerFunc func(*Conn, *Request)
// ServeHTTP calls f(c, req). // ServeHTTP calls f(c, req).
func (f HandlerFunc) ServeHTTP(c *Conn, req *Request) { func (f HandlerFunc) ServeHTTP(c *Conn, req *Request) {
f(c, req); f(c, req)
} }
</pre> </pre>
<p> <p>
...@@ -1768,7 +1783,7 @@ to have the right signature. ...@@ -1768,7 +1783,7 @@ to have the right signature.
// Argument server. // Argument server.
func ArgServer(c *http.Conn, req *http.Request) { func ArgServer(c *http.Conn, req *http.Request) {
for i, s := range os.Args { for i, s := range os.Args {
fmt.Fprintln(c, s); fmt.Fprintln(c, s)
} }
} }
</pre> </pre>
...@@ -1780,7 +1795,7 @@ to access <code>IntArray.Sort</code>. ...@@ -1780,7 +1795,7 @@ to access <code>IntArray.Sort</code>.
The code to set it up is concise: The code to set it up is concise:
</p> </p>
<pre> <pre>
http.Handle("/args", http.HandlerFunc(ArgServer)); http.Handle("/args", http.HandlerFunc(ArgServer))
</pre> </pre>
<p> <p>
When someone visits the page <code>/args</code>, When someone visits the page <code>/args</code>,
...@@ -1813,11 +1828,11 @@ here are their definitions. ...@@ -1813,11 +1828,11 @@ here are their definitions.
</p> </p>
<pre> <pre>
type Reader interface { type Reader interface {
Read(p []byte) (n int, err os.Error); Read(p []byte) (n int, err os.Error)
} }
type Writer interface { type Writer interface {
Write(p []byte) (n int, err os.Error); Write(p []byte) (n int, err os.Error)
} }
</pre> </pre>
<p> <p>
...@@ -1832,8 +1847,8 @@ to embed the two interfaces to form the new one, like this: ...@@ -1832,8 +1847,8 @@ to embed the two interfaces to form the new one, like this:
<pre> <pre>
// ReadWrite is the interface that groups the basic Read and Write methods. // ReadWrite is the interface that groups the basic Read and Write methods.
type ReadWriter interface { type ReadWriter interface {
Reader; Reader
Writer; Writer
} }
</pre> </pre>
<p> <p>
...@@ -1857,8 +1872,8 @@ but does not give them field names. ...@@ -1857,8 +1872,8 @@ but does not give them field names.
// ReadWriter stores pointers to a Reader and a Writer. // ReadWriter stores pointers to a Reader and a Writer.
// It implements io.ReadWriter. // It implements io.ReadWriter.
type ReadWriter struct { type ReadWriter struct {
*Reader; *Reader
*Writer; *Writer
} }
</pre> </pre>
<p> <p>
...@@ -1866,8 +1881,8 @@ This struct could be written as ...@@ -1866,8 +1881,8 @@ This struct could be written as
</p> </p>
<pre> <pre>
type ReadWriter struct { type ReadWriter struct {
reader *Reader; reader *Reader
writer *Writer; writer *Writer
} }
</pre> </pre>
<p> <p>
...@@ -1904,8 +1919,8 @@ This example shows an embedded field alongside a regular, named field. ...@@ -1904,8 +1919,8 @@ This example shows an embedded field alongside a regular, named field.
</p> </p>
<pre> <pre>
type Job struct { type Job struct {
Command string; Command string
*log.Logger; *log.Logger
} }
</pre> </pre>
<p> <p>
...@@ -1916,7 +1931,7 @@ a field name, of course, but it's not necessary to do so. And now we can ...@@ -1916,7 +1931,7 @@ a field name, of course, but it's not necessary to do so. And now we can
log to a <code>Job</code>: log to a <code>Job</code>:
</p> </p>
<pre> <pre>
job.Log("starting now..."); job.Log("starting now...")
</pre> </pre>
<p> <p>
The <code>Logger</code> is a regular field of the struct and we can initialize The <code>Logger</code> is a regular field of the struct and we can initialize
...@@ -1936,7 +1951,7 @@ This would be useful if we wanted to refine the methods of <code>Logger</code>. ...@@ -1936,7 +1951,7 @@ This would be useful if we wanted to refine the methods of <code>Logger</code>.
</p> </p>
<pre> <pre>
func (job *Job) Logf(format string, args ...) { func (job *Job) Logf(format string, args ...) {
job.Logger.Logf("%q: %s", job.Command, fmt.Sprintf(format, args)); job.Logger.Logf("%q: %s", job.Command, fmt.Sprintf(format, args))
} }
</pre> </pre>
<p> <p>
...@@ -2023,15 +2038,15 @@ exits, silently. (The effect is similar to the Unix shell's ...@@ -2023,15 +2038,15 @@ exits, silently. (The effect is similar to the Unix shell's
background.) background.)
</p> </p>
<pre> <pre>
go list.Sort(); // run list.Sort in parallel; don't wait for it. go list.Sort() // run list.Sort in parallel; don't wait for it.
</pre> </pre>
<p> <p>
A function literal can be handy in a goroutine invocation. A function literal can be handy in a goroutine invocation.
<pre> <pre>
func Announce(message string, delay int64) { func Announce(message string, delay int64) {
go func() { go func() {
time.Sleep(delay); time.Sleep(delay)
fmt.Println(message); fmt.Println(message)
}() // Note the parentheses - must call the function. }() // Note the parentheses - must call the function.
} }
</pre> </pre>
...@@ -2051,9 +2066,9 @@ If an optional integer parameter is provided, it sets the buffer size for the ch ...@@ -2051,9 +2066,9 @@ If an optional integer parameter is provided, it sets the buffer size for the ch
The default is zero, for an unbuffered or synchronous channel. The default is zero, for an unbuffered or synchronous channel.
</p> </p>
<pre> <pre>
ci := make(chan int); // unbuffered channel of integers ci := make(chan int) // unbuffered channel of integers
cj := make(chan int, 0); // unbuffered channel of integers cj := make(chan int, 0) // unbuffered channel of integers
cs := make(chan *os.File, 100); // buffered channel of pointers to Files cs := make(chan *os.File, 100) // buffered channel of pointers to Files
</pre> </pre>
<p> <p>
Channels combine communication&mdash;the exchange of a value&mdash;with Channels combine communication&mdash;the exchange of a value&mdash;with
...@@ -2066,14 +2081,14 @@ In the previous section we launched a sort in the background. A channel ...@@ -2066,14 +2081,14 @@ In the previous section we launched a sort in the background. A channel
can allow the launching goroutine to wait for the sort to complete. can allow the launching goroutine to wait for the sort to complete.
</p> </p>
<pre> <pre>
c := make(chan int); // Allocate a channel. c := make(chan int) // Allocate a channel.
// Start the sort in a goroutine; when it completes, signal on the channel. // Start the sort in a goroutine; when it completes, signal on the channel.
go func() { go func() {
list.Sort(); list.Sort()
c &lt;- 1; // Send a signal; value does not matter. c &lt;- 1 // Send a signal; value does not matter.
}(); }()
doSomethingForAWhile(); doSomethingForAWhile()
&lt;-c; // Wait for sort to finish; discard sent value. &lt;-c // Wait for sort to finish; discard sent value.
</pre> </pre>
<p> <p>
Receivers always block until there is data to receive. Receivers always block until there is data to receive.
...@@ -2095,15 +2110,15 @@ simultaneous calls to <code>process</code>. ...@@ -2095,15 +2110,15 @@ simultaneous calls to <code>process</code>.
var sem = make(chan int, MaxOutstanding) var sem = make(chan int, MaxOutstanding)
func handle(r *Request) { func handle(r *Request) {
sem <- 1; // Wait for active queue to drain. sem <- 1 // Wait for active queue to drain.
process(r); // May take a long time. process(r) // May take a long time.
<-sem; // Done; enable next request to run. <-sem // Done; enable next request to run.
} }
func Serve(queue chan *Request) { func Serve(queue chan *Request) {
for { for {
req := <-queue; req := <-queue
go handle(req); // Don't wait for handle to finish. go handle(req) // Don't wait for handle to finish.
} }
} }
</pre> </pre>
...@@ -2120,7 +2135,7 @@ receiving from that channel. ...@@ -2120,7 +2135,7 @@ receiving from that channel.
<pre> <pre>
func handle(queue chan *Request) { func handle(queue chan *Request) {
for r := range queue { for r := range queue {
process(r); process(r)
} }
} }
...@@ -2129,7 +2144,7 @@ func Serve(clientRequests chan *clientRequests, quit chan bool) { ...@@ -2129,7 +2144,7 @@ func Serve(clientRequests chan *clientRequests, quit chan bool) {
for i := 0; i < MaxOutstanding; i++ { for i := 0; i < MaxOutstanding; i++ {
go handle(clientRequests) go handle(clientRequests)
} }
<-quit; // Wait to be told to exit. <-quit // Wait to be told to exit.
} }
</pre> </pre>
...@@ -2148,9 +2163,9 @@ Here's a schematic definition of type <code>Request</code>. ...@@ -2148,9 +2163,9 @@ Here's a schematic definition of type <code>Request</code>.
</p> </p>
<pre> <pre>
type Request struct { type Request struct {
args []int; args []int
f func([]int) int; f func([]int) int
resultChan chan int; resultChan chan int
} }
</pre> </pre>
<p> <p>
...@@ -2167,9 +2182,9 @@ func sum(a []int) (s int) { ...@@ -2167,9 +2182,9 @@ func sum(a []int) (s int) {
request := &amp;Request{[]int{3, 4, 5}, sum, make(chan int)} request := &amp;Request{[]int{3, 4, 5}, sum, make(chan int)}
// Send request // Send request
clientRequests <- request; clientRequests <- request
// Wait for response. // Wait for response.
fmt.Printf("answer: %d\n", <-request.resultChan); fmt.Printf("answer: %d\n", <-request.resultChan)
</pre> </pre>
<p> <p>
On the server side, the handler function is the only thing that changes. On the server side, the handler function is the only thing that changes.
...@@ -2177,7 +2192,7 @@ On the server side, the handler function is the only thing that changes. ...@@ -2177,7 +2192,7 @@ On the server side, the handler function is the only thing that changes.
<pre> <pre>
func handle(queue chan *Request) { func handle(queue chan *Request) {
for req := range queue { for req := range queue {
req.resultChan <- req.f(req.args); req.resultChan <- req.f(req.args)
} }
} }
</pre> </pre>
...@@ -2207,7 +2222,7 @@ func (v Vector) DoSome(i, n int, u Vector, c chan int) { ...@@ -2207,7 +2222,7 @@ func (v Vector) DoSome(i, n int, u Vector, c chan int) {
for ; i < n; i++ { for ; i < n; i++ {
v[i] += u.Op(v[i]) v[i] += u.Op(v[i])
} }
c <- 1; // signal that this piece is done c <- 1 // signal that this piece is done
} }
</pre> </pre>
<p> <p>
...@@ -2220,9 +2235,9 @@ launching all the goroutines. ...@@ -2220,9 +2235,9 @@ launching all the goroutines.
const NCPU = 4 // number of CPU cores const NCPU = 4 // number of CPU cores
func (v Vector) DoAll(u Vector) { func (v Vector) DoAll(u Vector) {
c := make(chan int, NCPU); // Buffering optional but sensible. c := make(chan int, NCPU) // Buffering optional but sensible.
for i := 0; i < NCPU; i++ { for i := 0; i < NCPU; i++ {
go v.DoSome(i*len(v)/NCPU, (i+1)*len(v)/NCPU, u, c); go v.DoSome(i*len(v)/NCPU, (i+1)*len(v)/NCPU, u, c)
} }
// Drain the channel. // Drain the channel.
for i := 0; i < NCPU; i++ { for i := 0; i < NCPU; i++ {
...@@ -2267,12 +2282,12 @@ var serverChan = make(chan *Buffer) ...@@ -2267,12 +2282,12 @@ var serverChan = make(chan *Buffer)
func client() { func client() {
for { for {
b, ok := <-freeList; // grab a buffer if available b, ok := <-freeList // grab a buffer if available
if !ok { // if not, allocate a new one if !ok { // if not, allocate a new one
b = new(Buffer) b = new(Buffer)
} }
load(b); // read next message from the net load(b) // read next message from the net
serverChan <- b; // send to server serverChan <- b // send to server
} }
} }
</pre> </pre>
...@@ -2283,9 +2298,9 @@ and returns the buffer to the free list. ...@@ -2283,9 +2298,9 @@ and returns the buffer to the free list.
<pre> <pre>
func server() { func server() {
for { for {
b := <-serverChan; // wait for work b := <-serverChan // wait for work
process(b); process(b)
_ = freeList <- b; // reuse buffer if room _ = freeList <- b // reuse buffer if room
} }
} }
</pre> </pre>
...@@ -2316,7 +2331,7 @@ a simple interface. ...@@ -2316,7 +2331,7 @@ a simple interface.
</p> </p>
<pre> <pre>
type Error interface { type Error interface {
String() string; String() string
} }
</pre> </pre>
<p> <p>
...@@ -2329,13 +2344,13 @@ For example, <code>os.Open</code> returns an <code>os.PathError</code>. ...@@ -2329,13 +2344,13 @@ For example, <code>os.Open</code> returns an <code>os.PathError</code>.
// PathError records an error and the operation and // PathError records an error and the operation and
// file path that caused it. // file path that caused it.
type PathError struct { type PathError struct {
Op string; // "open", "unlink", etc. Op string // "open", "unlink", etc.
Path string; // The associated file. Path string // The associated file.
Error Error; // Returned by the system call. Error Error // Returned by the system call.
} }
func (e *PathError) String() string { func (e *PathError) String() string {
return e.Op + " " + e.Path + ": " + e.Error.String(); return e.Op + " " + e.Path + ": " + e.Error.String()
} }
</pre> </pre>
<p> <p>
...@@ -2363,12 +2378,12 @@ field for recoverable failures. ...@@ -2363,12 +2378,12 @@ field for recoverable failures.
<pre> <pre>
for try := 0; try < 2; try++ { for try := 0; try < 2; try++ {
file, err = os.Open(filename, os.O_RDONLY, 0); file, err = os.Open(filename, os.O_RDONLY, 0)
if err == nil { if err == nil {
return return
} }
if e, ok := err.(*os.PathError); ok &amp;&amp; e.Error == os.ENOSPC { if e, ok := err.(*os.PathError); ok &amp;&amp; e.Error == os.ENOSPC {
deleteTempFiles(); // Recover some space. deleteTempFiles() // Recover some space.
continue continue
} }
return return
...@@ -2400,12 +2415,12 @@ An explanation follows. ...@@ -2400,12 +2415,12 @@ An explanation follows.
package main package main
import ( import (
"flag"; "flag"
"http"; "http"
"io"; "io"
"log"; "log"
"strings"; "strings"
"template"; "template"
) )
var addr = flag.String("addr", ":1718", "http service address") // Q=17, R=18 var addr = flag.String("addr", ":1718", "http service address") // Q=17, R=18
...@@ -2416,20 +2431,20 @@ var fmap = template.FormatterMap{ ...@@ -2416,20 +2431,20 @@ var fmap = template.FormatterMap{
var templ = template.MustParse(templateStr, fmap) var templ = template.MustParse(templateStr, fmap)
func main() { func main() {
flag.Parse(); flag.Parse()
http.Handle("/", http.HandlerFunc(QR)); http.Handle("/", http.HandlerFunc(QR))
err := http.ListenAndServe(*addr, nil); err := http.ListenAndServe(*addr, nil)
if err != nil { if err != nil {
log.Exit("ListenAndServe:", err); log.Exit("ListenAndServe:", err)
} }
} }
func QR(c *http.Conn, req *http.Request) { func QR(c *http.Conn, req *http.Request) {
templ.Execute(req.FormValue("s"), c); templ.Execute(req.FormValue("s"), c)
} }
func UrlHtmlFormatter(w io.Writer, v interface{}, fmt string) { func UrlHtmlFormatter(w io.Writer, v interface{}, fmt string) {
template.HTMLEscape(w, strings.Bytes(http.URLEscape(v.(string)))); template.HTMLEscape(w, strings.Bytes(http.URLEscape(v.(string))))
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment