Futures/Promises Golang方式实现
来源:互联网 发布:安卓拼图游戏源码 编辑:程序博客网 时间:2024/06/06 00:32
原文:http://labs.strava.com/blog/futures-in-golang/
我并没有打算逐字逐句的翻译,我觉得太死板, 所以我把核心大意说一下就好,如果您希望逐字逐句斟酌, 请看原文链接!
通常网络程序中, 大量时间花费在请求和响应上, 如果需要发送的请求比较多, 若以同步方式,则必然是发送请求,等待响应;
然后再发下一个请求并等待结果返回, 这样依次处理,其效率可想而知, 比较低下!若以异步方式,则可将所有请求并行发出,
而每一个请求的响应则以回调方式异步处理,这样效率自然是非常高,但是异步回调方式不直观,并碎片化业务代码!所以比较好
的方案就是: 代码形式是同步的,执行实质是异步的,当属:Futures/Promises, 其它语言早已有之。
见go代码:
package mainimport ( "io/ioutil" "log" "net/http")func RequestFuture(url string) <-chan []byte { c := make(chan []byte, 1) go func() { var body []byte defer func() { c <- body }() resp, err := http.Get(url) if err != nil { return } defer resp.Body.Close() body, _ = ioutil.ReadAll(resp.Body) //同步阻塞调用,直到响应返回。 }() return c}func main() { future := RequestFuture("http://labs.strava.com") // do many other things, maybe create other futures body := <-future log.Printf("response length: %d", len(body))}
以上代码少而直观,不需多言,其缺点为:出错时channel只会返加nil/empty, 调用者拿不掉错误信息, 所以需改进。见go代码:
unc RequestFutureFunction(url string) func() ([]byte, error) { var body []byte var err error c := make(chan struct{}, 1) go func() { defer close(c) //1. 响应拿到了,并闭c. var resp *http.Response resp, err = http.Get(url) if err != nil { return } defer resp.Body.Close() body, err = ioutil.ReadAll(resp.Body)//2.同步阻塞调用,直到响应返回。 }() return func() ([]byte, error) { <-c //3.因为1处关闭了c,则此处不再同步阻塞等待,即响应已拿到,所以向下执行. return body, err }}
func main() { future := RequestFutureFunction("http://strava.com") // do many other things, maybe create other futures body, err := future() log.Printf("response length: %d", len(body)) log.Printf("request error: %v", err)}
以上代码主要改进:调用者可以拿到错误信息,再者以上代码返回的不再是channel而是一个function, 可以多次调用,即多次读取响应而第一个版本,只能从channel中读取一次响应信息。以上代码可以工作得不错, 但是用起来麻烦且不通用, 所以要抽象一下。
见go代码:
func Future(f func() (interface{}, error)) func() (interface{}, error) { var result interface{} var err error c := make(chan struct{}, 1) go func() { defer close(c) result, err = f() }() return func() (interface{}, error) { <-c return result, err }}
func main() { url := "http://labs.strava.com" future := Future(func() (interface{}, error) { resp, err := http.Get(url) if err != nil { return nil, err } defer resp.Body.Close() return ioutil.ReadAll(resp.Body) }) // do many other things b, err := future() body, _ := b.([]byte) log.Printf("response length: %d", len(body)) log.Printf("request error: %v", err)}
以上代码为抽象封装后的代码, 使用时, 需调用者传入同步执行的函数,而以上代码对这个同步函数进行异步封装,成为Futures/Promises.其实代码改进到此处,已经非常明晰好用,只是因为golang不支持C++那样的模板机制, 所以存在:[]byte
-> interface{}
-> []byte
.
这样的数据类型转换,所以在使用时, 如果数据类型不匹配, 则类型转换很可能失败引发运行时异常, 所以此篇
文章作者给出一个方案:代码生成器,实现代码我没看, 估计是不同的类型实现,用id表记,再提供一个工厂方法,
这样就可以以id获取对应数据类型的Futures/Promises代码实现,具体如何,您有时间可以深入研究一下!
注意: 此文章只是我个人笔记, 如有错漏,请一定指正, 共同学习, 我的邮箱: htyu_0203_39@sina.com
1 0
- Futures/Promises Golang方式实现
- Scala 并行和并发编程-Futures 和 Promises
- Promises
- JavaScript中Promises/A+规范的实现
- Golang以OO的方式实现二叉查找树
- GOLANG实现超时对象检测的最好理解的方式
- Golang 获得文件名最快的代码实现方式比较
- Golang以OO的方式实现二叉查找树
- 经典面试题golang实现方式(一)
- 基于promise.js实现nodejs的promises库
- promises/A+协议的实现模块【q】使用心得
- Python3之concurrent.futures实现线程池,进程池
- 【GoLang】Web工作方式
- JavaScript Promises
- JavaScript Promises
- 初识Promises
- 使用Promises
- JavaScript Promises
- 普通8位单片机和STM32单片机复位电路区别
- Java千百问_02基本使用(007)_eclipse变量高亮如何打开
- JZ2440使用tftp下载总结
- 单链表的创建、插入、删除
- VM VirtualBox虚拟机中OracleLinux-R6-U5-Server-x86_64系统下安装oracle11gr2
- Futures/Promises Golang方式实现
- emmet语法和sublime,webstorm快捷键
- 算法数组题
- python列表学习2
- OPEN资讯_更多学习资源-经常浏览
- 在Windows下写了一个shell脚本,上传到Linux下执行时报错
- 同步合成PPT幻灯片与讲演视频
- 现在的努力付出
- xml解析