练习 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. Windows下OSGEarth的编译过程

    目录 1. 依赖 1) OpenSceneGraph 2) GDAL 3) CURL 4) GEOS 5) 其他 2. 编译 1) 设置参数 2) 配置路径 3) 生成编译 3. 参考文献 1. 依赖 ...

  2. Python自学day-2

    一.模块     模块分两种:标准库和第三方库,标准库是不需要安装就可以使用的库.     import [模块名]:导入一个库,优先是在项目路径中寻找.自定义模块名不要和标准库模块名相同.   sy ...

  3. Spark学习之路(十二)—— Spark SQL JOIN操作

    一. 数据准备 本文主要介绍Spark SQL的多表连接,需要预先准备测试数据.分别创建员工和部门的Datafame,并注册为临时视图,代码如下: val spark = SparkSession.b ...

  4. HTML连载19-子元素选择器&交集选择器

    一.子元素选择器 1.定义:找到指定标签中所有特定的直接子元素,然后设置属性 2.格式: 标签名称一>标签名称2{ 属性:值: } 3.释义:先找到叫做“标签名称1”的标签,然后在这个标签中查找 ...

  5. SSH不能连接并提示REMOTE HOST IDENTIFICATION HAS CHANGED

    ssh连接报错: 解决: vi /root/.ssh/known_hosts 找到要连接的主机的ip,把它的那行所有信息删除(就是一行)

  6. GRPC与.net core

    系列章节 GRPC与.net core GRPC截止时间与元数据 GRPC与netcore Identity GRPC与netcore IdentityServer4 概述 GRPC的数据交互模式有: ...

  7. 并发编程-concurrent指南-阻塞队列-延迟队列DelayQueue

    DelayQueue是一个无界的BlockingQueue,用于放置实现了Delayed接口的对象,其中的对象只能在其到期时才能从队列中取走.这种队列是有序的,即队头对象的延迟到期时间最长.注意:不能 ...

  8. Modbus RTU 介绍

    S7-1200 Modbus RTU 通信概述 Modbus具有两种串行传输模式:分别为ASCII和RTU.Modbus是一种单主站的主从通信模式,Modbus网络上只能有一个主站存在,主站在Modb ...

  9. springboot2.x纯注解整合dubbo

    springboot1.x和springboot2.x整合差距挺大的,基于最新的2.x进行整合,使用纯注解的方式 依赖选取 首先pom文件的依赖引入,maven仓库有Apache和alibaba两个 ...

  10. 20190716 NOIP模拟测试4 考试反思

    总分 127分 满分300 第一题 礼物 10分 一道期望题,看起来挺简单,但对于概率与期望这一块我还不怎么会,花了一个小时调他,最后只QJ了一下10%的测试点 第二题 通讯 90分 显然的缩点求解, ...