[日常] GO语言圣经-并发获取多个URL
go语言圣经-并发获取多个URL
1.GO最新奇的特性就是对并发编程的支持,goroutine和channel
2.goroutine是一种函数的并发执行方式,而channel是用来在goroutine之间进行参数传递
go function则表示创建一个新的goroutine,并在这个新的goroutine中执行这个函数。
3.make函数创建了一个传递string类型参数的channel
4.io.Copy把响应的Body内容拷贝到ioutil.Discard输出流中,扔到一个垃圾桶
5.goroutine尝试在一个channel上做send或者receive操作时,这个goroutine会阻塞在调用处,直到另一个goroutine往这个channel里写入、或者接收值
6.用main函数来接收所有fetch函数传回的字符串,可以避免在goroutine异步执行还没有完成时main函数提前退出。
练习 1.10: 找一个数据量比较大的网站,用本小节中的程序调研网站的缓存策略,对每个URL执行两遍请求,查看两次时间是否有较大的差别,并且每次获取到的响应内容是否一致,修改本节中的程序,将响应结果输出,以便于进行对比。
练习 1.11: 在fetchall中尝试使用长一些的参数列表,比如使用在alexa.com的上百万网站里排名靠前的。如果一个网站没有回应,程序将采取怎样的行为?(Section8.9 描述了在这种情况下的应对机制)。
fetchall.go
package main //导入io/ioutil和net/http包
import (
"fmt"
"io"
"os"
"io/ioutil"
"net/http"
"strings"
"time"
) func main() {
//当前时间
start := time.Now()
//make函数创建了一个传递string类型参数的channel
ch := make(chan string)
//for循环命令行参数
for _, url := range os.Args[1:] {
//开启一个goroutine
go fetch(url,ch)
}
//接收并打印channel,for循环不需要key value
for range os.Args[1:]{
fmt.Printf(<-ch)//注意箭头方向,接收channel
}
//main函数的时间
fmt.Printf("main: %.2fs \n",time.Since(start).Seconds())
}
//参数类型:string , chan<- string
func fetch(url string,ch chan<- string){
start := time.Now()
//加入前缀
if !strings.HasPrefix(url, "http://") {
url = "http://" + url
}
res, err := http.Get(url)
//判断错误
if err != nil {
//向标准错误流打印信息
fmt.Fprintf(os.Stderr, "fetch:%v \n", err)
//终止进程
os.Exit(1)
}
//输出http code
//fmt.Printf("\nhttp status code :%s\n", res.Status) //把内容扔掉,只获取字节数
nBytes , err:=io.Copy(ioutil.Discard, res.Body)
//判断错误
if err != nil {
//向标准错误流打印信息
fmt.Fprintf(os.Stderr, "fetch:%v \n", err)
//终止进程
os.Exit(1)
}
res.Body.Close()
//记录执行的秒数
sec := time.Since(start).Seconds()
//发送给channel
ch<- fmt.Sprintf("%.2fs %7d %s \n",sec,nBytes,url)
}
对比fetch.go
package main //导入io/ioutil和net/http包
import (
"fmt"
"io"
"os"
"io/ioutil"
"net/http"
"strings"
"time"
) func main() {
//开始时间
start := time.Now()
//for循环命令行参数
for _, url := range os.Args[1:] {
//加入前缀
if !strings.HasPrefix(url, "http://") {
url = "http://" + url
}
res, err := http.Get(url)
//判断错误
if err != nil {
//向标准错误流打印信息
fmt.Fprintf(os.Stderr, "fetch:%v \n", err)
//终止进程
os.Exit(1)
} //body,err := ioutil.ReadAll(res.Body)
//避免申请一个缓冲区,直接到标准输出流
nBytes,err:=io.Copy(ioutil.Discard, res.Body)
//判断错误
if err != nil {
//向标准错误流打印信息
fmt.Fprintf(os.Stderr, "fetch:%v \n", err)
//终止进程
os.Exit(1)
}
res.Body.Close()
//输出http code
fmt.Printf("\nhttp status code :%s %7d %s\n", res.Status,nBytes,url)
//fmt.Printf("%s",body)
}
//结束时间
sec:=time.Since(start).Seconds()
fmt.Printf("main:%.2fs\n",sec)
}
执行效果对比:
[日常] GO语言圣经-并发获取多个URL的更多相关文章
- [日常] Go语言圣经-并发的非阻塞缓存
1.go test命令是一个按照约定和组织进行测试的程序2.竞争检查器 go run -race 附带一个运行期对共享变量访问工具的test,出现WARNING: DATA RACE 说明有数据竞争3 ...
- [日常] Go语言圣经--并发的循环习题
练习 8.4: 修改reverb2服务器,在每一个连接中使用sync.WaitGroup来计数活跃的echo goroutine.当计数减为零时,关闭TCP连接的写入,像练习8.3中一样.验证一下你的 ...
- [日常] Go语言圣经--并发的web爬虫
两种: crawler.go package main import ( "fmt" "links" //"log" "os&qu ...
- [日常] Go语言圣经前言
https://books.studygolang.com/gopl-zh/ go语言圣经 1.Go语言有时候被描述为“C类似语言”,或者是“21世纪的C语言”. 2.Go语言中和并发编程相关的特性是 ...
- [日常] Go语言圣经--复合数据类型,数组习题
go语言圣经-复合数据类型 1.以不同的方式组合基本类型可以构造出来的复合数据类型 2.四种类型——数组.slice.map和结构体 3.数组是由同构的元素组成——每个数组元素都是完全相同的类型——结 ...
- [日常] 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.通过这种方式定义的函数可以访 ...
随机推荐
- mvc 读写txt文档
-----------------写入内容---------------- string userfile = "UserData.txt"; StreamWriter sw = ...
- can not connect cube in performancce dashboard
需要在所有安装sharepoint服务器里面安装ADOMD组件 \Program Files\Microsoft Office Servers\15.0\WebServices\PpsMonitori ...
- umeng推送, 生产环境deviceToken失效可能原因
1 在系统升级之后会造成app的deviceToken重置(一定). 2 在app卸载之后可能会造成app的deviceToken重置. 3 deviceToken重置使用umeng推送时会因为dev ...
- CSDN无耻,亿赛通无耻
吐槽下,自己写一篇关于亿赛通加密文件的简单破解方式,竟然收到请求删除博客的私信,然后那篇博客就没有了. 太过于无耻了.
- 如何将Excel导入到Mysql数据库中
1.在mysql中建一张和Excel结构一样的表,或者修改excel信息,将excel的结构与mysql中table保持一致,包括字段名称. 2.利用mysql客户端工具navicat进行导入. 步骤 ...
- 页面按钮埋点+跟踪location.search
<a href="javascript: void(0)" onclick="setUrl('https://baoxian.pingan.com/pa18shop ...
- Ubuntu16.04 / OpenCV / Python 源码安装
为什么需要源码安装? 1. 对 Python 版的 OpenCV,Ubuntu 有两种安装方式: 源码安装:官网(https://opencv.org/releases.html)下载源代码,在机器上 ...
- Visual Studio 中的 Office 和 SharePoint 开发
MSDN Library 开发工具和语言 Visual Studio 中的 Office 和 SharePoint 开发 https://msdn.microsoft.com/zh-cn/libra ...
- 51单片机SRF寄存器
1.21个寄存器介绍 51系列单片机内部主要有四大功能模块,分别是I/O口模块.中断模块.定时器模块和串口通信模块(串行I/O口),如其结构和功能如下图: 图1 51单片机结构和功能图 ...
- PHP 修改目录下所有与文件夹重名的前缀文件为index.后缀
<?phpset_time_limit(0); function traverse($path = '.' , $dir_name='') { $current_dir = opendir($p ...