I dunno if I'd consider having a dummy method on an interface as "elegant", but it does work. A trade-off of keeping the language very simple, for sure.
What I really wish Go had was sum types, Rust style. That'd cover enumerations and more.
If you are satisfied with a dummy method on an interface, you can continue by adding more types to that interface. Color is not a great example, so:
type Vehicle interface {
isVehicle()
}
type Car struct {}
func (c Car) isVehicle() {}
type Van struct {}
func (v Van) isVehicle() {}
func VehicleType(vehicle Vehicle) {
switch v := vehicle.(type) {
case Car:
fmt.Println("car")
case Van:
fmt.Println("van")
default:
fmt.Println("unknown vehicle")
}
This covers most, but not all, of the bases, in that you don't get exhaustiveness checking at compile time, unless you adjoin a linter to your compile process: https://github.com/BurntSushi/go-sumtype