I started using Golang recently and stumbled across a problem:
I have two structs, human
and alien
, which are both based on the creature
struct. I want to initialize one of them based on the value of the isAlien
boolean inside of an if-statement.
Using the human := human{}
notation or the alien equivalent inside the if blocks to initialize, the instances aren't accessible from outside of the if-statement.
On the other hand, the usual solution of declaring the type and the name of the variable before the if-statement and initializing the variable inside the if-statement doesn't work, because there two are different types:
var h human //use human or alien here?
if isAlien {
h = alien{} //Error: incompatible types
} else {
h = human{}
}
//same when swapping human with alien at the declaration
I know that I could just declare both types before the if-statement but that solution doesn't seem elegant to me.
Is there some obvious solution that I'm missing here?
As you noted, the problem is clearly represented by this statement:
var h human //use human or alien here?
If you plan to use that h
variable there after creating the objects, then the type of h
must be one that can accept either a human
or alien
as a value.
The way to do this in Go is by using an ìnterface
that both alien
and human
can fulfil.
So you should declare an interface like:
type subject interface {
// you should list all functions that you plan to use on "h" afterwards
// both "human" and "alien" must implement those functions
}
Then:
var h subject
Will do the trick.
So, I'm going to go out on a limb and say you're probably thinking about this the wrong way.
The first question that occurs to me looking at your example is: what's the return type of this function? In other words, what signature do you need h
to be? If alien
has an embedded struct creature
(which seems to be the inheritance pattern you're trying to follow), and you return a human
from your function after declaring h
to be a creature
, anything that consumes your function will only know that it's dealing with a creature
, so there's no point in declaring it a human
or an alien
in the first place.
I suspect that what you really want to be doing is moving away from concrete structs here and instead using interfaces. In that world, you'd have a creature
interface, and both human
and alien
would satisfy the creature
interface. You wouldn't necessarily know which one you were dealing with downstream, but you'd be able to reliably call creature
methods and the appropriate human
or alien
implementation would be invoked.