练习 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的更多相关文章

  1. Go语言圣经习题练习_1.7. Web服务

    练习 1.12: 修改Lissajour服务,从URL读取变量,比如你可以访问 http://localhost:8000/?cycles=20 这个URL,这样访问可以将程序里的cycles默认的5 ...

  2. Go语言圣经习题练习_1.4. GIF动画

    练习 1.5: 修改前面的Lissajous程序里的调色板,由黑色改为绿色.我们可以用color.RGBA{0xRR, 0xGG, 0xBB, 0xff}来得到#RRGGBB这个色值,三个十六进制的字 ...

  3. Go语言圣经习题练习_1.5. 获取URL

    练习 1.7: 函数调用io.Copy(dst, src)会从src中读取内容,并将读到的结果写入到dst中,使用这个函数替代掉例子中的ioutil.ReadAll来拷贝响应结构体到os.Stdout ...

  4. [日常] GO语言圣经-并发获取多个URL

    go语言圣经-并发获取多个URL 1.GO最新奇的特性就是对并发编程的支持,goroutine和channel 2.goroutine是一种函数的并发执行方式,而channel是用来在goroutin ...

  5. golang学习 ---并发获取多个URL

    package main import ( "fmt" "io" "io/ioutil" "net/http" &quo ...

  6. [日常] Go语言圣经-WEB服务与习题

    Go语言圣经-web服务 1.Web服务程序,标准库里的方法已经帮我们完成了大量工作 2.main函数将所有发送到/路径下的请求和handler函数关联起来,/开头的请求其实就是所有发送到当前站点上的 ...

  7. [日常] Go语言圣经--接口约定习题

    Go语言圣经-接口1.接口类型是对其它类型行为的抽象和概括2.Go语言中接口类型的独特之处在于它是满足隐式实现的3.Go语言中还存在着另外一种类型:接口类型.接口类型是一种抽象的类型4.一个类型可以自 ...

  8. [日常] Go语言圣经-Panic异常,Recover捕获异常习题

    Go语言圣经-Panic异常1.当panic异常发生时,程序会中断运行,并立即执行在该goroutine中被延迟的函数(defer 机制)2.不是所有的panic异常都来自运行时,直接调用内置的pan ...

  9. [日常] Go语言圣经-匿名函数习题

    Go语言圣经-匿名函数1.拥有函数名的函数只能在包级语法块中被声明,通过函数字面量(function literal),我们可绕过这一限制,在任何表达式中表示一个函数值2.通过这种方式定义的函数可以访 ...

随机推荐

  1. git上如何处理无法clone和merge

    对于一些需要FQ才能克隆下来的项目,我们需要使用代理 进入terminal: 设置代理: git config --global http.proxy http://127.0.0.1:1087 gi ...

  2. python trojan development 1st —— use python to send mail and caputre the screen then combine them

    import smtplib from email.mime.text import MIMEText msg_from='1@qq.com' #发送方邮箱 passwd='bd' #填入发送方邮箱的 ...

  3. ElasticStack学习(二):ElasticStack安装与运行

    一.ElasticSearch的安装与运行 1.由于ElasticSearch是由Java语言开发的,若要运行ElasticSearch,需要安装并配置JDK,并要设置$JAVA_HOME环境变量. ...

  4. vue的懒加载如何实现?

    个人通过查找发现一个比较好用的模块,vue-lazyload 第一步 下载安装这个包    npm install vue-lazyload 第二步 在main.js中引入这个模块 import Vu ...

  5. CQRS之旅——旅程8(后记:经验教训)

    旅程8:后记:经验教训 我们的地图有多好?我们走了多远?我们学到了什么?我们迷路了吗? "这片土地可能对那些愿意冒险的人有益."亨利.哈德逊 这一章总结了我们旅程中的发现.它强调了 ...

  6. Selenium Grid分布式测试环境搭建

    Selenium Grid简介 Selenium Grid实际上是基于Selenium RC的,而所谓的分布式结构就是由一个hub节点和若干个node代理节点组成.Hub用来管理各个代理节点的注册信息 ...

  7. Codeforces Gym101170I:Iron and Coal(建多幅图+多次BFS)***

    题目链接 题意 有n个点,其中有m个点是铁矿,k个点是煤,从1号点出发,你可以派一些士兵跑向不同的点,问占领至少一个铁矿和一个煤的时候,最少需要占领多少个点. 思路 建两幅图,其中一幅是正向边,一幅是 ...

  8. POJ 3680:Intervals(最小费用最大流)***

    http://poj.org/problem?id=3680 题意:给出n个区间[Li,Ri],每个区间有一个权值wi,要使得每个点都不被超过k个区间覆盖(最多能被k个区间覆盖),如果选取了第i个区间 ...

  9. django基础知识之定义模型:

    定义模型 在模型中定义属性,会生成表中的字段 django根据属性的类型确定以下信息: 当前选择的数据库支持字段的类型 渲染管理表单时使用的默认html控件 在管理站点最低限度的验证 django会为 ...

  10. scrapy基础知识之 RedisCrawlSpider:

    这个RedisCrawlSpider类爬虫继承了RedisCrawlSpider,能够支持分布式的抓取.因为采用的是crawlSpider,所以需要遵守Rule规则,以及callback不能写pars ...