英文:
Using an interface within a struct in Go
问题
在尝试理解Go语言时,我在websocket.go
中遇到了这段代码(已剪辑):
type frameHandler interface {
HandleFrame(frame frameReader) (r frameReader, err error)
WriteClose(status int) (err error)
}
// Conn代表一个WebSocket连接。
type Conn struct {
config *Config
request *http.Request
.
.
frameHandler
PayloadType byte
defaultCloseStatus int
}
在Conn类型中,frameHandler
独自存在?一个没有名称的接口?
在代码的后面,他们甚至尝试检查这个可怜的接口是否为nil:
Conn(a).frameHandler == nil
我个人的猜测是,结构体中的frameHandler
是一个与frameHandler接口匹配的类型,并且还将具有名称frameHandler
。这个猜测正确吗?呵呵,不管怎样,这是一个有趣的语言。
英文:
In trying to understand Go, I ran into this piece of code in websocket.go
(snipped):
type frameHandler interface {
HandleFrame(frame frameReader) (r frameReader, err error)
WriteClose(status int) (err error)
}
// Conn represents a WebSocket connection.
type Conn struct {
config *Config
request *http.Request
.
.
frameHandler
PayloadType byte
defaultCloseStatus int
}
In the Conn type the frameHandler
stands there all alone? An interface without a name?
Later on in the code they even try check if the poor interface is nil:
Conn(a).frameHandler == nil
My own guess is that the frameHandler
within the struct is a type which matches the frameHandler interface, and on top of that will have the name frameHandler
. Is this correct? Hehe, fun language anyhow.
答案1
得分: 11
这一行:
frameHandler
大致等同于这个:
frameHandler frameHandler
其中frameHandler
既是字段的名称,也是它的类型。此外,它将frameHandler
的所有字段和方法添加到Conn
中,所以如果conn
是一个Conn
,那么conn.WriteClose(0)
意味着conn.frameHandler.WriteClose(0)
。
正如Go编程语言规范所述:
> 声明了一个类型但没有显式字段名的字段是一个<i>匿名字段</i>(俗称嵌入字段)。这样的字段类型必须指定为类型名<code>T</code>或非接口类型名的指针<code>*T</code>,而<code>T</code>本身不能是指针类型。未限定的类型名充当字段名。<pre>// 一个具有四个匿名字段T1、T2、P.T3和P.T4的结构体
struct {
T1 // 字段名为T1
T2 // 字段名为T2
P.T3 // 字段名为T3
P.T4 // 字段名为T4
x, y int // 字段名为x和y
}</pre> 下面的声明是非法的,因为字段名在结构体类型中必须是唯一的:<pre>struct {
T // 与匿名字段T和P.T冲突
T // 与匿名字段T和P.T冲突
P.T // 与匿名字段T和T冲突
}</pre> 匿名字段的字段和方法(§<a href="#Method_declarations">方法声明</a>)被提升为结构体的普通字段和方法(§<a href="#Selectors">选择器</a>)。对于一个名为<code>S</code>的结构体类型和一个名为<code>T</code>的类型,以下规则适用:<ul>
<li>如果<code>S</code>包含一个匿名字段<code>T</code>,则<code>S</code>的<a href="#Method_sets">方法集</a>包括<code>T</code>的方法集。
</li>
<li>如果<code>S</code>包含一个匿名字段<code>*T</code>,则<code>S</code>的方法集包括<code>*T</code>的方法集(它本身包括<code>T</code>的方法集)。
</li>
<li>如果<code>S</code>包含一个匿名字段<code>T</code>或<code>*T</code>,则<code>*S</code>的方法集包括<code>*T</code>的方法集(它本身包括<code>T</code>的方法集)。
</li>
</ul> 字段声明后可以跟一个可选的字符串字面量<i>标签</i>,它成为相应字段声明中所有字段的属性。这些标签通过<a href="#Package_unsafe">反射接口</a>可见,但在其他情况下被忽略。<pre>// 与TimeStamp协议缓冲区对应的结构体。
// 标签字符串定义了协议缓冲区字段的编号。
struct {
microsec uint64 "field 1"
serverIP6 uint64 "field 2"
process string "field 3"
}</pre>
英文:
This line:
frameHandler
is roughly equivalent to this:
frameHandler frameHandler
in that frameHandler
is both the name of the field and its type. In addition, it adds all the fields and methods of the frameHandler
to the Conn
, so if conn
is a Conn
, then conn.WriteClose(0)
means conn.frameHandler.WriteClose(0)
.
As the Go Programming Language Specification puts it:
> A field declared with a type but no explicit field name is an <i>anonymous field</i> (colloquially called an embedded field). Such a field type must be specified as a type name <code>T</code> or as a pointer to a non-interface type name <code>*T</code>, and <code>T</code> itself may not be a pointer type. The unqualified type name acts as the field name. <pre>// A struct with four anonymous fields of type T1, *T2, P.T3 and *P.T4
struct {
T1 // field name is T1
*T2 // field name is T2
P.T3 // field name is T3
*P.T4 // field name is T4
x, y int // field names are x and y
}</pre> The following declaration is illegal because field names must be unique in a struct type: <pre>struct {
T // conflicts with anonymous field *T and *P.T
*T // conflicts with anonymous field T and *P.T
*P.T // conflicts with anonymous field T and *T
}</pre> Fields and methods (§<a href="#Method_declarations">Method declarations</a>) of an anonymous field are promoted to be ordinary fields and methods of the struct (§<a href="#Selectors">Selectors</a>). The following rules apply for a struct type named <code>S</code> and a type named <code>T</code>: <ul>
<li>If <code>S</code> contains an anonymous field <code>T</code>, the
<a href="#Method_sets">method set</a> of <code>S</code> includes the
method set of <code>T</code>.
</li>
<li>If <code>S</code> contains an anonymous field <code>*T</code>, the
method set of <code>S</code> includes the method set of <code>*T</code>
(which itself includes the method set of <code>T</code>).
</li>
<li>If <code>S</code> contains an anonymous field <code>T</code> or
<code>*T</code>, the method set of <code>*S</code> includes the
method set of <code>*T</code> (which itself includes the method
set of <code>T</code>).
</li>
</ul> A field declaration may be followed by an optional string literal <i>tag</i>, which becomes an attribute for all the fields in the corresponding field declaration. The tags are made visible through a <a href="#Package_unsafe">reflection interface</a> but are otherwise ignored. <pre>// A struct corresponding to the TimeStamp protocol buffer.
// The tag strings define the protocol buffer field numbers.
struct {
microsec uint64 "field 1"
serverIP6 uint64 "field 2"
process string "field 3"
}</pre>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论