任何人都可以理解connStateInterface?

use*_*446 5 go

func (c *conn) setState(nc net.Conn, state ConnState) {
    ...
    c.curState.Store(connStateInterface[state])
    ...
}

// connStateInterface is an array of the interface{} versions of
// ConnState values, so we can use them in atomic.Values later without
// paying the cost of shoving their integers in an interface{}.
var connStateInterface = [...]interface{}{
    StateNew:      StateNew,
    StateActive:   StateActive,
    StateIdle:     StateIdle,
    StateHijacked: StateHijacked,
    StateClosed:   StateClosed,
}
Run Code Online (Sandbox Code Playgroud)

我无法弄清楚connStateInterface的技巧,它究竟是如何工作的?

Edd*_* R. 7

这里有一些事情......

[...]声明创建实际的阵列,而不是一个切片,以使得间接被去除.这里宣布的是一系列interface{}类型......所以你可能想知道为什么奇怪的地图符号?

StateXXX变量只是上面进一步声明的常量,所以他们是整数...这样的声明实际上是形式为index: value.

这是使用一组int的一个不太模糊的例子:

var i = [...]int{4: 2, 2: 7}
Run Code Online (Sandbox Code Playgroud)

这将分配一个包含:

[0, 0, 7, 0, 2]
Run Code Online (Sandbox Code Playgroud)

...注意索引2有7,索引4有2.不是一种声明数组的常用方法,但它是有效的Go.

所以回到原始声明,只需要我上面给出的例子,而不是int,创建类型的数组interface{}:

var i = [...]interface{}{4: 2, 2: 7}
Run Code Online (Sandbox Code Playgroud)

你会得到一个类似的数组,但nil接口值代替零.

更接近原始代码,StateXXX常量只是整数,而不是像我的例子中的文字.

那么,这一切有什么意义呢?为什么所有的混淆?

这是一次表演黑客攻击.该函数c.curState.Store()采用类型的参数interface{}.如果你要传递一个int,那么编译后的代码就必须在每次调用时转换类型.一个更清晰(但显然不切实际)的例子可能是:

var val interface{}

for i := 0; i < 1000000; i++ {
    // the types are different, compiler has to fumble int vs. interface{}
    val = i
    // do something with val
}
Run Code Online (Sandbox Code Playgroud)

每次你进行val = i转换intinterface{}需要发生.您发布的代码通过创建静态查找表来避免这种情况,其中所有值都已经是接口类型.

因此,这个:

c.curState.Store(connStateInterface[state])
Run Code Online (Sandbox Code Playgroud)

比这更有效:

c.curState.Store(state)
Run Code Online (Sandbox Code Playgroud)

由于state会,在这种情况下,需要进行的int -> interface{}转换.在优化代码中,state仅仅是一个将值查找到数组中的索引,其结果会使您获得interface{}...因此int -> interface{}可以避免类型转换.

我不熟悉那些代码,但我认为它处于一个关键的路径中,纳秒或任何节省的成本可能会产生影响.