GO Channels ending abruptly?

Issue

I’m trying to generate accounts concurrently using go channels (below is simplified code), however I see that it’s not generating all accounts:

package main

import (
    "fmt"
    "github.com/segmentio/ksuid"
)

const ConcurrencyLevel = 10

const TotalAccounts = 30

type (
    Accounts []Account

     Account struct {
        AccountID   string
    }
)

func GenerateRandomAccountID() (accountReferenceID string){
    return ksuid.New().String()
}

func main() {
    totalAccounts := make(Accounts, 0, TotalAccounts)
    total := 0
    for total < TotalAccounts {
        accounts := make([]Account, ConcurrencyLevel)
        ch := make(chan Account)
        for range accounts {
            go func() {
                accountID := GenerateRandomAccountID()
                account := Account{AccountID: accountID}
                ch <- account
            }()
        }

        for k, _ := range accounts {
            account := <-ch
            accounts[k] = account
        }
        totalAccounts = append(totalAccounts, accounts...)
        total += len(totalAccounts)
        close(ch)
    }
    fmt.Printf("total is : %d\n", total)
    fmt.Printf("total accounts generated is : %d\n", len(totalAccounts))

}

It prints out

total is : 30
total accounts generated is : 20

expecting total accounts generated to be 30 in this case.

https://go.dev/play/p/UtFhE2nidaP

Solution

There is an error in your logic:

totalAccounts = append(totalAccounts, accounts...)
total += len(totalAccounts)

Say this is the second iteration through the loop. totalAccounts already contains 10 items, you add another 10 so the length is now 20. You then take total (which will be 10 from the first run through) and add len(totalAccounts) (20) to give a result of 30. This means that your loop (for total < TotalAccounts) completes earlier than it should.

To fix this you could use playground:

totalAccounts = append(totalAccounts, accounts...)
total += len(accounts) // Add the number of NEW accounts

or

totalAccounts = append(totalAccounts, accounts...)
total = len(totalAccounts ) // = not +=

Answered By – Brits

Answer Checked By – David Marino (GoLangFix Volunteer)

Leave a Reply

Your email address will not be published.