Woo Xiong Wei Warren
Woo Xiong Wei Warren

Reputation: 23

GoRoutine that Returns Two Channels

Can someone please help me understand how to interpret the following line of code in the function return - (_, _ <-chan interface{})

I understand that the function returns two channels. But I don't understand how it is achieved using the following (_, _ <-chan interface{}). What is the difference if I just swap it out for (<-chan interface{}, <-chan interface{})?

tee := func(
    done <-chan interface{},
    in <-chan interface{},
) (_, _ <-chan interface{}) {
    out1 := make(chan interface{})
    out2 := make(chan interface{})

    go func() {
        defer close(out1)
        defer close(out2)

        for val := range orDone(done, in) {
            var out1, out2 = out1, out2
            for i := 0; i < 2; i++ {
                select {
                case <-done:
                case out1 <- val:
                    out1 = nil
                case out2 <- val:
                    out2 = nil
                }
            }
        }
    }()
    return out1, out2
}`

Upvotes: 2

Views: 192

Answers (2)

metalim
metalim

Reputation: 1613

(_, _ <-chan interface{}) is equivalent to (<-chan interface{}, <-chan interface{}). There are no differences, except source code length and readability.

  1. We start with (<-chan interface{}, <-chan interface{}) return value types.
  2. As return values can have names, one can write (ch1 <-chan interface{}, ch2 <-chan interface{}) to return same 2 channels.
  3. Sequence of arguments (or return values) with same types can omit types for all variables except last one. Hence our return types become: (ch1, ch2 <-chan interface{})
  4. And since we don't really need the names of return values, we can substitute names with underscore, making them anonymous again: (_, _ <-chan interface{})

Voila! Readable pair of channels of the same type.

Upvotes: 2

thst
thst

Reputation: 4602

This is the func declaration

FunctionType   = "func" Signature .
Signature      = Parameters [ Result ] .
Result         = Parameters | Type .
Parameters     = "(" [ ParameterList [ "," ] ] ")" .
ParameterList  = ParameterDecl { "," ParameterDecl } .
ParameterDecl  = [ IdentifierList ] [ "..." ] Type .

As you can see, the Result is like method's parameters a Parameters which in turn boils down to an IdentifierList. There comes the blank identifier _ that can replace every identifier in the IdentifierList.

The original author used this together with the "multiple identifiers declared to the same type" syntax to produce - as already mentioned - a strange to read declaration of two return values of the same type.

See https://golang.org/ref/spec#Function_declarations

You can also implement functions which "delete" parameters by using the blank identifier for them. May come handy, when you don't need the parameter of an interface you implement.

func foo(a string, _ int, b string) { ... }

The second parameter is not usable.

Upvotes: 0

Related Questions