英文:
After loop a channel with range app break
问题
我有一个问题,就是我的应用程序在循环遍历通道后不会执行下一个语句。为了澄清我的意思,看一下下面的代码片段。
这是我的创建账户函数。在三个goroutine之后,我对通道validation进行了循环遍历。循环结束后,语句
fmt.Println("Hello")
永远不会执行。但是当我将函数改成这样时。
Hello将被打印出来,并且我得到了返回值。
在第一个代码片段中,我做错了什么?
英文:
I have a problem, that my application is not going to reach the next statement after loop over a channel. To clarify, what I mean, look at the following code snippet.
func CreateAccount(name, email, password string) (string, string) {
validation := make(chan error)
errColl := make([]error, 3, 3)
iterator := 0
go func() {
nameErr := IsNameValid(name)
validation <- nameErr
}()
go func() {
emailErr := IsEmailValid(email)
validation <- emailErr
}()
go func() {
passwordErr := IsPasswordValid(password)
validation <- passwordErr
}()
for err := range validation {
errColl[iterator] = err
iterator++
}
fmt.Println("Hello")
return "hello", "dude"
}
That is my create account function. After three goroutine, i make a loop over channel validation. After loop is done, the statement
> fmt.Println("Hello)
is never going the execute. But when I change the function like this.
func CreateAccount(name, email, password string) (string, string) {
validation := make(chan error)
errColl := make([]error, 3, 3)
//iterator := 0
go func() {
nameErr := IsNameValid(name)
validation <- nameErr
}()
go func() {
emailErr := IsEmailValid(email)
validation <- emailErr
}()
go func() {
passwordErr := IsPasswordValid(password)
validation <- passwordErr
}()
errColl[0] = <-validation
errColl[1] = <-validation
errColl[2] = <-validation
close(validation)
fmt.Println("Hello")
return "hello", "dude"
}
Hello is going to printed out and plus I got the return value.
What do I wrong in the first code snippet?
答案1
得分: 7
validation
通道从未关闭。
for err := range validation {
errColl[iterator] = err
iterator++
}
> Go编程语言规范
>
> for语句
>
> 带有"range"子句的"for"语句遍历数组、切片、字符串或映射的所有条目,或者接收到的通道值。
>
> 对于通道,生成的迭代值是在通道上发送的连续值,直到通道关闭为止。
英文:
The validation
channel is never closed.
for err := range validation {
errColl[iterator] = err
iterator++
}
> The Go Programming Language Specification
>
> For statements
>
> A "for" statement with a "range" clause iterates through all entries
> of an array, slice, string or map, or values received on a channel.
>
> For channels, the iteration values produced are the successive values
> sent on the channel until the channel is closed.
答案2
得分: 4
像 @peterSO 说的那样,你没有关闭通道,这种模式的正确方法是使用 sync.WaitGroup
:
func CreateAccount(name, email, password string) (string, string) {
var wg sync.WaitGroup
validation := make(chan error, 3)
errColl := make([]error, 3)
wg.Add(3)
go func() {
nameErr := IsNameValid(name)
validation <- nameErr
wg.Done()
}()
go func() {
emailErr := IsEmailValid(email)
validation <- emailErr
wg.Done()
}()
go func() {
passwordErr := IsPasswordValid(password)
validation <- passwordErr
wg.Done()
}()
wg.Wait()
for i := range errColl {
errColl[i] = <-validation
}
return "hello", "dude"
}
英文:
Like @peterSO said, you didn't close the channel, the proper way for that pattern is to use a sync.WaitGroup
:
func CreateAccount(name, email, password string) (string, string) {
var wg sync.WaitGroup
validation := make(chan error, 3)
errColl := make([]error, 3)
wg.Add(3)
go func() {
nameErr := IsNameValid(name)
validation <- nameErr
wg.Done()
}()
go func() {
emailErr := IsEmailValid(email)
validation <- emailErr
wg.Done()
}()
go func() {
passwordErr := IsPasswordValid(password)
validation <- passwordErr
wg.Done()
}()
wg.Wait()
for i := range errColl {
errColl[i] = <-validation
}
return "hello", "dude"
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论