英文:
Initialize struct with global scope where type depends on boolean
问题
我最近开始使用Golang,并遇到了一个问题:
我有两个结构体,human
和alien
,它们都基于creature
结构体。我想根据if语句中的isAlien
布尔值的值来初始化其中一个。
在if块中使用human := human{}
或等效的alien初始化方式,实例在if语句外部是不可访问的。
另一方面,通常的解决方案是在if语句之前声明变量的类型和名称,并在if语句内部初始化变量,但这种方法不起作用,因为这两个类型是不同的:
var h human //在这里使用human还是alien?
if isAlien {
h = alien{} //错误:类型不兼容
} else {
h = human{}
}
//当在声明中将human替换为alien时,情况相同
我知道我可以在if语句之前声明两种类型,但这个解决方案对我来说不够优雅。
这里有什么明显的解决方案我忽略了吗?
英文:
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?
答案1
得分: 2
正如你所指出的,这个问题可以通过以下语句清晰地表示:
var h human // 在这里使用 human 还是 alien?
如果你计划在创建对象后使用变量 h
,那么 h
的类型必须能够接受 human
或 alien
作为值。
在 Go 语言中,可以通过使用一个 interface
来实现这一点,这个 interface
可以被 alien
和 human
都满足。
所以你应该声明一个类似这样的 interface
:
type subject interface {
// 你计划在之后使用 "h" 的所有函数都应该列在这里
// "human" 和 "alien" 都必须实现这些函数
}
然后:
var h subject
就可以解决问题了。
英文:
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.
答案2
得分: 1
所以,我要冒昧地说,你可能以错误的方式思考了这个问题。
看到你的示例后,我首先想到的问题是:这个函数的返回类型是什么?换句话说,你需要h
是什么样的签名?如果alien
有一个嵌入的结构体creature
(这似乎是你试图遵循的继承模式),并且在声明h
为creature
后从函数中返回一个human
,那么使用该函数的任何东西只会知道它正在处理一个creature
,所以一开始将其声明为human
或alien
是没有意义的。
我怀疑你真正想做的是摆脱具体的结构体,而是使用接口。在这种情况下,你会有一个creature
接口,human
和alien
都会满足creature
接口。你不一定知道你正在处理哪一个,但你可以可靠地调用creature
的方法,适当的human
或alien
实现将被调用。
英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论