0%

Go的Function types学习

翻Fabric源码的时候看到了一个type ChannelProvider func() (Channel, error),半天没看懂是个啥,查了一下发现是go的Function types语法,于是记录一下。

问题

起因是在翻Fabric sdk创建的时候发现New函数很明显有一个channelProvider函数参数,

1
2
3
4
5
6
7
8
func New(channelProvider context.ChannelProvider, opts ...ClientOption) (*Client, error) {

channelContext, err := channelProvider()
if err != nil {
return nil, errors.WithMessage(err, "failed to create channel context")
}
...
}

但找了一下定义发现是这么一个东西:

1
2
// ChannelProvider returns channel client context
type ChannelProvider func() (Channel, error)

而调用过程是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//ChannelContext creates and returns channel context
func (sdk *FabricSDK) ChannelContext(channelID string, options ...ContextOption) contextApi.ChannelProvider {

channelProvider := func() (contextApi.Channel, error) {

clientCtxProvider := sdk.Context(options...)
return context.NewChannel(clientCtxProvider, channelID)

}

return channelProvider
}

clientChannelContext := sdk.ChannelContext(initInfo.ChannelID, fabsdk.WithUser(initInfo.UserName), fabsdk.WithOrg(initInfo.OrgName))

channelClient, err := channel.New(clientChannelContext)

Function Types

官方文档在这里,对其的定义是:

A function type denotes the set of all functions with the same parameter and result types.

首先来看一个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package main

import "fmt"

// Greeting function types
type Greeting func(name string) string

func say(g Greeting, n string) {
fmt.Println(g(n))
}

func english(name string) string {
return "Hello, " + name
}

func main() {
say(english, "World")
}

say()函数要求一个Greeting类型的函数参数,而english()函数由于参数输入输出均与Greeting类型相同,因此便能够作为参数传入say()中。

我的理解是这样定义了一个函数类型或者说函数集合,同样输入输出的函数被归为一类,感觉和go的Interface设计理念有点类似,只要函数接口相同就能够传入。

把上面的例子进一步扩展一下的话:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package main

import "fmt"

// Greeting function types
type Greeting func(name string) string

func (g Greeting) say(n string) {
fmt.Println(g(n))
}

func english(name string) string {
return "Hello, " + name
}

func french(name string) string {
return "Bonjour, " + name
}

func main() {
g := Greeting(english)
g.say("World")
g = Greeting(french)
g.say("World")
}

输出:

1
2
Hello, World
Bonjour, World

这就有点类的意思了。一开始先把func(name string) string这样的函数声明成Greeting类型,接着通过Greeting(english)english函数转换成Greeting类型(类似强制类型转换)。通过这个转换以后,就可以借由变量g调用Greeting类型的say()方法。Greeting(french)同理。