From 163ecdac1a1e71ff99049a9df87f9356be918fac Mon Sep 17 00:00:00 2001
From: Rob Pike
type T struct {
- name string; // name of the object
- value int; // its value
+ name string // name of the object
+ value int // its value
}
@@ -88,8 +88,8 @@ type T struct {
type T struct {
- name string; // name of the object
- value int; // its value
+ name string // name of the object
+ value int // its value
}
@@ -103,26 +103,26 @@ Some formatting details remain. Very briefly,
gofmt
emits them by default.
- Use spaces only if you must.
- if
,
- for
, switch
) do not require parentheses in
- their syntax.
- Also, the operator precedence hierarchy is shorter and clearer, so
+ gofmt
emits them by default.
+ Use spaces only if you must.
+ if
,
+ for
, switch
) do not require parentheses in
+ their syntax.
+ Also, the operator precedence hierarchy is shorter and clearer, so
x<<8 + y<<16- means what the spacing implies. -
/* - The regexp package implements a simple library for - regular expressions. + The regexp package implements a simple library for + regular expressions. - The syntax of the regular expressions accepted is: + The syntax of the regular expressions accepted is: - regexp: - concatenation { '|' concatenation } - concatenation: - { closure } - closure: - term [ '*' | '+' | '?' ] - term: - '^' - '$' - '.' - character - '[' [ '^' ] character-ranges ']' - '(' regexp ')' + regexp: + concatenation { '|' concatenation } + concatenation: + { closure } + closure: + term [ '*' | '+' | '?' ] + term: + '^' + '$' + '.' + character + '[' [ '^' ] character-ranges ']' + '(' regexp ')' */ package regexp@@ -228,10 +228,10 @@ Since the whole declaration is presented, such a comment can often be perfunctor
// Error codes returned by failures to parse an expression. var ( - ErrInternal = os.NewError("internal error"); - ErrUnmatchedLpar = os.NewError("unmatched '('"); - ErrUnmatchedRpar = os.NewError("unmatched ')'"); - ... + ErrInternal = os.NewError("internal error") + ErrUnmatchedLpar = os.NewError("unmatched '('") + ErrUnmatchedRpar = os.NewError("unmatched ')'") + ... )@@ -242,10 +242,10 @@ such as the fact that a set of variables is protected by a mutex.
var ( - countLock sync.Mutex; - inputCount uint32; - outputCount uint32; - errorCount uint32; + countLock sync.Mutex + inputCount uint32 + outputCount uint32 + errorCount uint32 )@@ -360,50 +360,65 @@ multiword names.
-Go needs fewer semicolons between statements than do other C variants.
-Semicolons are never required at the top level.
-And they are separators, not terminators, so they
-can be left off the last element of a statement or declaration list,
-a convenience
-for one-line funcs
and the like.
+Like C, Go's formal grammar uses semicolons to terminate statements;
+unlike C, those semicolons do not appear in the source.
+Instead the lexer uses a simple rule to insert semicolons automatically
+as it scans, so the input text is mostly free of them.
+The rule is this. If the last token before a newline is an identifier
+(which includes words like int
and float64
),
+a basic literal such as a number or string constant, or one of the
+tokens
+
+break continue fallthrough return ++ -- ) } ++
+the lexer always inserts a semicolon after the token. +This could be summarized as, “if the newline comes +after a token that could end a statement, add a semicolon”. +
+ ++A semicolon can also be omitted immediately before a closing brace, +so a statement such as +
-func CopyInBackground(dst, src chan Item) { go func() { for { dst <- <-src } }() -}+
+needs no semicolons.
+Idiomatic Go programs have semicolons only in places such as
+for
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.
+
-In fact, semicolons can be omitted at the end of any "StatementList" in the
-grammar, which includes things like cases in switch
-statements.
+One caveat. You should never put the opening brace of a
+control structure (if
, for
, switch
,
+or select
) on the next line. If you do, a semicolon
+will be inserted before the brace, which could cause unwanted
+effects. Write them like this
-switch { -case a < b: - return -1 -case a == b: - return 0 -case a > b: - return 1 +if i < f() { + g() +} ++
+not like this +
++if i < f() // wrong! +{ // wrong! + g() } --
-The grammar accepts an empty statement after any statement list, which
-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 struct
-declarations, or of funcs
for that matter)
-and often left off one-liners. But within functions, place them
-as you see fit.
-
if err := file.Chmod(0664); err != nil { - log.Stderr(err); - return err; + log.Stderr(err) + return err }@@ -462,11 +477,11 @@ the body ends in
break
, continue
,
-f, err := os.Open(name, os.O_RDONLY, 0); +f, err := os.Open(name, os.O_RDONLY, 0) if err != nil { - return err; + return err } -codeUsing(f); +codeUsing(f)
@@ -478,15 +493,15 @@ statements, the resulting code needs no else
statements.
-f, err := os.Open(name, os.O_RDONLY, 0); +f, err := os.Open(name, os.O_RDONLY, 0) if err != nil { - return err; + return err } -d, err := f.Stat(); +d, err := f.Stat() if err != nil { - return err; + return err } -codeUsing(f, d); +codeUsing(f, d)@@ -513,7 +528,7 @@ for { } Short declarations make it easy to declare the index variable right in the loop.
-sum := 0; +sum := 0 for i := 0; i < 10; i++ { sum += i } @@ -525,8 +540,8 @@ or reading from a channel, a@@ -1554,8 +1569,8 @@ effort if we convert therange
clause can manage the loop for you.-var m map[string]int; -sum := 0; +var m map[string]int +sum := 0 for _, value := range m { // key is unused sum += value } @@ -559,7 +574,7 @@ you should use parallel assignment.// Reverse a for i, j := 0, len(a)-1; i < j; i, j = i+1, j-1 { - a[i], a[j] = a[j], a[i] + a[i], a[j] = a[j], a[i] }@@ -639,15 +654,15 @@ have the corresponding type in each clause.switch t := interfaceValue.(type) { default: - fmt.Printf("unexpected type %T", t); // %T prints type + fmt.Printf("unexpected type %T", t) // %T prints type case bool: - fmt.Printf("boolean %t\n", t); + fmt.Printf("boolean %t\n", t) case int: - fmt.Printf("integer %d\n", t); + fmt.Printf("integer %d\n", t) case *bool: - fmt.Printf("pointer to boolean %t\n", *t); + fmt.Printf("pointer to boolean %t\n", *t) case *int: - fmt.Printf("pointer to integer %d\n", *t); + fmt.Printf("pointer to integer %d\n", *t) }@@ -693,13 +708,13 @@ and the next position.func nextInt(b []byte, i int) (int, int) { - for ; i < len(b) && !isDigit(b[i]); i++ { - } - x := 0; - for ; i < len(b) && isDigit(b[i]); i++ { - x = x*10 + int(b[i])-'0' - } - return x, i; + for ; i < len(b) && !isDigit(b[i]); i++ { + } + x := 0 + for ; i < len(b) && isDigit(b[i]); i++ { + x = x*10 + int(b[i])-'0' + } + return x, i }@@ -708,10 +723,10 @@ You could use it to scan the numbers in an input arraya
like this:- for i := 0; i < len(a); { - x, i = nextInt(a, i); - fmt.Println(x); - } + for i := 0; i < len(a); { + x, i = nextInt(a, i) + fmt.Println(x) + }Named result parameters
@@ -745,13 +760,13 @@ ofio.ReadFull
that uses them well:func ReadFull(r Reader, buf []byte) (n int, err os.Error) { - for len(buf) > 0 && err == nil { - var nr int; - nr, err = r.Read(buf); - n += nr; - buf = buf[nr:len(buf)]; - } - return; + for len(buf) > 0 && err == nil { + var nr int + nr, err = r.Read(buf) + n += nr + buf = buf[nr:len(buf)] + } + return }@@ -790,8 +805,8 @@ The zero-value-is-useful property works transitively. Consider this type declaratype SyncedBuffer struct { - lock sync.Mutex; - buffer bytes.Buffer; + lock sync.Mutex + buffer bytes.Buffer }@@ -802,8 +817,8 @@ correctly without further arrangement.-p := new(SyncedBuffer); // type *SyncedBuffer -var v SyncedBuffer; // type SyncedBuffer +p := new(SyncedBuffer) // type *SyncedBuffer +var v SyncedBuffer // type SyncedBufferConstructors and composite literals
@@ -816,15 +831,15 @@ packageos
.func NewFile(fd int, name string) *File { - if fd < 0 { - return nil - } - f := new(File); - f.fd = fd; - f.name = name; - f.dirinfo = nil; - f.nepipe = 0; - return f; + if fd < 0 { + return nil + } + f := new(File) + f.fd = fd + f.name = name + f.dirinfo = nil + f.nepipe = 0 + return f }@@ -838,11 +853,11 @@ new instance each time it is evaluated.func NewFile(fd int, name string) *File { - if fd < 0 { - return nil - } - f := File{fd, name, nil, 0}; - return &f; + if fd < 0 { + return nil + } + f := File{fd, name, nil, 0} + return &f }@@ -856,7 +871,7 @@ so we can combine these last two lines.- return &File{fd, name, nil, 0}; + return &File{fd, name, nil, 0}@@ -867,7 +882,7 @@ order, with the missing ones left as their respective zero values. Thus we coul
- return &File{fd: fd, name: name} + return &File{fd: fd, name: name}@@ -883,9 +898,9 @@ In these examples, the initializations work regardless of the values of
En
-a := [...]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"}; +a := [...]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"}Allocation with
@@ -927,15 +942,15 @@ These examples illustrate the difference betweenmake()
new()
and-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 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 // Unnecessarily complex: -var p *[]int = new([]int); -*p = make([]int, 100, 100); +var p *[]int = new([]int) +*p = make([]int, 100, 100) // Idiomatic: -v := make([]int, 100); +v := make([]int, 100)@@ -977,14 +992,14 @@ you can pass a pointer to the array.
func Sum(a *[3]float) (sum float) { - for _, v := range *a { - sum += v - } - return + for _, v := range *a { + sum += v + } + return } -array := [...]float{7.0, 8.5, 9.1}; -x := Sum(&array); // Note the explicit address-of operator +array := [...]float{7.0, 8.5, 9.1} +x := Sum(&array) // Note the explicit address-of operator@@ -1020,23 +1035,23 @@ any. To read into the first 32 bytes of a larger buffer
b
, slice (here used as a verb) the buffer.- n, err := f.Read(buf[0:32]); + n, err := f.Read(buf[0:32])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.
- var n int; - var err os.Error; - for i := 0; i < 32; i++ { - nbytes, e := f.Read(buf[i:i+1]); // Read one byte. - if nbytes == 0 || e != nil { - err = e; - break; - } - n += nbytes; - } + var n int + var err os.Error + for i := 0; i < 32; i++ { + nbytes, e := f.Read(buf[i:i+1]) // Read one byte. + if nbytes == 0 || e != nil { + err = e + break + } + n += nbytes + }The length of a slice may be changed as long as it still fits within @@ -1051,21 +1066,21 @@ resulting slice is returned. The function uses the fact that
func Append(slice, data[]byte) []byte { - l := len(slice); - if l + len(data) > cap(slice) { // reallocate - // Allocate double what's needed, for future growth. - newSlice := make([]byte, (l+len(data))*2); - // Copy data (could use bytes.Copy()). - for i, c := range slice { - newSlice[i] = c - } - slice = newSlice; - } - slice = slice[0:l+len(data)]; - for i, c := range data { - slice[l+i] = c - } - return slice; + l := len(slice) + if l + len(data) > cap(slice) { // reallocate + // Allocate double what's needed, for future growth. + newSlice := make([]byte, (l+len(data))*2) + // Copy data (could use bytes.Copy()). + for i, c := range slice { + newSlice[i] = c + } + slice = newSlice + } + slice = slice[0:l+len(data)] + for i, c := range data { + slice[l+i] = c + } + return slice }@@ -1096,11 +1111,11 @@ so it's easy to build them during initialization.
var timeZone = map[string] int { - "UTC": 0*60*60, - "EST": -5*60*60, - "CST": -6*60*60, - "MST": -7*60*60, - "PST": -8*60*60, + "UTC": 0*60*60, + "EST": -5*60*60, + "CST": -6*60*60, + "MST": -7*60*60, + "PST": -8*60*60, }@@ -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.
-var seconds int; -var ok bool; +var seconds int +var ok bool seconds, ok = timeZone[tz]@@ -1125,11 +1140,11 @@ Here's a function that puts it together:
func offset(tz string) int { - if seconds, ok := timeZone[tz]; ok { - return seconds - } - log.Stderr("unknown time zone", tz); - return 0; + if seconds, ok := timeZone[tz]; ok { + return seconds + } + log.Stderr("unknown time zone", tz) + return 0 }@@ -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.
-_, present := timeZone[tz]; +_, present := timeZone[tz]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 from the map.
-timeZone["PDT"] = 0, false; // Now on Standard Time +timeZone["PDT"] = 0, false // Now on Standard TimePrinting
@@ -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.-fmt.Printf("Hello %d\n", 23); -fmt.Fprint(os.Stdout, "Hello ", 23, "\n"); -fmt.Println(fmt.Sprint("Hello ", 23)); +fmt.Printf("Hello %d\n", 23) +fmt.Fprint(os.Stdout, "Hello ", 23, "\n") +fmt.Println(fmt.Sprint("Hello ", 23))As mentioned in @@ -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.
-var x uint64 = 1<<64 - 1; -fmt.Printf("%d %x; %d %x\n", x, x, int64(x), int64(x)); +var x uint64 = 1<<64 - 1 +fmt.Printf("%d %x; %d %x\n", x, x, int64(x), int64(x))prints @@ -1204,7 +1219,7 @@ Moreover, that format can print any value, even arrays, structs, and maps. Here is a print statement for the time zone map defined in the previous section.
-fmt.Printf("%v\n", timeZone); // or just fmt.Println(timeZone); +fmt.Printf("%v\n", timeZone) // or just fmt.Println(timeZone)which gives output @@ -1220,15 +1235,15 @@ format
%#v
prints the value in full Go syntax.type T struct { - a int; - b float; - c string; + a int + b float + c string } -t := &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", timeZone); +t := &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", timeZone)prints @@ -1251,7 +1266,7 @@ a space in the format (
% x
) it puts spaces between the bytes.Another handy format is
%T
, which prints the type of a value.-fmt.Printf("%T\n", timeZone); +fmt.Printf("%T\n", timeZone)prints @@ -1266,9 +1281,9 @@ For our simple type
T
, that might look like this.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)to print in the format @@ -1296,7 +1311,7 @@ function
log.Stderr
we used above. It passes its arguments directly// Stderr is a helper function for easy logging to stderr. It is analogous to Fprint(os.Stderr). 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) }@@ -1339,13 +1354,13 @@ sets of values.
type ByteSize float64 const ( - _ = iota; // ignore first value by assigning to blank identifier - KB ByteSize = 1<<(10*iota); - MB; - GB; - TB; - PB; - YB; + _ = iota // ignore first value by assigning to blank identifier + KB ByteSize = 1<<(10*iota) + MB + GB + TB + PB + YB )@@ -1355,21 +1370,21 @@ automatically for printing, even as part of a general type.
func (b ByteSize) String() string { - switch { - case b >= YB: - return fmt.Sprintf("%.2fYB", b/YB) - case b >= PB: - return fmt.Sprintf("%.2fPB", b/PB) - case b >= TB: - return fmt.Sprintf("%.2fTB", b/TB) - case b >= GB: - return fmt.Sprintf("%.2fGB", b/GB) - case b >= MB: - return fmt.Sprintf("%.2fMB", b/MB) - case b >= KB: - return fmt.Sprintf("%.2fKB", b/KB) - } - return fmt.Sprintf("%.2fB", b) + switch { + case b >= YB: + return fmt.Sprintf("%.2fYB", b/YB) + case b >= PB: + return fmt.Sprintf("%.2fPB", b/PB) + case b >= TB: + return fmt.Sprintf("%.2fTB", b/TB) + case b >= GB: + return fmt.Sprintf("%.2fGB", b/GB) + case b >= MB: + return fmt.Sprintf("%.2fMB", b/MB) + case b >= KB: + return fmt.Sprintf("%.2fKB", b/KB) + } + return fmt.Sprintf("%.2fB", b) }@@ -1385,9 +1400,9 @@ initializer can be a general expression computed at run time.
var ( - HOME = os.Getenv("HOME"); - USER = os.Getenv("USER"); - GOROOT = os.Getenv("GOROOT"); + HOME = os.Getenv("HOME") + USER = os.Getenv("USER") + GOROOT = os.Getenv("GOROOT") )@@ -1412,17 +1427,17 @@ correctness of the program state before real execution begins.func init() { - if USER == "" { - log.Exit("$USER not set") - } - if HOME == "" { - HOME = "/usr/" + USER - } - if GOROOT == "" { - GOROOT = HOME + "/go" - } - // GOROOT may be overridden by --goroot flag on command line. - flag.StringVar(&GOROOT, "goroot", GOROOT, "Go root directory") + if USER == "" { + log.Exit("$USER not set") + } + if HOME == "" { + HOME = "/usr/" + USER + } + if GOROOT == "" { + GOROOT = HOME + "/go" + } + // GOROOT may be overridden by --goroot flag on command line. + flag.StringVar(&GOROOT, "goroot", GOROOT, "Go root directory") }@@ -1442,7 +1457,7 @@ then make the receiver for the method a value of that type. type ByteSlice []byte func (slice ByteSlice) Append(data []byte) []byte { - // Body exactly the same as above + // Body exactly the same as above }@@ -1453,9 +1468,9 @@ method can overwrite the caller's slice.
func (p *ByteSlice) Append(data []byte) { - slice := *p; - // Body as above, without the return. - *p = slice; + slice := *p + // Body as above, without the return. + *p = slice }@@ -1464,10 +1479,10 @@ like a standard
Write
method, like this,func (p *ByteSlice) Write(data []byte) (n int, err os.Error) { - slice := *p; - // Again as above. - *p = slice; - return len(data), nil; + slice := *p + // Again as above. + *p = slice + return len(data), nil }@@ -1476,8 +1491,8 @@ then the type
*ByteSlice
satisfies the standard interface print into one.- var b ByteSlice; - fmt.Fprintf(&b, "This hour has %d days\n", 7); + var b ByteSlice + fmt.Fprintf(&b, "This hour has %d days\n", 7)We pass the address of a
ByteSlice
@@ -1521,26 +1536,26 @@ type Sequence []int // Methods required by sort.Interface. func (s Sequence) Len() int { - return len(s) + return len(s) } func (s Sequence) Less(i, j int) bool { - return s[i] < s[j] + return s[i] < s[j] } func (s Sequence) Swap(i, j int) { - s[i], s[j] = s[j], s[i] + s[i], s[j] = s[j], s[i] } // Method for printing - sorts the elements before printing. func (s Sequence) String() string { - sort.Sort(s); - str := "["; - for i, elem := range s { - if i > 0 { - str += " " - } - str += fmt.Sprint(elem); - } - return str + "]"; + sort.Sort(s) + str := "[" + for i, elem := range s { + if i > 0 { + str += " " + } + str += fmt.Sprint(elem) + } + return str + "]" }
Sequence
to a plain
func (s Sequence) String() string { - sort.Sort(s); - return fmt.Sprint([]int(s)); + sort.Sort(s) + return fmt.Sprint([]int(s)) }
@@ -1582,8 +1597,8 @@ type Sequence []int // Method for printing - sorts the elements before printing func (s Sequence) String() string { - sort.IntArray(s).Sort(); - return fmt.Sprint([]int(s)) + sort.IntArray(s).Sort() + return fmt.Sprint([]int(s)) }
@@ -1631,9 +1646,9 @@ The interface to crypto/block
includes:
type Cipher interface { - BlockSize() int; - Encrypt(src, dst []byte); - Decrypt(src, dst []byte); + BlockSize() int + Encrypt(src, dst []byte) + Decrypt(src, dst []byte) } // NewECBDecrypter returns a reader that reads data @@ -1665,7 +1680,7 @@ that implementsHandler
can serve HTTP requests.type Handler interface { - ServeHTTP(*Conn, *Request); + ServeHTTP(*Conn, *Request) }@@ -1678,12 +1693,12 @@ page is visited.
// Simple counter server. type Counter struct { - n int; + n int } func (ctr *Counter) ServeHTTP(c *http.Conn, req *http.Request) { - ctr.n++; - fmt.Fprintf(c, "counter = %d\n", ctr.n); + ctr.n++ + fmt.Fprintf(c, "counter = %d\n", ctr.n) }@@ -1692,8 +1707,8 @@ For reference, here's how to attach such a server to a node on the URL tree.
import "http" ... -ctr := new(Counter); -http.Handle("/counter", ctr); +ctr := new(Counter) +http.Handle("/counter", ctr)But why make
Counter
a struct? An integer is all that's needed. @@ -1704,8 +1719,8 @@ But why makeCounter
a struct? An integer is all that's needed. type Counter int func (ctr *Counter) ServeHTTP(c *http.Conn, req *http.Request) { - *ctr++; - fmt.Fprintf(c, "counter = %d\n", *ctr); + *ctr++ + fmt.Fprintf(c, "counter = %d\n", *ctr) }
@@ -1718,8 +1733,8 @@ has been visited? Tie a channel to the web page. type Chan chan *http.Request func (ch Chan) ServeHTTP(c *http.Conn, req *http.Request) { - ch <- req; - fmt.Fprint(c, "notification sent"); + ch <- req + fmt.Fprint(c, "notification sent") }
@@ -1729,9 +1744,9 @@ It's easy to write a function to print the arguments.
func ArgServer() { - for i, s := range os.Args { - fmt.Println(s); - } + for i, s := range os.Args { + fmt.Println(s) + } }
@@ -1750,7 +1765,7 @@ type HandlerFunc func(*Conn, *Request) // ServeHTTP calls f(c, req). func (f HandlerFunc) ServeHTTP(c *Conn, req *Request) { - f(c, req); + f(c, req) }
@@ -1767,9 +1782,9 @@ to have the right signature.
// Argument server. func ArgServer(c *http.Conn, req *http.Request) { - for i, s := range os.Args { - fmt.Fprintln(c, s); - } + for i, s := range os.Args { + fmt.Fprintln(c, s) + } }
@@ -1780,7 +1795,7 @@ to access IntArray.Sort
.
The code to set it up is concise:
-http.Handle("/args", http.HandlerFunc(ArgServer)); +http.Handle("/args", http.HandlerFunc(ArgServer))
When someone visits the page /args
,
@@ -1813,11 +1828,11 @@ here are their definitions.
type Reader interface { - Read(p []byte) (n int, err os.Error); + Read(p []byte) (n int, err os.Error) } type Writer interface { - Write(p []byte) (n int, err os.Error); + Write(p []byte) (n int, err os.Error) }
@@ -1832,8 +1847,8 @@ to embed the two interfaces to form the new one, like this:
// ReadWrite is the interface that groups the basic Read and Write methods. type ReadWriter interface { - Reader; - Writer; + Reader + Writer }
@@ -1857,8 +1872,8 @@ but does not give them field names. // ReadWriter stores pointers to a Reader and a Writer. // It implements io.ReadWriter. type ReadWriter struct { - *Reader; - *Writer; + *Reader + *Writer }
@@ -1866,8 +1881,8 @@ This struct could be written as
type ReadWriter struct { - reader *Reader; - writer *Writer; + reader *Reader + writer *Writer }
@@ -1877,7 +1892,7 @@ to provide forwarding methods, like this:
func (rw *ReadWriter) Read(p []byte) (n int, err os.Error) { - return rw.reader.Read(p) + return rw.reader.Read(p) }
@@ -1904,8 +1919,8 @@ This example shows an embedded field alongside a regular, named field.
type Job struct { - Command string; - *log.Logger; + Command string + *log.Logger }
@@ -1916,7 +1931,7 @@ a field name, of course, but it's not necessary to do so. And now we can
log to a Job
:
-job.Log("starting now..."); +job.Log("starting now...")
The Logger
is a regular field of the struct and we can initialize
@@ -1924,7 +1939,7 @@ it in the usual way.
func NewJob(command string, logger *log.Logger) *Job { - return &Job{command, logger} + return &Job{command, logger} }
@@ -1936,7 +1951,7 @@ This would be useful if we wanted to refine the methods of Logger
.
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)) }
@@ -2023,16 +2038,16 @@ exits, silently. (The effect is similar to the Unix shell's background.)
-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.
A function literal can be handy in a goroutine invocation.
func Announce(message string, delay int64) { - go func() { - time.Sleep(delay); - fmt.Println(message); - }() // Note the parentheses - must call the function. + go func() { + time.Sleep(delay) + fmt.Println(message) + }() // Note the parentheses - must call the function. }
@@ -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.
-ci := make(chan int); // 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 +ci := make(chan int) // 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
Channels combine communication—the exchange of a value—with @@ -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.
-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. go func() { - list.Sort(); - c <- 1; // Send a signal; value does not matter. -}(); -doSomethingForAWhile(); -<-c; // Wait for sort to finish; discard sent value. + list.Sort() + c <- 1 // Send a signal; value does not matter. +}() +doSomethingForAWhile() +<-c // Wait for sort to finish; discard sent value.
Receivers always block until there is data to receive.
@@ -2095,15 +2110,15 @@ simultaneous calls to process
.
var sem = make(chan int, MaxOutstanding)
func handle(r *Request) {
- sem <- 1; // Wait for active queue to drain.
- process(r); // May take a long time.
- <-sem; // Done; enable next request to run.
+ sem <- 1 // Wait for active queue to drain.
+ process(r) // May take a long time.
+ <-sem // Done; enable next request to run.
}
func Serve(queue chan *Request) {
for {
- req := <-queue;
- go handle(req); // Don't wait for handle to finish.
+ req := <-queue
+ go handle(req) // Don't wait for handle to finish.
}
}
@@ -2119,17 +2134,17 @@ receiving from that channel.
func handle(queue chan *Request) { - for r := range queue { - process(r); - } + for r := range queue { + process(r) + } } func Serve(clientRequests chan *clientRequests, quit chan bool) { - // Start handlers - for i := 0; i < MaxOutstanding; i++ { - go handle(clientRequests) - } - <-quit; // Wait to be told to exit. + // Start handlers + for i := 0; i < MaxOutstanding; i++ { + go handle(clientRequests) + } + <-quit // Wait to be told to exit. }@@ -2148,9 +2163,9 @@ Here's a schematic definition of type
Request
.
type Request struct { - args []int; - f func([]int) int; - resultChan chan int; + args []int + f func([]int) int + resultChan chan int }
@@ -2159,26 +2174,26 @@ a channel inside the request object on which to receive the answer.
func sum(a []int) (s int) { - for _, v := range a { - s += v - } - return + for _, v := range a { + s += v + } + return } request := &Request{[]int{3, 4, 5}, sum, make(chan int)} // Send request -clientRequests <- request; +clientRequests <- request // Wait for response. -fmt.Printf("answer: %d\n", <-request.resultChan); +fmt.Printf("answer: %d\n", <-request.resultChan)
On the server side, the handler function is the only thing that changes.
func handle(queue chan *Request) { - for req := range queue { - req.resultChan <- req.f(req.args); - } + for req := range queue { + req.resultChan <- req.f(req.args) + } }
@@ -2207,7 +2222,7 @@ func (v Vector) DoSome(i, n int, u Vector, c chan int) { for ; i < n; i++ { v[i] += u.Op(v[i]) } - c <- 1; // signal that this piece is done + c <- 1 // signal that this piece is done }
@@ -2217,12 +2232,12 @@ count the completion signals by draining the channel after launching all the goroutines.
-const NCPU = 4 // number of CPU cores +const NCPU = 4 // number of CPU cores 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++ { - 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. for i := 0; i < NCPU; i++ { @@ -2266,14 +2281,14 @@ var freeList = make(chan *Buffer, 100) var serverChan = make(chan *Buffer) func client() { - for { - b, ok := <-freeList; // grab a buffer if available - if !ok { // if not, allocate a new one - b = new(Buffer) - } - load(b); // read next message from the net - serverChan <- b; // send to server - } + for { + b, ok := <-freeList // grab a buffer if available + if !ok { // if not, allocate a new one + b = new(Buffer) + } + load(b) // read next message from the net + serverChan <- b // send to server + } }
@@ -2282,11 +2297,11 @@ and returns the buffer to the free list.
func server() { - for { - b := <-serverChan; // wait for work - process(b); - _ = freeList <- b; // reuse buffer if room - } + for { + b := <-serverChan // wait for work + process(b) + _ = freeList <- b // reuse buffer if room + } }
@@ -2316,7 +2331,7 @@ a simple interface.
type Error interface { - String() string; + String() string }
@@ -2329,13 +2344,13 @@ For example, os.Open
returns an os.PathError
.
// PathError records an error and the operation and
// file path that caused it.
type PathError struct {
- Op string; // "open", "unlink", etc.
- Path string; // The associated file.
- Error Error; // Returned by the system call.
+ Op string // "open", "unlink", etc.
+ Path string // The associated file.
+ Error Error // Returned by the system call.
}
func (e *PathError) String() string {
- return e.Op + " " + e.Path + ": " + e.Error.String();
+ return e.Op + " " + e.Path + ": " + e.Error.String()
}
@@ -2363,15 +2378,15 @@ field for recoverable failures.
for try := 0; try < 2; try++ { - file, err = os.Open(filename, os.O_RDONLY, 0); - if err == nil { - return - } - if e, ok := err.(*os.PathError); ok && e.Error == os.ENOSPC { - deleteTempFiles(); // Recover some space. - continue - } - return + file, err = os.Open(filename, os.O_RDONLY, 0) + if err == nil { + return + } + if e, ok := err.(*os.PathError); ok && e.Error == os.ENOSPC { + deleteTempFiles() // Recover some space. + continue + } + return }@@ -2400,36 +2415,36 @@ An explanation follows. package main import ( - "flag"; - "http"; - "io"; - "log"; - "strings"; - "template"; + "flag" + "http" + "io" + "log" + "strings" + "template" ) var addr = flag.String("addr", ":1718", "http service address") // Q=17, R=18 var fmap = template.FormatterMap{ - "html": template.HTMLFormatter, - "url+html": UrlHtmlFormatter, + "html": template.HTMLFormatter, + "url+html": UrlHtmlFormatter, } var templ = template.MustParse(templateStr, fmap) func main() { - flag.Parse(); - http.Handle("/", http.HandlerFunc(QR)); - err := http.ListenAndServe(*addr, nil); - if err != nil { - log.Exit("ListenAndServe:", err); - } + flag.Parse() + http.Handle("/", http.HandlerFunc(QR)) + err := http.ListenAndServe(*addr, nil) + if err != nil { + log.Exit("ListenAndServe:", err) + } } 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) { - template.HTMLEscape(w, strings.Bytes(http.URLEscape(v.(string)))); + template.HTMLEscape(w, strings.Bytes(http.URLEscape(v.(string)))) } @@ -2508,13 +2523,13 @@ Go is powerful enough to make a lot happen in a few lines.