Reputation: 34099
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?
Upvotes: 0
Views: 1368
Reputation: 99351
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"
}
Upvotes: 4
Reputation: 166815
The validation
channel is never closed.
for err := range validation {
errColl[iterator] = err
iterator++
}
The Go Programming Language Specification
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.
Upvotes: 7