Go语言圣经习题练习_1.6并发获取多个URL
练习 1.10: 找一个数据量比较大的网站,用本小节中的程序调研网站的缓存策略,对每个URL执行两遍请求,查看两次时间是否有较大的差别,并且每次获取到的响应内容是否一致,修改本节中的程序,将响应结果输出,以便于进行对比。
练习 1.11: 在fatchall中尝试使用长一些的参数列表,比如使用在alexa.com的上百万网站里排名靠前的。如果一个网站没有回应,程序将采取怎样的行为?(Section8.9 描述了在这种情况下的应对机制)。
package main import (
"fmt"
"io/ioutil"
"net/http"
"os"
"time"
"strings"
"io"
"sort"
)
func fetchUrl(url string, ch chan <- map[string]string) { //使用map记录,url -> response
start := time.Now()
resp,err := http.Get(url)
result := make(map[string]string)
if err != nil {
result[url] = fmt.Sprintf("http-get: %v",err)
ch <- result
return
}
nbytes,err := io.Copy(ioutil.Discard,resp.Body)
if err != nil {
result[url] = fmt.Sprintf("while reading:%v %v",url,err)
ch <- result
return
} resp.Body.Close()
secs := time.Since(start).Seconds()
//fmt.Printf("%v %v %v Bytes %v's\n",url,resp.Status,nbytes,secs)
result[url] = fmt.Sprintf("%v %v %v Bytes %v's",url,resp.Status,nbytes,secs)
ch <- result } func main() {
start := time.Now()
ch := make(chan map[string]string)
count := 0
for _,url := range os.Args[1:] {
if ! strings.HasPrefix(url,"htto") {
url = "http://" + url
}
fmt.Printf("start fetch %v\n",url)
go fetchUrl(url,ch) // 重复3次
go fetchUrl(url,ch)
go fetchUrl(url,ch)
count += 3
}
result := make(map[string]string)
keys := []string{}
for i:=0;i<count;i++{
for k,v := range <-ch {
result[k] = v
keys = append(keys,k)
}
}
sort.Strings(keys) //按照url排序
for _,k := range keys {
fmt.Printf("%s : %s\n",k,result[k]) //输出按照URL排序后的结果
}
fmt.Printf("done, use %v seconds",time.Since(start).Seconds())
}
运行测试
go run main.go baidu.com sina.cn 163.com google.cn qq.com weibo.cn
start fetch http://baidu.com
start fetch http://sina.cn
start fetch http://163.com
start fetch http://google.cn
start fetch http://qq.com
start fetch http://weibo.cn
http://163.com : http://163.com 200 OK 648796 Bytes 0.8530488's
http://163.com : http://163.com 200 OK 648796 Bytes 0.8530488's
http://163.com : http://163.com 200 OK 648796 Bytes 0.8530488's
http://baidu.com : http://baidu.com 200 OK 81 Bytes 0.0630036's
http://baidu.com : http://baidu.com 200 OK 81 Bytes 0.0630036's
http://baidu.com : http://baidu.com 200 OK 81 Bytes 0.0630036's
http://google.cn : http://google.cn 200 OK 3213 Bytes 0.3580205's
http://google.cn : http://google.cn 200 OK 3213 Bytes 0.3580205's
http://google.cn : http://google.cn 200 OK 3213 Bytes 0.3580205's
http://qq.com : http://qq.com 200 OK 248761 Bytes 0.3360192's
http://qq.com : http://qq.com 200 OK 248761 Bytes 0.3360192's
http://qq.com : http://qq.com 200 OK 248761 Bytes 0.3360192's
http://sina.cn : http://sina.cn 200 OK 14147 Bytes 0.1520087's
http://sina.cn : http://sina.cn 200 OK 14147 Bytes 0.1520087's
http://sina.cn : http://sina.cn 200 OK 14147 Bytes 0.1520087's
http://weibo.cn : http://weibo.cn 200 OK 5293 Bytes 0.3700212's
http://weibo.cn : http://weibo.cn 200 OK 5293 Bytes 0.3700212's
http://weibo.cn : http://weibo.cn 200 OK 5293 Bytes 0.3700212's
done, use 0.8830505 seconds
Go语言圣经习题练习_1.6并发获取多个URL的更多相关文章
- Go语言圣经习题练习_1.7. Web服务
练习 1.12: 修改Lissajour服务,从URL读取变量,比如你可以访问 http://localhost:8000/?cycles=20 这个URL,这样访问可以将程序里的cycles默认的5 ...
- Go语言圣经习题练习_1.4. GIF动画
练习 1.5: 修改前面的Lissajous程序里的调色板,由黑色改为绿色.我们可以用color.RGBA{0xRR, 0xGG, 0xBB, 0xff}来得到#RRGGBB这个色值,三个十六进制的字 ...
- Go语言圣经习题练习_1.5. 获取URL
练习 1.7: 函数调用io.Copy(dst, src)会从src中读取内容,并将读到的结果写入到dst中,使用这个函数替代掉例子中的ioutil.ReadAll来拷贝响应结构体到os.Stdout ...
- [日常] GO语言圣经-并发获取多个URL
go语言圣经-并发获取多个URL 1.GO最新奇的特性就是对并发编程的支持,goroutine和channel 2.goroutine是一种函数的并发执行方式,而channel是用来在goroutin ...
- golang学习 ---并发获取多个URL
package main import ( "fmt" "io" "io/ioutil" "net/http" &quo ...
- [日常] Go语言圣经-WEB服务与习题
Go语言圣经-web服务 1.Web服务程序,标准库里的方法已经帮我们完成了大量工作 2.main函数将所有发送到/路径下的请求和handler函数关联起来,/开头的请求其实就是所有发送到当前站点上的 ...
- [日常] Go语言圣经--接口约定习题
Go语言圣经-接口1.接口类型是对其它类型行为的抽象和概括2.Go语言中接口类型的独特之处在于它是满足隐式实现的3.Go语言中还存在着另外一种类型:接口类型.接口类型是一种抽象的类型4.一个类型可以自 ...
- [日常] Go语言圣经-Panic异常,Recover捕获异常习题
Go语言圣经-Panic异常1.当panic异常发生时,程序会中断运行,并立即执行在该goroutine中被延迟的函数(defer 机制)2.不是所有的panic异常都来自运行时,直接调用内置的pan ...
- [日常] Go语言圣经-匿名函数习题
Go语言圣经-匿名函数1.拥有函数名的函数只能在包级语法块中被声明,通过函数字面量(function literal),我们可绕过这一限制,在任何表达式中表示一个函数值2.通过这种方式定义的函数可以访 ...
随机推荐
- ansible(三)
一.setup模块(收集信息 ) 1.ansible中的setup模块可以收集到的信息 ansible web -m setup ansible_all_ipv4_addresses # ipv4的所 ...
- pytorch实现yolov3(2) 配置文件解析及各layer生成
配置文件 配置文件yolov3.cfg定义了网络的结构 .... [convolutional] batch_normalize=1 filters=64 size=3 stride=2 pad=1 ...
- JVM底层实现与总结
一.类加载器 1.BootstrapClassLoader(启动类加载器) 它主要负责加载%JAVA_HOME%/jre/lib,-Xbootclasspath参数指定的路径以及%JAVA_HOME% ...
- 【Mac】Mac快捷键与Mac下的Idea快捷键
本人之前一直在windows平台下进行开发,刚接触Mac的时候有些许的不适应,无论是无鼠标操作,还是文件系统的变更,以及键盘格式以及系统快捷键的变更,都曾对自己造成过一定程度的困扰. ...
- java虚拟机-GC-GC算法
在C/C++中是由程序员自己去申请.管理和释放内存的,因此没有GC的概念.而在Java中,专门有一个用于垃圾回收的后台线程来进行监控.扫描,自动将一些无用的内存进行释放.下面介绍几种常见的GC算法. ...
- Linux虚拟机怎么添加磁盘?
一.VMware workstation菜单栏
- 跟我学SpringCloud | 第十二篇:Spring Cloud Gateway初探
SpringCloud系列教程 | 第十二篇:Spring Cloud Gateway初探 Springboot: 2.1.6.RELEASE SpringCloud: Greenwich.SR1 如 ...
- scrapy基础知识之 Scrapy 和 scrapy-redis的区别:
Scrapy 和 scrapy-redis的区别 Scrapy 是一个通用的爬虫框架,但是不支持分布式,Scrapy-redis是为了更方便地实现Scrapy分布式爬取,而提供了一些以redis为基础 ...
- 【无线安全实践入门】网络扫描和ARP欺骗
文中可能存在错误操作或错误理解,望大家不吝指正. 同时也希望可以帮助到想要学习接触此方面.或兴趣使然的你,让你有个大概的印象. !阅前须知! 本文是基于我几年前的一本笔记本,上面记录了我学习网络基础时 ...
- TypeScript算法与数据结构-队列和循环队列
本文涉及的源码,均在我的github.有两部分队列和循环队列.有问题的可以提个issue,看到后第一时间回复 1. 队列(Queue) 队列也是一种线性的数据结构, 队列是一种先进先出的数据结构.类似 ...