英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论