Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
spekary opened this issue Jun 25, 2018 · 1 comment
Closed
Labels
FrozenDueToAge LanguageChange Suggested changes to the Go language Proposal v2 An incompatible library change
Milestone

Comments

@spekary
Copy link

spekary commented Jun 25, 2018

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.

@ianlancetaylor ianlancetaylor changed the title Go 2 proposal: Type switch on slices and maps of objects that match interface proposal: Go 2: Type switch on slices and maps of objects that match interface Jun 26, 2018
@gopherbot gopherbot added this to the Proposal milestone Jun 26, 2018
@ianlancetaylor ianlancetaylor added LanguageChange Suggested changes to the Go language v2 An incompatible library change and removed Proposal labels Jun 26, 2018
@ianlancetaylor
Copy link
Contributor

In the general case this will require creating a complete copy of the slice or map, in order to convert the values to the desired type. That in turn will cause confusion if the code changes an index. It could also lead to loss of type safety: if a []A is converted to a []fmt.Stringer in a type switch, and the type switch case changes an element of the slice, it could install a new value that is a fmt.Stringer but is not an A. And in fact that might happen by passing the slice to some other function entirely, in a different package. So the only way this could be implemented safely would be to change every assignment to an element of a slice of interface type to check whether the type is valid for the slice, or something like that. We aren't going to do this.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge LanguageChange Suggested changes to the Go language Proposal v2 An incompatible library change
Projects
None yet
Development

No branches or pull requests

4 participants