我遇到了一段使用.(string)
方法的代码。我不知道这叫什么,我很难找到它。
我试图理解它:
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
}
结果:
string
string
但是,我认为reflect.TypeOf
发生在运行时,而.(string)
会告诉编译器b
确实是一个字符串,这可以用来告诉编译器变量属于某种类型。我的理解是对的吗?
答案 0 :(得分:11)
b.(string)
被称为 type assertion 。如 Effective Go :
类型断言接受一个接口值,并从中提取指定显式类型的值。
所以,是的,从类型断言获得的值不是接口值,而是显式类型。您还可以通过添加无类型布尔值来测试类型断言是否成功:
s, ok := b.(string) // s is of type string
if !ok {
// b did not contain a value of type string!
}
修改强>
进一步解释清除任何可能的误解:
类型断言不会"告诉Go b b是一个字符串" 如你所建议的那样。它的作用是在运行时尝试从b
中提取字符串,如果b
包含其他类型,则会发生混乱(除非指定可选的bool值)。
从断言获得的值确实是string
类型,允许您执行切片(不能切片接口值)或检查其len
等内容。
答案 1 :(得分:1)
之前的答案是正确的。但我提交的内容更像是在实践中发生的事情。 。(类型)语法通常与交换机的类型名称一起使用。在此示例中,I(整数expr),B(bool expr)和Bop(二进制op)是类型名称。
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语句中你保证匹配类型。在阅读频道时我会看到这一点,其中频道的类型是所有案例实现的接口。