What is the correct way to write a distinct channel in Go?

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

What is the correct way to write a distinct channel in Go?

问题

我是一名Go语言初学者。

我正在尝试找到一种简单的方法来实现一个只输出不同值的通道。

我想要做的是这样的:

  1. package example
  2. import (
  3. "fmt"
  4. "testing"
  5. )
  6. func TestShouldReturnDistinctValues(t *testing.T) {
  7. c := make(chan int)
  8. go func() {
  9. c <- 1
  10. c <- 1
  11. c <- 2
  12. c <- 2
  13. c <- 3
  14. close(c)
  15. }()
  16. seen := make(map[int]bool)
  17. for e := range c {
  18. if !seen[e] {
  19. seen[e] = true
  20. // 只打印1、2和3。
  21. fmt.Println(e)
  22. }
  23. }
  24. }

如果我使用一个映射来记住先前的值,我应该担心内存泄漏吗?

英文:

I am a beginner in go.

I am trying to figure out an easy way to implement a channel that only output distinct values.

What I want to do is this:

  1. package example
  2. import (
  3. &quot;fmt&quot;
  4. &quot;testing&quot;
  5. )
  6. func TestShouldReturnDistinctValues(t *testing.T) {
  7. var c := make([]chan int)
  8. c &lt;- 1
  9. c &lt;- 1
  10. c &lt;- 2
  11. c &lt;- 2
  12. c &lt;- 3
  13. for e := range c {
  14. // only print 1, 2 and 3.
  15. fmt.println(e)
  16. }
  17. }

Should I be concern about memory leak here if I were to use a map to remember previous values?

答案1

得分: 7

你真的不能这样做,你必须以某种方式跟踪这些值,map[int]struct{}可能是最节省内存的方法。

一个简单的示例:

  1. func UniqueGen(min, max int) <-chan int {
  2. m := make(map[int]struct{}, max-min)
  3. ch := make(chan int)
  4. go func() {
  5. for i := 0; i < 1000; i++ {
  6. v := min + rand.Intn(max)
  7. if _, ok := m[v]; !ok {
  8. ch <- v
  9. m[v] = struct{}{}
  10. }
  11. }
  12. close(ch)
  13. }()
  14. return ch
  15. }

示例链接

英文:

You really can't do that, you'd have to keep a track of the values somehow, a map[int]struct{} is probably the most memory efficient way.

A simple example:

  1. func UniqueGen(min, max int) &lt;-chan int {
  2. m := make(map[int]struct{}, max-min)
  3. ch := make(chan int)
  4. go func() {
  5. for i := 0; i &lt; 1000; i++ {
  6. v := min + rand.Intn(max)
  7. if _, ok := m[v]; !ok {
  8. ch &lt;- v
  9. m[v] = struct{}{}
  10. }
  11. }
  12. close(ch)
  13. }()
  14. return ch
  15. }

答案2

得分: 3

我以前做过类似的事情,只是我的问题是按升序输出输入。你可以通过添加一个中间的goroutine来实现这个功能。这里有一个示例:

  1. package main
  2. func main() {
  3. input, output := distinct()
  4. go func() {
  5. input <- 1
  6. input <- 1
  7. input <- 2
  8. input <- 2
  9. input <- 3
  10. close(input)
  11. }()
  12. for i := range output {
  13. println(i)
  14. }
  15. }
  16. func distinct() (input chan int, output chan int) {
  17. input = make(chan int)
  18. output = make(chan int)
  19. go func() {
  20. set := make(map[int]struct{})
  21. for i := range input {
  22. if _, ok := set[i]; !ok {
  23. set[i] = struct{}{}
  24. output <- i
  25. }
  26. }
  27. close(output)
  28. }()
  29. return
  30. }

你可以参考这个示例来解决你的问题。

英文:

I have done similar things before, except my problem was output inputs in ascending order. You can do this by adding a middle go routine. Here is an example:

  1. package main
  2. func main() {
  3. input, output := distinct()
  4. go func() {
  5. input &lt;- 1
  6. input &lt;- 1
  7. input &lt;- 2
  8. input &lt;- 2
  9. input &lt;- 3
  10. close(input)
  11. }()
  12. for i := range output {
  13. println(i)
  14. }
  15. }
  16. func distinct() (input chan int, output chan int) {
  17. input = make(chan int)
  18. output = make(chan int)
  19. go func() {
  20. set := make(map[int]struct{})
  21. for i := range input {
  22. if _, ok := set[i]; !ok {
  23. set[i] = struct{}{}
  24. output &lt;- i
  25. }
  26. }
  27. close(output)
  28. }()
  29. return
  30. }

huangapple
  • 本文由 发表于 2014年8月13日 22:24:20
  • 转载请务必保留本文链接:https://go.coder-hub.com/25288763.html
匿名

发表评论

匿名网友

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

确定