为什么明显会失败的类型断言不会引发语法错误?

huangapple go评论80阅读模式
英文:

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已经解释了为什么你的代码不会导致编译错误:float64interface{}的有效子类型。
如果不是这样,你在这里也会得到一个编译时错误,例如:

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.

huangapple
  • 本文由 发表于 2022年6月19日 20:39:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/72676957.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定