// Like a C for
forinit;condition;post{}// Like a C while
forcondition{}// Like a C for(;;)
for{}//If you're looping over an array, slice, string, or map, or reading from a channel, a range clause can manage the loop.
forkey,value:=rangeoldMap{newMap[key]=value}//If you only need the first item in the range (the key or index), drop the second:
forkey:=rangem{ifkey.expired(){delete(m,key)}}//If you only need the second item in the range (the value), use the blank identifier, an underscore, to discard the first:
sum:=0for_,value:=rangearray{sum+=value}
defer
Defer
Deferred functions are executed in LIFO order when return
funcPrintf(formatstring,v...interface{})(nint,errerror){}// v is any number of any type
// btw, below is the usage of ...
funcMin(a...int)int{min:=int(^uint(0)>>1)// largest int
for_,i:=rangea{ifi<min{min=i}}returnmin}
interface
Go type 不需要显示声明它实现了接口,仅通过实现接口来实现接口
1
2
3
4
5
6
7
8
9
// embedding
typeJobstruct{Commandstring*log.Logger// as implement interface
}func(job*Job)Printf(formatstring,args...interface{}){job.Logger.Printf("%q: %s",job.Command,fmt.Sprintf(format,args...))}
concurrency
Do not communicate by sharing memory; instead, share memory by communicating.
add go before func to make it run concurrently
1
2
3
4
5
6
funcAnnounce(messagestring,delaytime.Duration){gofunc(){time.Sleep(delay)fmt.Println(message)}()// Note the parentheses - must call the function.
}
on above, go func is closures, how to sent signal? Use channels
channels
channels like the slide with semaphore.
1
2
3
4
// init
// if no buffer, <-ci wait until something -> ci
ci:=make(chanint)//no buffer
cj:=make(chanint,10)//buffer
// 不能确保 req 是唯一的
funcServe(queuechan*Request){forreq:=rangequeue{sem<-1gofunc(){process(req)// Buggy; see explanation below.
<-sem}()}}//solve1: args sent to func
funcServe(queuechan*Request){forreq:=rangequeue{sem<-1gofunc(req*Request){process(req)<-sem}(req)}}//solve2: redeclear
funcServe(queuechan*Request){forreq:=rangequeue{req:=req// Create new instance of req for the goroutine.
sem<-1gofunc(){process(req)<-sem}()}}
server by channels
1
2
3
4
5
6
7
8
9
10
11
12
13
funchandle(queuechan*Request){forr:=rangequeue{process(r)}}funcServe(clientRequestschan*Request,quitchanbool){// Start handlers
fori:=0;i<MaxOutstanding;i++{gohandle(clientRequests)}<-quit// Wait to be told to exit.
}
go concurrency
涉及到并发 data race 都需要用锁。
如果不需要等待,那么可以用 mutex
若需要等待,
chan := make(channel bool)
var wg sync.WaitGroup
var mu sync.Mutex
cond := sync.NewCond(&mu) // 需要用到 broadcast 的地方才需要 cond,不然直接 chan
go channels: synchronous communication mechanism
如果是 unbuffer channels,那么无论是只有发送方还是只有接收方,都会造成阻塞,因为 channels 的本质是同步(buffer channel 也只会延迟这个过程)。