Skip to content

proposal: Go 2: Type switch on slices and maps of objects that match interface #26056

@spekary

Description

@spekary

What did you do?

package main

import (
"fmt"
)


type A struct {
	s string
}

func (a A) String() string {
	return "I am " + a.s + "\n"
}


func main() {

	a := []A{{"a"}, {"b"}}
	b := map[string]A{"a":{"a"}, "b":{"b"}}

	var i1, i2 interface{}

	i1 = a
	i2 = b

	switch v := i1.(type) {
	case []fmt.Stringer:
		for _,s := range v {
			fmt.Print(s.String())
		}
	default:
		fmt.Println("Failed")
	}

	switch v2 := i2.(type) {
	case map[string]fmt.Stringer:
		for _,s := range v2 {
			fmt.Print(s.String())
		}
	default:
		fmt.Println("Failed")
	}

}

What did you expect to see?

I am a
I am b
I am a
I am b

What did you see instead?

Failed
Failed

Discussion

I realize this is currently as designed. I also realize there are other related issues around this, including generics, but I think this might be an inexpensive way of achieving a variety of goals.

Since this is within a type switch, there is an understanding with the developer that there is potential performance impacting type juggling going on. By controlling the order of the switch statements, the developer can decide when to ask the compiler to consider a slice or map of objects as to whether the inner object matches an interface.

I also realize that there is a type conversion issue inside of the for statements. A possible solution is that a type assertion in this way might cause the slice or map variable to have an internal indicator that if it is ranged over inside of the case, it will return the asked for interface instead. There are recursion issues here too, but that should be no problem since the asked for interface is inside of the returned type assertion variable, and a recursive type switch would create a new variable. So yes, its complex, but should be doable and quite helpful.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions