大家好,我从Python3转到了Go,因此我试图重写为获得更好性能而创建的库。
由于Golang XD中的im noob,即时通讯遇到问题,即时通讯使用有限的API下载数百个json,因此我希望在可能的情况下使用尽可能少的请求。 因此,在下载这些json时,使用的某些URL是重复的,我的第一个想法是在下载函数(goroutines)和每个goroutine之间传递map [stringLink] * myJsonReceived,然后再下载,以检查链接是否已被另一个处理,因此与其再次请求并浪费带宽+ API调用,不如等待其他goroutine完成下载并从字典中获取它。
我的选择很少:
1)goroutine必须检查链接是否在地图内,如果字典中的Pointer仍为nil或包含json,它将每0.05秒检查一次。 (可能是最糟糕的方法,但它可以工作)
2)将在goroutine之间传递的映射更改为(map [stringlink] chan myjson),这可能是最有效的方法,但是我不知道如何将单个消息发送到通道并通过多个等待的Goroutine接收。 >
3)我可以通过在结构上添加一个计数器来使用选项(2),并且每当goroutine发现已请求url时,它只会在计数器上添加+1并在等待通道响应时下载goroutine完成后,它将向通道发送X条消息。但是这种方式会使我在地图上添加太多LOCK,这会浪费性能。
注意:我需要在所有函数执行结束时使用映射,以将下载的Jsons保存到我的数据库中,以免再次下载它们。
在此先感谢大家的帮助。
答案 0 :(得分:1)
要解决您的任务,我将为此使用goroutine池。将有一个生产者在一个通道上发送URL,而工作程序goroutines将在该通道范围内接收URL以进行处理(获取)。一旦URL被“完成”,同一工作程序goroutine也可以将其保存到数据库中,或将结果传递到“收集器” goroutine的结果通道上,如果需要,可以按顺序进行保存。
这种通过设计进行的构造可确保在通道上发送的每个URL仅由一个工作程序goroutine接收,因此您不需要任何其他同步(在使用共享映射的情况下将需要同步)。有关频道的更多信息,请参见What are golang channels used for?
Go通过共享变量来支持goroutine(通道)之间的通信。引用Effective Go: Share by communicating:
请勿通过共享内存进行通信;而是通过交流共享内存。
有关如何创建工作池的示例,请参见Is this an idiomatic worker thread pool in Go?