I have a function which takes an interface, like this:
func method(data interface{})
.. because I need to process different structs which have common fields/methods. In this function I use data
tens or hundreds of times, in different places. It's really unpleasant to add switch a.(type) { case .. case ..
all the time.
Is there a way to create a variable with just one switch
with needed type and then just use this variable everywhere later? Something like:
var a .... // something here
switch data.(type) {
case *Struct1:
a = data.(*Struct1)
case *Struct2:
a = data.(*Struct2)
}
// Continue with 'a' only
a.Param = 15
fmt.Println(a.String())
Go is a statically typed language, the type of a
must be known at compile time. And since Go does not support generics yet, you can't do what you want.
Try to come up with some other solution, e.g. abstract away the things you want to do with a
into an interface, and have the concrete types implement that interface. Then a
can be a variable of this interface type, and you can call methods of it.
If you can achieve this, actually you can even change the parameter of the data
type to this interface, and no type assertion or type switch is needed.
Alternatively you could use reflection to access common fields (either for get or set) identified by their name, but reflection provides no compile-time guarantee, and it's usually less efficient. For an example how to do that, see this question: Assert interface to its type
You can't do what you ask for in your question directly, go is statically typed, so you can't have one variable that can hold different types, and still access that variable as if it is typed.
If you're only working on the common struct fields in your method, you are perhaps better off gathering all the common variables in its own struct, illustrated below as the commons
struct and have your method
take that type as an argument
package main
import (
"fmt"
)
type commons struct {
name string
age int
}
type structA struct {
commons
other_stuff int
}
type structB struct {
commons
foo string
}
func method(c* commons) {
fmt.Println(c)
c.age +=1
}
func main() {
a := structA{commons{"foo", 44}, 1}
b := structB{commons{"bar", 33}, "test"}
method(&a.commons)
method(&b.commons)
fmt.Println(a)
}
I can't figure out what is your real goal but if the "method" you want to write handles common fields from similar structures, and you cannot fix original structures using Type Embedding, as @nos said above, then you can try to make another structure for method-internal use:
var v Vehicle // with common fields
switch data.(type) {
case *Car:
v.Handle = data.(*Car).Handle // or CircleHandle
case *Motorcycle:
v.Handle = data.(*Motorcycle).Handle // or BarHandle
}
v.Degree = 15
v.Speed = 50
v.Direction = "left"
v.Style = "rough"
/// so many things on `v`...
steering(v)
I think it is not a good approach but sometimes... :-)