重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
1.创建一个文件夹,例如:golang入门到项目实战
淇县网站建设公司创新互联公司,淇县网站设计制作,有大型网站制作公司丰富经验。已为淇县成百上千家提供企业网站建设服务。企业网站搭建\成都外贸网站建设公司要多少钱,请找那个售后服务好的淇县做网站的公司定做!
2.在golang入门到项目实战文件夹中创建一个go文件,例如:test.go
3.在test.go中输入如下内容:
4.编译执行go run test.go
5.可仅选择编译执行go build test.go,则目录下会多出个exe程序
go语言没有面向对象的特性,也没有类对象的概念。但是,可以使用结构体来模拟这些特性,我们都知道面向对象里面有类方法等概念。我们也可以声明一些方法,属于某个结构体。
Go中的方法,是一种特殊的函数,定义域struct之上(与struct关联、绑定),被称为struct的接受者(receiver)。通俗的讲,方法就是有接收者的函数。
语法格式如下:
mytype:定义一个结构体
recv:接受该方法的结构体(receiver)
my_method:方法名称
para:参数列表
return_type:返回值类型
从语法格式可以看出,一个方法和一个函数非常相似,多了一个接受类型。
实例
运行结果
爬取器 fetcher 和解析器 parser 与之前相同,模型类也不变。
注意:
见本小节文末分析。
Q1. 为什么在 scheduler 中每一个将 Request 添加到 chan 的任务都开启一个 Goroutine 来执行?
A:在 Go 语言学习9 - Channel 一节描述过,对于无缓冲的 channel, 如果两个 goroutine 没有同时准备好,通道会导致先执行发送或接收操作的 goroutine 阻塞等待 ,假设使用 s.workerChan - request 而不是 go func() { s.workerChan - request }() ,假设开启了 10 个 Worker Goroutine,这 10 个 goroutine 阻塞在 r := -in 阻塞等待获取 Request 上,假设 seeds 大于 10,例如 11,那么当 Engine 的这个循环执行到底 11 个的时候,将陷入等待
,因为所有的10个 Worker goroutine 此时都可能也处于等待中,即 in chan 没有接收方准备好接收数据,所以 engine 作为发送方也要阻塞等待;那么为什么10个 Worker goroutine 都会处于等待中呢?
因为10个 Worker Goroutine 都处理完了请求,并阻塞在 out - result ,由于 Engine 阻塞在 “将第11个 Request 发送到 in” 上,所以其无法进行后续的死循环去开启 result := -out ,到此为止,相互等待死锁形成!!!Engine 等待 Worker 准备好 r := -in ,而10个 Worker 等待 Engine 的 result := -out 。
当使用 go func() { s.workerChan - request }() 之后,Engine Goroutine 将不再阻塞,死锁等待被打破!!!
Q2. scheduler 方法为何使用指针接收者而不是值接收者?
A:在 Go 语言学习5 - 面向接口 中我们详细的介绍了什么时候使用指针接收者,什么时候使用值接收者,其中最重要的两条就是 “ 1. 如果要改变接收者内部的属性值,必须使用指针接收者,因为值接收者是对接收者副本的操作;2. 如果 struct 内一个方法是指针接收者,那么其全部方法都是用指针接收者 ”,在 scheduler 中,我们要将外界的 in chan 赋值给 scheduler 的 workChann,所以需要改变 workChann 的值,需要使用指针接收者。