英文:
Why type assertion that surely fails is not a syntax error?
问题
我正在阅读这个Go语言之旅。
最初,我声明了一个类型为字符串的接口。
var i interface{} = "hello"
但是当我们执行以下操作时:
f = i.(float64) // panic
我的问题是,为什么在Go语言中这个错误没有在编译时被捕获。
C++的泛型在编译时就会捕获这个错误,而不像Go语言一样在运行时才决定。
在编译期间,i
的"类型"信息是存在的。
这种问题从Go语言程序员的角度来看,更容易在编译期间捕获,而不是在运行时。
编辑:Eduardo Thales建议后来在Go语言中引入了泛型。我原以为接口的底层机制就是泛型,显然不是。谢谢Eduardo的指正。
英文:
I was going through this tour of go.
Initially i is declared an interface with type string.
var i interface{} = "hello"
But when we do
f = i.(float64) // panic
My question is, why isn't this caught during compile time in golang.
C++ generics catch this during compile time, unlike go which decides to do it at runtime.
The "type" information for i
exists during compilation.
This kind of issue would be something that would make it easier (from a golang programmer's perspective) to catch during compilation than runtime.
edit: Eduardo Thales suggested that generics were included later in golang. I was under the assumption that the underlying mechanism of interfaces is generics. apparently not. Thanks Eduardo
答案1
得分: 2
语言规范明确指出,错误的类型断言会导致运行时恐慌。请参阅:
> 如果类型断言为假,将发生运行时恐慌。
此外,语言中没有规定不能编写一个明确导致恐慌的程序。例如,下面是一个有效的程序,可以在没有错误的情况下编译通过:
package main
import "fmt"
func main() {
fmt.Println("Don't panic!")
panic(1)
}
英文:
The language specification explicitly says that false type assertions cause a run-time panic. See:
> If the type assertion is false, a run-time panic occurs.
Also, there's nothing in the language that says that you can't make a program that will unambiguously panic. For example, this is a valid program that will compile without error:
package main
import "fmt"
func main() {
fmt.Println("Don't panic!")
panic(1)
}
答案2
得分: 2
你混淆了泛型和变量类型。
以这个例子为例:
items := []string{"item1", "item2"}
fmt.Println(slices.Contains(items, "item1"))
变量类型是slice
。泛型部分是string
,在slices.Contains
中被视为泛型。
因此,fmt.Println(slices.Contains(items, 1))
会导致编译时错误,因为泛型类型string
与泛型类型int
不匹配。
(注意:slice
并不是Go中典型泛型的最佳代表,因为它们通常看起来不同,但它是最容易理解概念的一个例子。)
@mkopriva已经解释了为什么你的代码不会导致编译错误:float64
是interface{}
的有效子类型。
如果不是这样,你在这里也会得到一个编译时错误,例如:
var i string = "hello"
f := i.(float64) // 编译时错误
然而,在这里甚至不存在泛型,你的示例中也是如此。
英文:
You're mixing up generics and variable types.
Take this as an example:
items := []string{"item1", "item2"}
fmt.Println(slices.Contains(items, "item1"))
The variable type is slice
. The generic part is string
, which is regarded in slices.Contains
.
So, fmt.Println(slices.Contains(items, 1))
would cause a compile time error because the generic type string
doesn't match the generic type int
.
(NB: slice
is not the best representative of a typical generic in Go because usually they look different, but it's the easiest one to grasp the concept.)
@mkopriva has already answered why your code doesn't cause a compile error: float64
is a valid subtype of interface{}
.
If it wasn't, you'ld get a compile time error here as well, e.g. as in
var i string = "hello"
f := i.(float64) // compile time error
Generics don't even exist here, though, and neither they did in your example.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论