步骤连续时使用goroutine
我觉得我的问题的答案是否定的,只是要求确定,因为我才开始玩围棋几天。我们是否应该将IO绑定的任务(如http请求)封装到goroutine中,即使它将在顺序用例中使用 这是我天真的例子。假设我有一个方法,可以发出3个http请求,但需要按顺序执行。将步骤连续时使用goroutine,go,goroutine,Go,Goroutine,我觉得我的问题的答案是否定的,只是要求确定,因为我才开始玩围棋几天。我们是否应该将IO绑定的任务(如http请求)封装到goroutine中,即使它将在顺序用例中使用 这是我天真的例子。假设我有一个方法,可以发出3个http请求,但需要按顺序执行。将invoke方法创建为goroutines有什么好处吗?我知道下面的例子实际上会影响性能 func myMethod() { chan1 := make(chan int) chan2 := make(chan int) chan3
invoke
方法创建为goroutines有什么好处吗?我知道下面的例子实际上会影响性能
func myMethod() {
chan1 := make(chan int)
chan2 := make(chan int)
chan3 := make(chan int)
go invoke1(chan1)
res1 := <-chan1
invoke2(res1, chan2)
res2 := <-chan2
invoke3(res2, chan3)
// Do something with <-chan3
}
func myMethod(){
通道1:=制造(通道内部)
通道2:=制造(通道内部)
通道3:=制造(通道内部)
go invoke1(通道1)
res1:=没有任何标准会对这个问题说是或不是
虽然您可以通过这种方式正确地执行,但坚持简单的顺序执行要简单得多
我想到三个原因:
- 这仍然是顺序的:您正在按顺序等待每一个goroutine,因此这不会给您带来任何好处。如果只是执行一个http请求,性能可能不会有太大变化,这两种情况都将花费大部分时间等待响应
- 如果只获得
结果,err:=invoke;if err!=nil….
则错误处理要简单得多,而不必通过通道传递结果和错误
- 过度泛化是一个比“未来验证”更合适的词。如果将来需要异步调用
invoke
方法,那么以后可以更改代码。在函数周围添加异步包装也同样容易
您可以使用像buf这样的频道,或者使用[]字符串(字符串片段URL)。如果您只需要顺序执行,则无法从goroutine中获得任何好处,因为我们无法在goroutine启动时控制它
但是我们可以询问,然后不要等待runtime.Gosched()
从文件:
Gosched生成处理器,允许其他goroutine运行。它不会挂起当前goroutine,因此执行会自动恢复
顺序执行的示例:
package main
func main() {
urls := []string{
"https://google.com",
"https://yahoo.com",
"https://youtube.com",
}
buf := make([][]byte, 0, len(urls))
for _, v := range urls {
buf = append(buf, sendRequest(v))
}
}
func sendRequest(url string) []byte {
//send
return []byte("")
}
就解决方案而言,我认为以现实世界中的方式解决问题没有任何好处。这并不意味着解决方案没有好处。例如,如果你在练习同步围棋,那么你就有太多的可能性进行实验和学习
因此,对我来说,这远不是一个明确的“不”,但也不是一个明确的“是”。我不想说“可能”,这取决于你到底在追求什么。你是在真正解决问题还是在学习?我参加聚会有点晚了,但我想我还有一些东西要分享
在回答这个问题之前,我想深入探讨一下Go谚语,并发性不是parellism。人们对goroutine和Go语言特征的误解是,当人们想到goroutine时,他们会想到成为parell的能力
但正如Rob Pike在许多围棋会谈中指出的那样,围棋和goroutine实际上提供的是一致性。一致性是更好地理解现实世界的一种模式,是一种代码交互方式和结构
回到问题上来。当步骤是连续的时,是否应该使用goroutine?这取决于设计。如果您的代码由各个部分组成,彼此之间的对话非常自然,或者如果您的一些代码保留状态并且经常返回没有意义,或者如果您的代码适合任何其他Concurrency设计,则是有意义的使用goroutine和channel以及select
语句非常好。Rob Pike再次就now Go的text/template
使用的lexer进行了一次Go演讲,lexer使用goroutine和channel,但是解析器显然只按顺序使用lexer。他表示,使用goroutine和channel,以牺牲一点性能为代价,可以获得更好的性能实现了API
但另一方面,在您的示例中,可能是您正在考虑的(可能需要未来parellism的代码),我同意@Marc.Stick的阻塞调用,至少现在是这样。@Flimzy-我不确定你是否忽略了这个例子,或者我不理解,但是这个例子中的每个方法都需要前一个方法的结果,所以它们不能并行执行。如果你想按顺序执行步骤,不要使用并发。并发是相反的当然。@Adrian-是的,我知道;那不是我的问题。如果你知道,那么你也知道你问题的答案。