GO通道突然结束了吗?

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

GO Channels ending abruptly?

问题

我正在尝试使用Go通道并发生成账户(下面是简化的代码),但是我发现它没有生成所有的账户:

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))
}

它输出:

total is : 30
total accounts generated is : 20

期望在这种情况下生成的总账户数为30。

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

英文:

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 (
	&quot;fmt&quot;
	&quot;github.com/segmentio/ksuid&quot;
)

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 &lt; TotalAccounts {
		accounts := make([]Account, ConcurrencyLevel)
		ch := make(chan Account)
		for range accounts {
			go func() {
				accountID := GenerateRandomAccountID()
				account := Account{AccountID: accountID}
				ch &lt;- account
			}()
		}

		for k, _ := range accounts {
			account := &lt;-ch
			accounts[k] = account
		}
		totalAccounts = append(totalAccounts, accounts...)
		total += len(totalAccounts)
		close(ch)
	}
	fmt.Printf(&quot;total is : %d\n&quot;, total)
	fmt.Printf(&quot;total accounts generated is : %d\n&quot;, 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

答案1

得分: 2

你的逻辑中有一个错误:

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

假设这是循环的第二次迭代。totalAccounts 已经包含了 10 个元素,你又添加了另外 10 个元素,所以长度现在是 20。然后你将 total(第一次迭代时的值为 10)与 len(totalAccounts)(20)相加,得到结果为 30。这意味着你的循环(for total < TotalAccounts)比预期提前结束。

要修复这个问题,你可以使用 playground 中的以下代码:

totalAccounts = append(totalAccounts, accounts...)
total += len(accounts) // 添加新账户的数量

或者

totalAccounts = append(totalAccounts, accounts...)
total = len(totalAccounts) // 不是 +=
英文:

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 &lt; 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 +=

huangapple
  • 本文由 发表于 2022年2月16日 09:54:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/71135523.html
匿名

发表评论

匿名网友

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

确定