1、Timeouts 超时
package main
import (
"fmt"
"time"
)
func main() {
c1:=make(chan string,1)
go func() {
time.Sleep(2*time.Second)
c1<-"result 1"
}()
select {
case res:=<-c1:
fmt.Println(res)
case <-time.After(1*time.Second):
fmt.Println("timeout 1")
}
c2:=make(chan string,1)
go func() {
time.Sleep(2*time.Second)
c2<-"result 2"
}()
select {
case res:=<-c2:
fmt.Println(res)
case <-time.After(3*time.Second):
fmt.Println("timeout 2")
}
}
/*
timeout 1
result 2
*/
2、Non-Blocking Channel Operations 非阻塞通道
通道中被阻塞,我们使用select来实现非阻塞发送。
package main
import "fmt"
func main(){
jobs:=make(chan int,5)
done:=make(chan bool)
go func(){
for{
j,more:=<-jobs
if more{
fmt.Println("received job",j)
}else{
fmt.Println("received all jobs")
done<-true
return
}
}
}
for j:=1;j<=3;j++{
jobs<-j
fmt.Println("sent job",j)
}
close(jobs)
fmt.Println("sent all jobs")
<-done
}
/*
*/
3、closing channels 关闭通道
package main
import "fmt"
func main() {
jobs:=make(chan int,5)
done:=make(chan bool)
go func() {
for {
j,more:=<-jobs
if more{
fmt.Println("received job",j)
}else{
fmt.Println("received all job")
done<-true
return
}
}
}()
for j:=0;j<=3;j++ {
jobs<-j
fmt.Println("sent job",j)
}
close(jobs)
fmt.Println("sent all jobs")
<-done
}
/*
sent job 0
received job 0
received job 1
sent job 1
sent job 2
sent job 3
sent all jobs
received job 2
received job 3
received all job
Process finished with the exit code 0
*/
4、Range over Channels
通过range 来遍历channels
package main
import "fmt"
func main(){
queue:=make(chan string,2)
queue<-"one"
queue<-"two"
close(queue)
for elem:=range queue{
fmt.Println(elem)
}
}
/*
one
two
*/
5、timer
package main
import (
"fmt"
"time"
)
func main() {
timer1:=time.NewTimer(2*time.Second)
<-timer1.C
fmt.Println("timer 1 fired")
timer2:=time.NewTimer(time.Second)
go func() {
<-timer2.C
fmt.Println("Timer 2 fired")
}()
stop2:=timer2.Stop()
if stop2{
fmt.Println("timer 2 stopped")
}
time.Sleep(2*time.Second)
}
/*
timer 1 fired
timer 2 stopped
*/
6、Tickers
package main
import (
"fmt"
"time"
)
func main() {
ticker:=time.NewTicker(500*time.Millisecond)
done:=make(chan bool)
go func() {
for {
select {
case <-done:
return
case t:=<-ticker.C:
fmt.Println("ticker at",t)
}
}
}()
time.Sleep(1600*time.Millisecond)
ticker.Stop()
done<-true
fmt.Println("Ticker stopped")
}
/*
ticker at 2021-07-30 15:20:32.8857464 +0800 CST m=+0.508700601
ticker at 2021-07-30 15:20:33.3872252 +0800 CST m=+1.010179401
ticker at 2021-07-30 15:20:33.8872464 +0800 CST m=+1.510200601
Ticker stopped
*/
6、worker pools 工作池
package main
import (
"fmt"
"time"
)
func Worker(id int,jobs <-chan int,result chan<-int) {
for j:=range jobs{
fmt.Println("worker",id,"started job",j)
time.Sleep(time.Second)
fmt.Println("worker",id,"finished job",j)
result<-j*2
}
}
func main() {
const numJobs =5
jobs:=make(chan int,numJobs)
results:=make(chan int,numJobs)
for w:=1;w<=3;w++{
go Worker(w,jobs,results)
}
for j:=1;j<=numJobs;j++{
jobs<-j
}
close(jobs)
for a:=1;a<=numJobs;a++{
<-results
}
}
7、WaitGroups 等待组
package main
import (
"fmt"
"sync"
"time"
)
func work(id int,wg *sync.WaitGroup) {
defer wg.Done()
fmt.Printf("worker %d starting\n",id)
time.Sleep(time.Second)
fmt.Printf("worker %d done\n",id)
}
func main() {
var wg sync.WaitGroup
for i:=1;i<=5;i++{
wg.Add(1)
go work(i,&wg)
}
wg.Wait()
}
8、Rate Limiting
package main
import (
"fmt"
"time"
)
func main() {
requests:=make(chan int,5)
for i:=1;i<=5;i++{
requests<-i
}
close(requests)
limiter:=time.Tick(200*time.Millisecond)
for req:=range requests{
<-limiter
fmt.Println("request",req,time.Now())
}
burstyLimiter:=make(chan time.Time,3)
for i:=0;i<3;i++{
burstyLimiter<-time.Now()
}
go func() {
for t:=range time.Tick(200*time.Millisecond){
burstyLimiter<-t
}
}()
burstyRequest:=make(chan int,5)
for i:=1;i<=5;i++{
burstyRequest<-i
}
close(burstyRequest)
for req:=range burstyRequest{
<-burstyLimiter
fmt.Println("request",req,time.Now())
}
}
9、Atimic Counters 原子计数器
package main
import (
"fmt"
"sync"
"sync/atomic"
)
func main() {
var ops uint 64
var wg sync.WaitGroup
for i:=0;i<50;i++{
wg.Add(1)
go func() {
for c:=0;c<1000;c++{
atomic.AddUint64(&ops,1)
}
wg.Done()
}()
}
wg.Wait()
fmt.Println("ops:",ops)
}
10、Mutexes 互斥器
package main
import (
"fmt"
"math/rand"
"sync"
"sync/atomic"
"time"
)
func main() {
var state = make(map[int]int)
var mutex = &sync.Mutex{}
var readOps uint64
var writeOps uint64
for r := 0; r < 100; r++ {
go func() {
total := 0
for {
key := rand.Intn(5)
mutex.Lock()
total += state[key]
mutex.Unlock()
atomic.AddUint64(&readOps, 1)
time.Sleep(time.Millisecond)
}
}()
}
for w := 0; w < 10; w++ {
go func() {
for {
key := rand.Intn(5)
val := rand.Intn(100)
mutex.Lock()
state[key] = val
mutex.Unlock()
atomic.AddUint64(&writeOps, 1)
time.Sleep(time.Millisecond)
}
}()
}
time.Sleep(time.Second)
readOpsFinal := atomic.LoadUint64(&readOps)
fmt.Println("readOps:", readOpsFinal)
writeOpsFinal := atomic.LoadUint64(&writeOps)
fmt.Println("writeOps:", writeOpsFinal)
mutex.Lock()
fmt.Println("state:", state)
mutex.Unlock()
}
11、Stateful Goroutines有状态的协程
package main
import (
"fmt"
"math/rand"
"sync/atomic"
"time"
)
type readOp struct {
key int
resp chan int
}
type writeOp struct {
key int
val int
resp chan bool
}
func main() {
var readOps uint64
var writeOps uint64
reads := make(chan readOp)
writes := make(chan writeOp)
go func() {
var state = make(map[int]int)
for {
select {
case read := <-reads:
read.resp <- state[read.key]
case write := <-writes:
state[write.key] = write.val
write.resp <- true
}
}
}()
for r := 0; r < 100; r++ {
go func() {
for {
read := readOp{
key: rand.Intn(5),
resp: make(chan int)}
reads <- read
<-read.resp
atomic.AddUint64(&readOps, 1)
time.Sleep(time.Millisecond)
}
}()
}
for w := 0; w < 10; w++ {
go func() {
for {
write := writeOp{
key: rand.Intn(5),
val: rand.Intn(100),
resp: make(chan bool)}
writes <- write
<-write.resp
atomic.AddUint64(&writeOps, 1)
time.Sleep(time.Millisecond)
}
}()
}
time.Sleep(time.Second)
readOpsFinal := atomic.LoadUint64(&readOps)
fmt.Println("readOps:", readOpsFinal)
writeOpsFinal := atomic.LoadUint64(&writeOps)
fmt.Println("writeOps:", writeOpsFinal)
}
12、Sorting
package main
import (
"fmt"
"sort"
)
func main() {
str:=[] string{"c","a","b"}
sort.Strings(str)
fmt.Println("string",str)
ints:=[] int {7,2,4}
sort.Ints(ints)
fmt.Println("Ints",ints)
s:=sort.IntsAreSorted(ints)
fmt.Println("Sorted",s)
}
13、SortingByFunctions 通过函数排序
go 中的排序算法用的快排,当max<11时用的堆排,总体来说是快排结合堆排
package main
import (
"fmt"
"sort"
)
type byLength [] string
func (s byLength) Len() int {
return len(s)
}
func (s byLength) Swap(i,j int) {
s[i],s[j]=s[j],s[i]
}
func (s byLength) Less(i,j int)bool {
return len(s[i])<len(s[j])
}
func main() {
fruits:=[]string{"perch","banna","kiwi"}
sort.Sort(byLength(fruits))
fmt.Println(fruits)
}
14、panic
用来判定潜在的错误,通常我们用panic来表示程序正常运行不应该出现的错误。
package main
import "os"
func main() {
panic("a problem")
_,err:=os.Create("/tmp/file")
if err!=nil{
panic(err)
}
}
/*
panic: a problem
*/
15、defer 延迟
package main
import "fmt"
func main() {
defer fmt.Println("1")
defer fmt.Println("2")
defer fmt.Println("3")
fmt.Println("4")
}
返回 4 3 2 1
15、stringFunc 字符串函数
package main
import (
"fmt"
"strings"
)
var p=fmt.Println
func main() {
p("contains:",strings.Contains("test","es"))
p("count:",strings.Count("trst","t"))
p("hasPrefix:",strings.HasSuffix("test","te"))
p("index:",strings.Index("test","e"))
p("join:",strings.Join([]string{"a","b"},"."))
p("Repeat:",strings.Repeat("a",5))
p("Split:",strings.Split("a-b-c-d-e","-"))
p("ToLower:",strings.ToLower("StringS"))
p("Toupper:",strings.ToUpper("StringS"))
p()
p("len:",len("hello"))
p("char","hello"[1])
}
16、String Formatting 字符串格式
package main
import (
"fmt"
"os"
)
type point struct {
x, y int
}
func main() {
p := point{1, 2}
fmt.Printf("%v\n", p)
fmt.Printf("%+v\n", p)
fmt.Printf("%#v\n", p)
fmt.Printf("%T\n", p)
fmt.Printf("%t\n", true)
fmt.Printf("%d\n", 123)
fmt.Printf("%b\n", 14)
fmt.Printf("%c\n", 33)
fmt.Printf("%x\n", 456)
fmt.Printf("%f\n", 78.9)
fmt.Printf("%e\n", 123400000.0)
fmt.Printf("%E\n", 123400000.0)
fmt.Printf("%s\n", ""string"")
fmt.Printf("%q\n", ""string"")
fmt.Printf("%x\n", "hex this")
fmt.Printf("%p\n", &p)
fmt.Printf("|%6d|%6d|\n", 12, 345)
fmt.Printf("|%6.2f|%6.2f|\n", 1.2, 3.45)
fmt.Printf("|%-6.2f|%-6.2f|\n", 1.2, 3.45)
fmt.Printf("|%6s|%6s|\n", "foo", "b")
fmt.Printf("|%-6s|%-6s|\n", "foo", "b")
s := fmt.Sprintf("a %s", "string")
fmt.Println(s)
fmt.Fprintf(os.Stderr, "an %s\n", "error")
}