not all these need to be in the tour, and many are in effective go, but for the
record:
- runes and rune constants
- constant promotion
- the blank identifier
- the zero value
- initialization of local variables
- taking the address of a local variable
- init() functions
- defer
- panic and recover
- multi-file packages
- universe, package, file scope
- compilation
- godoc
- gofmt
- arrays
- pointer vs. value receiver
- resizing, reslicing, append, and copy
- embedding interfaces
- embedding structs
- type assertions
- interface-to-value, value-to-interface, interface-to-interface assignment
- type switch
- reflection
- segmented stacks
- the function-returning-channel idiom
- typed directional channels
some examples from the go course:
===
random bit generator
c := make(chan int)
go func() {
for {
fmt.Println(<-c)
} }()
for { select {
case c <- 0: // no statement, no fall through
case c <- 1:
}
}
===
timeout
select {
case v := <-ch:
fmt.Println("received", v)
case <-time.After(30*1e9):
fmt.Println("timed out after 30 seconds")
}
===
muxing server (in the tutorial)
type request struct { a,b int
replyc chan int
}
type binOp func(a, b int) int
func run(op binOp, req *request) {
req.replyc <- op(req.a, req.b)
}
func server(op binOp, service <-chan *request) {
for {
req := <-service // requests arrive here
go run(op, req) // don't wait for op
}
}
func startServer(op binOp) chan<- *request {
service := make(chan *request)
go server(op, req)
return service
}
adderChan := startServer(
func(a, b int) int { return a + b }
)
func (r *request) String() string {
return fmt.Sprintf("%d+%d=%d",
r.a, r.b, <-r.replyc)
}
req1 := &request{7, 8, make(chan int)}
req2 := &request{17, 18, make(chan int)}
adderChan <- req1
adderChan <- req2
Can retrieve results in any order; r.replyc demuxes:
fmt.Println(req2, req1)
===
chaining
package main
import ("flag"; "fmt")
var nGoroutine = flag.Int("n", 100000, "how many")
func f(left, right chan int) { left <- 1 + <-right }
func main() {
flag.Parse()
leftmost := make(chan int)
var left, right chan int = nil, leftmost
for i := 0; i < *nGoroutine; i++ {
left, right = right, make(chan int)
go f(left, right) }
right <- 0 // bang!
x := <-leftmost // wait for completion
fmt.Println(x) // 100000
}
===
channel as buffer cache
var freeList = make(chan *Buffer, 100)
var serverChan = make(chan *Buffer)
func server() {
for {
b := <-serverChan // Wait for work to do.
process(b) // Process the request in buffer.
select {
case freeList <- b: // Reuse buffer if room.
default:
} }}
func client() {
for {
// Otherwise drop it.
var b *Buffer
select {
case b = <-freeList:
default: b = new(Buffer) // Allocate if not.
}
load(b) // Read next request into b.
serverChan <- b // Send request to server.
// Grab one if available.
} }
====
also: the fan-out database example