2 回答
TA贡献1871条经验 获得超13个赞
shapesinterface 是*rect实现的东西,但它不是一个具体的 type *rect。就像任何接口一样,它是一组方法,允许任何满足它的类型通过,就像给它一个临时的访客贴纸以登上建筑物。
例如,如果有一只猴子(或者说它的价值是一只海豚),它可以行动并做人类所能做的一切,那么在 Go 的大楼里,他可以越过守卫,登上电梯。然而,这并不使他在基因上成为人类。
Go 是静态类型的,这意味着即使没有类型断言或有意识地转换类型,即使是具有相同底层类型的两种类型也无法动态转换或强制相互转换。
var a int
type myInt int
var b myInt
a = 2
b = 3
b = a // Error! cannot use a (type int) as type myInt in assignment.
b = myInt(a) // This is ok.
和我一起想象一下这种情况:
type MyInt int
type YourInt int
type EveryInt interface {
addableByInt(a int) bool
}
func (i MyInt) addableByInt(a int) bool {
// whatever logic doesn't matter
return true
}
func (i YourInt) addableByInt(a int) bool {
// whatever logic doesn't matter
return true
}
func main() {
// Two guys want to pass as an int
b := MyInt(7)
c := YourInt(2)
// Do everything an `EveryInt` requires
// and disguise as one
bi := EveryInt(b)
ci := EveryInt(c)
// Hey, look we're the same! That's the closest
// we can get to being an int!
bi = ci // This is ok, we are EveryInt brotherhood
fmt.Println(bi) // bi is now 2
// Now a real int comes along saying
// "Hey, you two look like one of us!"
var i int
i = bi // Oops! bi has been made
// ci runs away at this point
}
现在回到你的场景——想象一下*circle实现shapes:
type circle struct {
Radius float64
}
func (c *circle) setWidth(w float64) {
c.Radius = w
}
*circle完全可以通过 asshapes但它没有Width属性,因为它不是*rect. 接口不能直接访问底层类型的属性,而只能通过实现的方法集来访问。为了访问属性,需要在接口上进行类型断言,以便实例成为具体类型:
var r *rect
// Verify `s` is in fact a `*rect` under the hood
if r, ok := s.(*rect); ok {
fmt.Println(r.Width)
}
这就是为什么像 Go 这样的静态类型语言总是比动态类型语言更快的核心,后者几乎总是使用某种反射来为您动态处理类型强制。
TA贡献1796条经验 获得超4个赞
s 是 shape 接口的实现者,但在 for 循环中没有输入为 rect。如果您执行类型断言以强制 s 为具体类型,如下所示:
s.(*rect).Width
你会得到你想要的。
但是,您需要小心混合这样的具体类型和接口。
- 2 回答
- 0 关注
- 229 浏览
添加回答
举报
