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 syntax of the regular expressions accepted is:
-
- regexp:
- concatenation { '|' concatenation }
- concatenation:
- { closure }
- closure:
- term [ '*' | '+' | '?' ]
- term:
- '^'
- '$'
- '.'
- character
- '[' [ '^' ] character-ranges ']'
- '(' regexp ')'
+ The regexp package implements a simple library for
+ regular expressions.
+
+ The syntax of the regular expressions accepted is:
+
+ 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()
}
-
-
-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.
+not like this
+if i < f() // wrong!
+{ // wrong!
+ g()
+}
+
+
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 range 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 array a 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 @@ of io.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 declara
type 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 SyncedBuffer
Constructors and composite literals
@@ -816,15 +831,15 @@ package os.
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 make()
@@ -927,15 +942,15 @@ These examples illustrate the difference between 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 Time
Printing
@@ -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 + "]"
}
@@ -1554,8 +1569,8 @@ effort if we convert the 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 implements Handler 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 make Counter 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.
--
2.52.0