如何正确处理多个并发请求?

huangapple go评论73阅读模式
英文:

How can I do multiple concurrent requests properly?

问题

大家好,我正在尝试对数据库进行多次请求,我发现按顺序同步执行它们非常慢,并且在等待每个请求完成时响应时间呈指数增长。以下是我目前的代码:

var wg sync.WaitGroup
dbUsername := make(chan string, 1)
dbEmail := make(chan string, 1)

wg.Add(2)
go func(username chan string, waiter sync.WaitGroup) {
    defer waiter.Done()
    err = db.QueryRow("SELECT username FROM user WHERE username = ?", vals.Get("username")).Scan(&result)
    if err != nil {
        log.Println(err)
    }
}(dbUsername, wg)

go func(email chan string, waiter sync.WaitGroup) {
    defer waiter.Done()
    err = db.QueryRow("SELECT email FROM user WHERE email = ?", vals.Get("email")).Scan(&result)
    if err != nil {
        log.Println(err)
    }
}(dbEmail, wg)

wg.Wait()

if <-dbUsername != "" {
    formErrors = append(formErrors, "Username has already been taken.")
}
if <-dbEmail != "" {
    formErrors = append(formErrors, "Email has already been taken.")
}

但它似乎无法正常工作,我完全按照WaitGroup的示例进行操作,但它似乎在wg.Wait()处挂起,我不确定原因。还有没有更好的方法来实现这个功能,或者我目前的代码是正常的?

另外一个小问题

是否可以使用var声明一个带缓冲的通道,例如var blah chan string 1

英文:

Hi guys I'm trying to make multiple requests to a database, and I found doing them in order synchronously is quite slow and exponentially increases response time while waiting for each request to finish, this is what I have so far:

var wg sync.WaitGroup
dbUsername := make(chan string, 1)
dbEmail := make(chan string, 1)

wg.Add(2)
go func(username chan string, waiter sync.WaitGroup) {
	defer waiter.Done()
	err = db.QueryRow(&quot;SELECT username FROM user WHERE username = ?&quot;, vals.Get(&quot;username&quot;)).Scan(&amp;result)
	if err != nil {
		log.Println(err)
	}
}(dbUsername, wg)

go func(email chan string, waiter sync.WaitGroup) {
	defer waiter.Done()
	err = db.QueryRow(&quot;SELECT email FROM user WHERE email = ?&quot;, vals.Get(&quot;email&quot;)).Scan(&amp;result)
	if err != nil {
		log.Println(err)
	}
}(dbEmail, wg)

wg.Wait()



if &lt;-dbUsername != &quot;&quot; {
	formErrors = append(formErrors, &quot;Username has already been taken.&quot;)
}
if &lt;-dbEmail != &quot;&quot; {
	formErrors = append(formErrors, &quot;Email has already been taken.&quot;)
}

but it doesn't seem to work correctly, I've followed the WaitGroup example to the dot, but it seems to hang on wg.Wait() and I'm not sure why. And is there a prettier way to do this or is what I have mocked up normal?

also small sub question:

is it possible to declare a buffered channel with var e.g. var blah chan string 1

答案1

得分: 1

你正在将你的WaitGroup的副本传递给你的两个函数,

相反,传递一个指针waiter *sync.WaitGroup,这样等待WaitGroup的代码和goroutine都可以操作同一个WaitGroup。

这也在文档中有说明:
>包含在此包中定义的类型的值不应被复制。

然而,在你的情况下,goroutine函数可以访问外部作用域中声明的变量,所以你根本不需要传递任何参数。你可能也不需要WaitGroup,因为接收&lt;-dbUsername&lt;-dbEmail会等待goroutine完成 - 只要你的两个goroutine在各自的通道上发送一个值。在这里你也不需要缓冲通道。

至于这个问题:
>是否可以使用var声明一个带缓冲的通道,例如var blah chan string 1

是的,记住通道需要使用make()来创建

var blah chan string 
blah = make(chan string, 1)

或者var blah chan string = make(chan string, 1)

英文:

You're passing in a copy of your WaitGroup to your two functions,

Instead pass in a pointer, waiter *sync.WaitGroup, so your code that waits on the WaitGroup and the goroutines all operates on the same WaitGroup.

This is also noted in the documentation:
>Values containing the types defined in this package should not be copied.

However, in your case your goroutine functions can access the variables declared in the outer scope, so you don't need to pass in any arguments at all. You might not need the WaitGroup either, as receiving of &lt;-dbUsername and &lt;-dbEmail will anyway wait until the goroutines are done - as long as you make both your goroutines send a value on their respective channels. And you don't need buffered channels here either.

As for this:
> is it possible to declare a buffered channel with var e.g. var blah chan string 1

Yes, remember that channels need to be created using make()

var blah chan string 
blah = make(chan string, 1)

Or var blah chan string = make(chan string, 1)

huangapple
  • 本文由 发表于 2015年11月22日 11:32:11
  • 转载请务必保留本文链接:https://go.coder-hub.com/33851312.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定