猿问

识别存储在 go 接口中的实际类型

在下面的代码中


    var r io.Reader

    c, _ := net.Dial("tcp", ":8080")

    r = c 

    switch r.(type) {

    case io.Reader:

        fmt.Println("r implements the reader interface")

        // fallthrough

    case io.Writer:

        fmt.Println("r implements the writer interface")

    case net.Conn:

        fmt.Println("r implements the conn interface")

    }

第一个case语句是始终执行的语句。

如果我取消注释fallthrough代码将无法编译,因为fallthrough类型开关中不允许这样做

如果我没记错,go接口有 2 个值:

  • 存储在接口中的实际类型(描述符)(例如io.Writerio.Reader等)

  • 存储在其中的值

既然r显然满足上述所有case陈述,那么找到存储在中的确切类型的方法是什么r

是不是只能通过反射才能完成这个锥体?


德玛西亚99
浏览 200回答 2
2回答

慕斯王

类型切换和类型断言可用于检查接口值是否包含具体类型的值(同时提取该具体类型的值)。如果您检查的类型(或断言类型)是接口类型(而不是具体类型),则如果具体类型实现给定的接口类型,则大小写将匹配(或断言将成立)。net.Conn是一个接口,它是io.Reader和的超集io.Writer。如果某物 implements net.Conn,它也会自动实现io.Readerand io.Writer,所以如果你先检查io.Reader,那将匹配(如果类型也 implements net.Conn)。如果您想使用类型开关检查已实现的接口,请先检查net.Conn,如果未实现,请列出io.Reader并io.Writer稍后。switch r.(type) {case net.Conn:    fmt.Println("r implements the conn interface")case io.Reader:    fmt.Println("r implements the reader interface")case io.Writer:    fmt.Println("r implements the writer interface")}如果我没记错的话,go 接口有 2 个值:存储在接口中的实际类型(描述符)(例如 io.Writer、io.Reader 等)存储在其中的值你没有错,但你错过了一个关键点:实际的具体类型。io.Conn并且io.Reader不是具体类型,它们是接口类型。可能返回的示例具体net.Dial()类型是*net.TCPConn。

FFIVE

使用此代码查找值的具体类型:var r io.Readerc, _ := net.Dial("tcp", ":8080")r = c fmt.Printf("The type of r is %T\n", r)reflect 包也可用于查找具体类型:t := reflect.TypeOf(r)fmt.Println("The type of or is", t)使用单独的 if 语句来检查对每个接口的支持。类型开关无法测试所有接口,因为该开关继续使用第一个匹配的类型。if _, ok := r.(io.Reader); ok {    // we know this already because r is an io.Reader    fmt.Println("r implements the reader interface")}if _, ok := r.(io.Writer); ok {    fmt.Println("r implements the writer interface")}if _. ok := r.(net.Conn); ok {    fmt.Println("r implements the conn interface")}我们知道所有 if 语句中的条件都为 true,因为 in 的值r满足net.Conn接口。
随时随地看视频慕课网APP

相关分类

Go
我要回答