翻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
| type ChannelProvider func() (Channel, error)
|
而调用过程是这样的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| 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"
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"
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)
同理。