go example之旅(下)
来源:互联网 发布:magento建站 编辑:程序博客网 时间:2024/05/22 16:00
Introduce
这是来自于go by example的例子,花了几天的时间写完了这些例子,感觉对我的帮助很大,对于初学者来说,我的建议还是先找本go的书从头到尾看一下,然后再来看这些例子,每个例子都手敲一遍,对你的帮助还是很大的。在敲这些例子的过程中,有一些疑问,也有一些知识的扩充,因此总结了本文。
time和channel
golang的time package带有定时器的功能,而定时器和channel完美融合,创建一个定时器会返回一个channel,在定时器到期之前读这个channel是阻塞的,直到定时时间到达这个channel就会变成可读的。
func main() { //创建了一个定时器,2秒后会发送事件到timer1.C channel timer1 := time.NewTimer(time.Second * 2) //等待定时器到期 data := <-timer1.C //接收到的数据 2016-07-16 15:24:19.337701998 +0800 CST fmt.Println("Timer 1 expired") fmt.Println("Timer 1 expired",data) timer2 := time.NewTimer(time.Second) go func() { <- timer2.C fmt.Println("Timer 2 expired") }() //关闭定时器 stop2 := timer2.Stop() if stop2 { fmt.Println("Timer 2 stopped") }}
time package除了具有定时器的功能外,还有一个Ticker,Ticker同样也是和channel完美融合的一个功能,创建一个Ticker会返回channel
通过range这个channel。来表示每次interval的到来。再结合go的协程就很容易实现一个定时任务的功能。
func main() { //创建了定时器,每time.Millisecond * 500就产生事件,发送到chnanel ticker := time.NewTicker(time.Millisecond * 500) go func() { for t := range ticker.C { fmt.Println("Tick at",t) } }() //睡上一段事件,然后关闭 time.Sleep(time.Millisecond * 1600) ticker.Stop() fmt.Println("Ticker stopped")}
goroutines和work pool
goroutines结合channel很容易就可以实现一个work pool,开上N个goroutines,然后这N个goroutines共同去读channel,读到channel
就去执行相应的工作,然后结果通过另外一个channel传出来即可,模型很简单。用go实现起来还是很容易的。
func worker(id int,jobs <-chan int,result chan<- int) { for j := range jobs { fmt.Println("worker",id,"processing job",j) time.Sleep(time.Second) result <- j * 2 }}func main() { jobs := make(chan int,100) results := make(chan int,100) //启动三个worker for w := 1; w <= 3; w++ { go worker(w,jobs,results) } //循环9次,发送任务 for j := 1; j <= 9;j++ { jobs <- j } close(jobs) //循环得到结果 for a := 1; a <= 9; a++ { <-results }}
rate limiting与channel
限速这是一个用于控制资源利用率和保证服务质量的一种机制,golang通过goroutines,channel还有tickers优雅的支持了这个机制。比如处理web请求的限速,每接收一个请求就先读取一个tick,这个tick每隔固定时间才可读,这样就可以实现限速的功能。
func main() { requests := make(chan int,5) //发送五条消息 for i := 1; i <= 5;i++ { requests <- i } close(requests) //创建了定时器,然后遍历channel,打印信息 limiter := time.Tick(time.Millisecond * 200) for req := range requests { <-limiter //每隔time.Millisecond * 200,起到了限速的作用 fmt.Println("requests",req,time.Now()) }}
但是上面的限速存在一个问题,就是并发数只有1,如果可以在拥有固定的并发数的情况下限速呢?,这就需要借助channel的buffer功能了。上面的time.Tick返回的channel是没有buffer的,所以一次只能处理一个请求,如果这个channel是有buffer的,比如这个buffer的大小是N那么可以同时并发接收N个请求,想处理第N+1个请求就需要等待固定时间才可以。
func main() { //创建了另外一个time.Time类似的channel burstyLimiter := make(chan time.Time,3) //发送三个 for i := 0; i < 3; i++ { burstyLimiter <- time.Now() } go func() { for t := range time.Tick(time.Millisecond * 200) { burstyLimiter <- t //每200 * time.Millisecond 就发送一个事件到burstyLimiter } }() burstyRequests := make(chan int,5) for i := 1; i <= 5; i++ { burstyRequests <- i //发送五个数据 } close(burstyRequests) for req := range burstyRequests { //现在开始限速读取 <-burstyLimiter//在读前三个的时候是不会阻塞的,直到读取第四个的 时候才开始通过Limiter限速 fmt.Println("request",req,time.Now()) }}
自定义sort和Interface
golang的sort package自带排序的功能,但是如果要对用户自己定义的数据结构进行排序这就不好半了,在C++中要求用户对关系运算符重载即可在golang中则需要和interface完美融合,只要用户实现Len,Less,Swap三个接口即可,就是这么简单。
package mainimport "fmt"import "sort"//string slice的别名,给这个别名struct 添加方法type ByLength []stringfunc (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])}//sort接口需要实现 Swap Less和len即可func main() { fruits := []string{"peach","banana","kiwi"} sort.Sort(ByLength(fruits)) fmt.Println(fruits)}
signal和channel
golang再一次将unix上的signals和channel结合了起来,unix上通过给信号注册处理函数来完成信号处理,在golang中,通过把信号和channel关联起来,当有信号到来channel就可读了。返回的结果就是signal的号码。
import "fmt"import "os"import "os/signal"import "syscall"func main() { //os.Signal类型的chn sigs := make(chan os.Signal,1) done := make(chan bool,1) //通过Norify来注册信号, signal.Notify(sigs,syscall.SIGINT,syscall.SIGTERM) //将SIGINT和SIGTERM和sigs channel结合起来 //协成来收集信号,然后发送done chan来表示完成 go func() { sig := <-sigs fmt.Println() fmt.Println(sig) done <- true }() fmt.Println("awaiting signal") <-done fmt.Println("exiting")}
- go example之旅(下)
- go example之旅(上)
- go example之旅(中)
- go by example 之arrays.go
- go by example之channel-synchronization.go
- go-kit 上手之example stringsvc2 添加日志和监控
- go-kit 上手之example stringsvc1 函数即服务
- Go by Example: Values
- Go by Example: Variables
- Go by Example: Constants
- Go by Example: For
- Go by Example: Switch
- Go by Example: Arrays
- Go by Example: Slices
- Go by Example: Maps
- Go by Example: Range
- Go by Example: Functions
- Go by Example: Closures
- Dalvik虚拟机【2】——Dex文件格式
- 并查集想法
- C++使用外部库开发的环境配置
- MySQL索引类型总结
- 士兵队列训练问题
- go example之旅(下)
- 从尾到头打印链表
- 【JZOJ 4639】Angel Beats!
- 计算机英语
- spring常用注解使用讲解
- 定位new运算符
- 关于R语言字符型数据清洗问题
- NOIP2002提高组第1题 均分纸牌
- Html css 前端学习