该接口内嵌了之前讲过的 Module 接口,其声明如下:
//组件的内部基础接口的类型 type ModuleInternal interface { module.Module //把调用计数增 1 IncrCalledCount() //把接受计数增1 IncrAcceptedCount() //把成功完成计数增 1 IncrCompletedCount() //把实时处理数增 1 IncrHandlingNumber() //把实时处理数减 1 DecrHandlingNumber() //用于清空所有计数 Clear() }
Module 接口中声明的更多的是获取内部状态的方法,比如:获取组件 ID、组件地址、各种计数值,等等。而在 ModuleInternal 接口中,添加的方法都是改变内部状态的方法。
由于通常情况下外部不应该宜接改变组件的内部状态,所以该接口的名字才以 "Internal" 为后缀,以起到提示的作用。并且,在 gopcp.v2/chapter6/webcrawler/module 包中公开的程序实体并没有涉及该接口。
ModuleInternal 接口及其实现类型只是为了方便自行编写组件的人而准备的。在编写组件时也用到了它们。
ModuleInternal 接口是 Module 接口的扩展,前者的实现类型自然也是后者的实现类型。这个实现类型命名为 myModule,它的基本结构如下:
//组件内部基曲接口的实现类型 type myModule struct { //组件ID mid module.MID //组件的网络地址 addr string //组件评分 score uint64 //评分计算器 scoreCalculator module.CalculateScore //调用计数 calledCount uint64 //接受计数 acceptedCount uint64 //成功完成计数 completedCount uint64 //实时处理数 handlingNumber uint64 }
这些字段都是理所应当存在的,它们分别与 Module 接口(以及 ModuleInternal 口)中声明的方法有直接的对应关系。按照惯例, NewModuleInternal 用于新建一个 ModuleInternal 类型的实例,它的声明如下。
//创建一个组件内部基础类型的实例 func NewModuleInternal( mid module.MID, scoreCalculator module.CalculateScore) (ModuleInternal, error) { parts, err := module.SplitMID(mid) if err != nil { return nil, errors.NewIllegalParameterError( fmt.Sprintf("illegal ID %q: %s", mid, err)) } return &myModule{ mid: mid, addr: parts[2], scoreCalculator: scoreCalculator }, nil }
myModule 类型中的字段有几个是需要显式初始化的,包括:组件 ID、组件的网络地址(下面简称组件地址)和组件评分计算器。参数 mid 提供了组件 ID,同时也提供了组件地址。因为组件 ID 中可以包含组件地址。
如果组件地址为空,就说明该组件与网络爬虫程序同处在一个进程中。这时的 addr 字段自然就是 ""。module 包的 SplitMID 函数用于分离出组件 ID 的各个部分,并在组件 ID 不符合规范时报错,它是 module 包中众多工具类函数中的一个。
与之相对应,module 包中还有一个 GenMID 函数,用它可以生成组件 ID。调用 GenMID 函数时,需要给定一个序列号。大家可以通过调用 module 包中的 NewSNGenertor 函数创建出一个序列号生成器。强烈建议把序列号生成器的实例赋给一个全局变量。
组件评分计算器理应由外部提供,并且一般会为同一类组件实例设置同一种组件评分计算器,而且一旦设置就不允许更改。所以,即使是 ModuleInternal 接口也没有提供改变它的方法。
再强调一下,NewIllegalParameterError 是 gopcp.v2/chapter6/webcrawler/errors 包中的函数。该包中还有 NewCrawlerError 和 NewCrawlerErrorBy 函数,用于生成爬虫程序运作过程中抛出的错误值。
有了上述的那些字段,实现 ModuleInternal 接口的方法就相当简单了,唯一要注意的就是充分利用原子操作保证它们的并发安全。这里就不展示了。或许大家可以试着编写出来,然后对比看看。
原创文章,作者:奋斗,如若转载,请注明出处:https://blog.ytso.com/tech/pnotes/22616.html