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

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

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

问题

我是一名Go语言初学者。

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

我想要做的是这样的:

package example

import (
	"fmt"
	"testing"
)

func TestShouldReturnDistinctValues(t *testing.T) {

	c := make(chan int)

	go func() {
		c <- 1
		c <- 1
		c <- 2
		c <- 2
		c <- 3
		close(c)
	}()

	seen := make(map[int]bool)

	for e := range c {
		if !seen[e] {
			seen[e] = true
			// 只打印1、2和3。
			fmt.Println(e)
		}
	}
}

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

英文:

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:

package example

import (
	&quot;fmt&quot;
	&quot;testing&quot;
)

func TestShouldReturnDistinctValues(t *testing.T) {

	var c := make([]chan int)

	c &lt;- 1
	c &lt;- 1
	c &lt;- 2
	c &lt;- 2
	c &lt;- 3

	for e := range c {
		// only print 1, 2 and 3.
		fmt.println(e)		
	}
}

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

答案1

得分: 7

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

一个简单的示例:

func UniqueGen(min, max int) <-chan int {
    m := make(map[int]struct{}, max-min)
    ch := make(chan int)
    go func() {
        for i := 0; i < 1000; i++ {
            v := min + rand.Intn(max)
            if _, ok := m[v]; !ok {
                ch <- v
                m[v] = struct{}{}
            }
        }
        close(ch)
    }()

    return ch
}

示例链接

英文:

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:

func UniqueGen(min, max int) &lt;-chan int {
	m := make(map[int]struct{}, max-min)
	ch := make(chan int)
	go func() {
		for i := 0; i &lt; 1000; i++ {
			v := min + rand.Intn(max)
			if _, ok := m[v]; !ok {
				ch &lt;- v
				m[v] = struct{}{}
			}
		}
		close(ch)
	}()

	return ch
}

答案2

得分: 3

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

package main

func main() {
    input, output := distinct()

    go func() {
        input <- 1
        input <- 1
        input <- 2
        input <- 2
        input <- 3
        close(input)
    }()

    for i := range output {
        println(i)
    }
}

func distinct() (input chan int, output chan int) {
    input = make(chan int)
    output = make(chan int)

    go func() {
        set := make(map[int]struct{})
        for i := range input {
            if _, ok := set[i]; !ok {
                set[i] = struct{}{}
                output <- i
            }
        }
        close(output)
    }()
    return
}

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

英文:

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:

package main

func main() {
	input, output := distinct()

	go func() {
		input &lt;- 1
		input &lt;- 1
		input &lt;- 2
		input &lt;- 2
		input &lt;- 3
		close(input)
	}()

	for i := range output {
		println(i)
	}
}

func distinct() (input chan int, output chan int) {
	input = make(chan int)
	output = make(chan int)

	go func() {
		set := make(map[int]struct{})
		for i := range input {
			if _, ok := set[i]; !ok {
				set[i] = struct{}{}
				output &lt;- i
			}
		}
		close(output)
	}()
	return
}

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:

确定