英文:
What exactly does .(data_type) method called/do?
问题
我遇到了一段使用.(string)
方法的代码。由于不知道这个方法的名称,我在搜索时遇到了困难。
这是我试图理解它的方式:
package main
import "fmt"
import "reflect"
func main(){
var b interface{}
b = "silly"
fmt.Println(reflect.TypeOf(b.(string))) // 我们知道b在编译时是一个字符串
fmt.Println(reflect.TypeOf(b)) // 我们不知道
}
结果:
string
string
然而,我认为reflect.TypeOf
是在运行时发生的,而.(string)
会告诉编译器b
确实是一个字符串,这可以用来告诉编译器变量的某种类型。我的理解正确吗?
英文:
I came a cross a piece of code that used .(string)
method. Not knowing what this is called I had difficulties searching for it.
Here is my try to understand it:
package main
import "fmt"
import "reflect"
func main(){
var b interface{}
b = "silly"
fmt.Println(reflect.TypeOf(b.(string))) // we know that b
// is a string
// at compile time
fmt.Println(reflect.TypeOf(b)) // we do not
}
Result:
string
string
However, I think that reflect.TypeOf
takes place at run time, while .(string)
would tell the compiler that b
is indeed a string, and this could be used to tell the compiler that a variable is of certain type. Is my understanding right?
答案1
得分: 15
b.(string)
被称为**类型断言。正如在Effective Go**中所述:
类型断言从接口值中提取指定显式类型的值。
因此,是的,从类型断言中获取的值不是接口值,而是显式类型的值。您还可以通过添加一个无类型布尔值来测试类型断言是否成功:
s, ok := b.(string) // s 的类型是 string
if !ok {
// b 不包含 string 类型的值!
}
编辑:
为了进一步解释以消除可能的误解:
正如您所提到的,类型断言并不是告诉 Go b
是一个字符串。它的作用是在运行时尝试从 b
中提取一个字符串,并在 b
包含其他类型时引发 panic(除非分配了可选的布尔值)。
从断言中获取的值确实是 string
类型,这使您可以执行诸如切片操作(无法对接口值进行切片)或检查其 len
等操作。
英文:
b.(string)
is called a type assertion. As written in Effective Go:
>A type assertion takes an interface value and extracts from it a value of the specified explicit type.
So, yes, the value you get from a type assertion is not an interface value, but is of the explicit type. You can also test if the type assertion was successful by adding an untyped boolean value:
s, ok := b.(string) // s is of type string
if !ok {
// b did not contain a value of type string!
}
Edit:
To explain further to clear out any possible misunderstanding:
A type assertion doesn't "tell Go that b is a string" as you suggested. What it does is that it will, in run time, try to extract a string from b
, and panic if b
contains some other type (unless assigning the optional bool value).
The value that you get from the assertion will indeed be of type string
, allowing you to do things like slicing (you cannot slice an interface value) or checking its len
.
答案2
得分: 2
之前的答案是正确的。但是我提交这个更像是实际情况中发生的情况。在 switch 语句中,通常会使用 .(type) 语法来处理类型名称。在这个例子中,I(整数表达式)、B(布尔表达式)和Bop(二元操作符)都是类型名称。
func commute(e Expr) (r Expr, d bool) {
switch exp := e.(type) {
case I:
r, d = exp, false
case B:
r, d = exp, false
case Bop:
r, d = Bop{exp.op, exp.right, exp.left}, true
default:
r, d = e, false
}
return
}
这不像 C 语言中的强制类型转换那样不安全,因为在 case 语句内部,你可以确保具有匹配的类型。当我读取一个通道时,我经常会看到这种情况,其中通道的类型是所有 case 都实现的接口类型。
英文:
The previous answer is correct. But I submit this as more like what happens in practice. The .(type) syntax is usually used with type names in the cases of a switch. In this example, I (integer expr), B (bool expr), and Bop (binary op) are type names.
func commute (e Expr) (r Expr, d bool) {
switch exp:= e.(type) {
case I: r,d = exp,false
case B: r,d = exp,false
case Bop: r,d = Bop{exp.op, exp.right, exp.left},true
default: r,d = e,false
}
return
}
This isn't unsafe like a C cast, because inside the case statement you are guaranteed to have the matching type. I see this quite a bit when reading a channel, where the type of the channel is an interface that all the cases implement.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论