Google GO (5) – "Effective Go" Notes

Effective GO link

“gofmt” could do the code formatting for you.

Underscore (_), is the blank identifier, provides a way to ignore values returned by a multi-valued expression.

x, _ = f() // ignore second value returned by f()

use range to help for loop

for _, value := range m { // key is unused
sum += value
}

In switch, cases can be presented in comma-seperated lists

switch c {
case ‘ ‘, ‘?’, ‘&’, ‘=’, ‘#’, ‘+’, ‘%’:
return true
}

Switch can be used to discover the dynamic type of an interface variable.

switch t := interfaceValue.(type) {
default:
fmt.Printf(“unexpected type %T”, type); // %T prints type
case bool:
fmt.Printf(“boolean %t\n”, t);
case int:
fmt.Printf(“integer %d\n”, t);
case *bool:
fmt.Printf(“pointer to boolean %t\n”, *t);
case *int:
fmt.Printf(“pointer to integer %d\n”, *t);
}

Functions support multiple returns, such as

func nextInt(b []byte, i int) (int, int)

Named return parameter is initialized by zero, and return by current value if return with no arguments.

Composite literal, could use

return &File{fd, name, nil, 0};

or labels inside

return &File{fd: fd, name: name}

new() returns the pointer with all zeroed memory.

make(T, args) creates slices, maps and channels.

Arrays, when it is passed to a function, it is a copy of the array, not just the pointer.

The size of an array is part of its type, which means [10]int and [20]int are distinct.

len(slice) -> length, cap(slice) -> capacity

In if statement, the expression may be preceded by a simple statement, which executes before the expression is evaluated.

if x := f(); x < y {

Go’s memory sharing design:

Do not communicate by sharing memory; instead, share memory by communicating.

Buffered channel & Unbuffered 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

Channels could be used as semaphore

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.
}