代码之家  ›  专栏  ›  技术社区  ›  pkaramol

识别go界面中存储的实际类型

go
  •  0
  • pkaramol  · 技术社区  · 4 年前

    在以下代码中

        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 鉴于以下情况,代码无法编译 跌倒 不允许在类型开关中使用

    如果我没有错 go 接口有两个值:

    • 存储在接口中的实际TYPE(描述符)(例如。 io.Writer , io.Reader 等等)
    • 存储在其中的值

    自从 r 显然满足上述所有条件 案例 语句,查找存储在中的确切类型的方法是什么 r ?

    这个圆锥体是通过反射完成的吗?

    2 回复  |  直到 4 年前
        1
  •  4
  •   icza    4 年前

    这个 type switch 以及 type assertion 可用于检查接口值是否包含具体类型的值(同时提取该具体类型的数值)。如果您检查的类型(或类型断言)是接口类型(而不是具体类型),如果具体类型实现了给定的接口类型,则情况将匹配(或断言将成立)。

    net.Conn 是两者的超集接口 io.Reader io.Writer 如果有什么东西实现了 网。康 ,它会自动执行 io.阅读器 io.作家 同样,如果你检查一下 io.阅读器 首先,这将匹配(如果该类型也实现 网。康 ).

    如果要使用类型开关检查已实现的接口,请检查 网。康 首先,如果没有实现,请列出 io.阅读器 io.作家 后来。

    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接口有两个值:

    • 存储在接口中的实际TYPE(描述符)(例如io.Writer、io.Reader等)
    • 存储在其中的值

    你没有错,但你错过了一个关键点:实际 混凝土 类型。 io.Conn io.阅读器 它们不是具体类型,而是界面类型。

    举个例子 混凝土 可能返回的类型 net.Dial() *net.TCPConn .

        2
  •  1
  •   3 revs<br/>user13631587&#13;    4 年前

    使用此代码查找值的具体类型:

    var r io.Reader
    c, _ := net.Dial("tcp", ":8080")
    r = c 
    fmt.Printf("The type of r is %T\n", r)
    

    反射包也可用于查找混凝土类型:

    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语句中的条件都为真,因为 r 满足 net.Conn 界面。