首页 > 解决方案 > 识别存储在 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 个值:

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

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

标签: gotypesinterface

解决方案


类型切换类型断言可用于检查接口值是否包含具体类型的值(同时提取该具体类型的值)。如果您检查的类型(或断言类型)是接口类型(而不是具体类型),则如果具体类型实现给定的接口类型,则大小写将匹配(或断言将成立)。

net.Conn是一个接口,它是io.Reader和的超集io.Writer。如果某物 implements net.Conn,它也会自动实现io.Readerand io.Writer,所以如果你先检查io.Reader,那将匹配(如果类型也 implements net.Conn)。

如果您想使用类型开关检查已实现的接口,请先检查net.Conn,如果未实现,请列出io.Readerio.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


推荐阅读