Arian Motamedi
Arian Motamedi

Reputation: 7423

Channel of type "set"

I recently started writing Go after years of programming in C#, and I'm having a hard time wrapping my head around several concepts of the language. Here's an example of what I'm trying to solve: I'd like to be able to create a routine that iterates over a list, calls a function, and stores the output in a buffered channel. The issue is I want to return a distinct set of these output values, as the function can return similar results for two different elements in the list.

Since Go doesn't have a built-in set type, I'm trying to use a map[string]bool to store distinct values (using map[string]bool or map[string]struct is what others suggested as a replacement for a set); and I'm using a buffered channel to insert into this map, however I'm not certain what the right syntax for inserting 1 element into a map would look like. Here's what I'm trying to do:

resultsChnl := make(chan map[string]bool, len(myList))
go func(myList []string, resultsChnl chan map[string]bool) {
    for _, item := range myList {

        result, err := getResult(item)
        /* error checking */

        resultsChnl <- {result: true}
    }

    close(resultsChnl)
}(myList, resultsChnl)

for item := range resultsChnl {
    ...
}

Obviously this doesn't compile due to invalid syntax of resultsChnl <- {result: true}. I know this sounds impractical since naturally in this particular case I could create a local map inside the for loop and assign one map[string]bool object to a non-buffered channel and return that, but let's assume I was creating a go routine for each item in the list and really wanted to use a buffered channel (as opposed to using a mutex to grab a lock on a shared map). So is there any way to insert one key-value pair in a map channel? Or am I thinking about this completely wrong?

Upvotes: 0

Views: 336

Answers (1)

hobbs
hobbs

Reputation: 240434

To answer the question directly, you would want

resultsChnl <- map[string]bool{result: true}

But this doesn't seem useful at all. You may want to collect the results in a map, but there's no reason to pass a map over the channel for each result when you know it will only have one element. Simply use a channel of string, do

resultsChnl <- result

for each result in your producer goroutine, and

seenResult[item] = true

in your consumer loop to collect the results (where seenResult is a map[string]bool).

Or forget about the channel entirely and have your producer goroutines write directly into a sync.Map.

Upvotes: 3

Related Questions