【问题标题】:What exactly does .(data_type) method called/do?.(data_type) 方法调用/做什么究竟是什么?
【发布时间】:2015-03-10 01:50:49
【问题描述】:

我遇到了一段使用.(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 确实是一个字符串,这可以用来告诉编译器变量是某种类型.我的理解对吗?

goplayground

【问题讨论】:

    标签: go


    【解决方案1】:

    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 包含其他类型(除非分配可选的 bool 值),则会出现恐慌。

    您从断言中获得的值确实是 string 类型,允许您执行切片(不能切片接口值)或检查其 len 等操作。

    【讨论】:

    • 非常有帮助。谢谢。
    • 一个更好的例子是将它与开关一起使用。 Go 在任何地方都使用带有开关的类型断言,这样你就可以传递未知类型的东西,而不会发现自己在处理一个不正确的转换对象的分支。
    • @Rob 如果您觉得缺少一个很好的例子,请随时在您的答案中添加它。
    【解决方案2】:

    前面的答案是正确的。但我认为这更像是在实践中发生的事情。在开关的情况下,.(type) 语法通常与类型名称一起使用。在本例中,I (integer expr)、B (bool expr) 和 Bop (binary 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 语句中,您可以保证具有匹配的类型。我在阅读频道时看到了很多,其中频道的类型是所有案例都实现的接口。

    【讨论】:

    • Type switches 是独立于type assertions 的概念和构造。让前者使用x.(type) 语法而不是(比如说)typeof(x) 只是一个任意(但很好)的设计选择。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-01-28
    • 1970-01-01
    • 2013-02-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多