Go figure

Learning a new programming language is painful sometimes. I remember when I was learning Python, and I would run into language quirks all the time. It was only after suffering through a few embarrassing pull requests that I finally grokked the dang thing.

The same thing is happening to me in Go. Let’s say you have two structs that have the same field:

type A struct {
    C string
}

type B struct {
    C string
}

and then you have a list of interfaces that include two of these:

interfaces := []interface{}{A{"hello"}, B{"world"}}

In this reduced example, all I wanted to do was access C from both of these. It seemed natural to use a type switch:

for _, value := range interfaces {
    switch c := value.(type) {
    case A, B:
        fmt.Println(c.C)
    }
}

Uh oh. Go complains that c is still an interface, and as a result has no field C. That’s really strange, because this definitely works:

for _, value := range interfaces {
    switch c := value.(type) {
    case A:
        fmt.Println(c.C)
    case B:
        fmt.Println(c.C)
    }
}

So what doesn’t work with a compound case statement works just fine when you break the statement up into multiple cases. This baffled me.

It took some creative Googling to find this gem in the spec:

The TypeSwitchGuard may include a short variable declaration. When that form is used, the variable is declared at the end of the TypeSwitchCase in the implicit block of each clause. In clauses with a case listing exactly one type, the variable has that type; otherwise, the variable has the type of the expression in the TypeSwitchGuard.

In non-Golangese, this just means that a case has a single listing, the variable after switch takes on the type of the case. If the case has more than one listing, it stays its original type, which is interface{}.

I wish this type of thing would be more obvious. I expected the first pattern to be fully acceptable, or error out if compilation finds that one of the types doesn’t have a C field. It’s more expressive and avoids duplication, both strong indicators of a proper language construct. Go figure, I guess.

 
4
Kudos
 
4
Kudos

Now read this

Tools

I don’t use many tools. I used to think that the most important thing when choosing which tools to use is to use the one that’s most suited for the task. Not every problem is a nail, so put that hammer away sorta thing. I’ve since... Continue →