[英]Identifying the actual type being stored in a go interface
In the following code在下面的代码中
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")
}
the first case
statement is the one that's always executed.第一个
case
语句是始终执行的语句。
If I uncomment fallthrough
the code does not compile given that fallthrough
is not allowed in a type switch如果我取消注释
fallthrough
则代码不会编译,因为类型开关中不允许fallthrough
If I am not wrong a go
interface has 2 values:如果我没有错的话,
go
接口有 2 个值:
io.Writer
, io.Reader
etc)io.Writer
、 io.Reader
等)Since r
apparently satisfies all of the above case
statements, what is the way of finding the exact type stored in r
?由于
r
显然满足上述所有case
语句,那么找到存储在r
的确切类型的方法是什么?
Is it only through reflection that this cone be done?这个锥体是通过反思才完成的吗?
The type switch as well as the type assertion may be used to check if an interface value holds a value of a concrete type (and at the same time extract a value of that concrete type).类型开关以及类型断言可用于检查接口值是否包含具体类型的值(并同时提取该具体类型的值)。 If the type you check (or type assert) is an interface type (and not a concrete type), the case will match (or the assertion will hold) if the concrete type implements the given interface type.
如果您检查的类型(或类型断言)是接口类型(而不是具体类型),则如果具体类型实现给定的接口类型,则案例将匹配(或断言将成立)。
net.Conn
is an interface that is a superset of both io.Reader
and io.Writer
. net.Conn
是一个接口,它是io.Reader
和io.Writer
的超集。 If something implements net.Conn
, it automatically implements io.Reader
and io.Writer
as well, so if you check io.Reader
first, that will match (if the type also implements net.Conn
).如果某些东西实现了
net.Conn
,它net.Conn
自动实现io.Reader
和io.Writer
,所以如果你先检查io.Reader
,那将匹配(如果类型也实现了net.Conn
)。
If you want to use a type switch to check for implemented interfaces, check for net.Conn
first, and if it's not implemented, list io.Reader
and io.Writer
later on.如果要使用类型开关检查实现的接口,请先检查
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")
}
If I am not wrong a go interface has 2 values:
如果我没有错的话,go 接口有 2 个值:
- the actual TYPE (descriptor) stored in the interface (eg io.Writer, io.Reader etc)
存储在接口中的实际 TYPE(描述符)(例如 io.Writer、io.Reader 等)
- the value stored in it
存储在其中的值
You are not wrong but you miss a key point: the actual concrete type.你没有错,但你错过了一个关键点:实际的具体类型。
io.Conn
and io.Reader
are not concrete types, they are inteface types. io.Conn
和io.Reader
不是具体类型,它们是接口类型。
An example concrete type that may be returned by net.Dial()
is *net.TCPConn
. net.Dial()
可能返回的一个具体类型示例是*net.TCPConn
。
Use this code to find the concrete type of the value:使用此代码查找值的具体类型:
var r io.Reader
c, _ := net.Dial("tcp", ":8080")
r = c
fmt.Printf("The type of r is %T\n", r)
The reflect package can also be used to find the concrete type:反射包也可用于查找具体类型:
t := reflect.TypeOf(r)
fmt.Println("The type of or is", t)
Use separate if statements to check support for each interface.使用单独的 if 语句来检查对每个接口的支持。 A type switch cannot test for all interfaces because the switch continues on the the first type to match.
类型交换机无法测试所有接口,因为交换机会继续匹配第一个类型。
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")
}
We know that the conditions in all of the if statements evaluate to true because the value in r
satisfies the net.Conn
interface.我们知道所有 if 语句中的条件评估为真,因为
r
的值满足net.Conn
接口。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.