一个类型在Go中如何成为函数?
我是个新手。我正在寻找some Kubernetes source code。一个类型在Go中如何成为函数?
我看到这一点:
// GetByKey returns the key if it exists in the list returned by kl.
func (kl keyLookupFunc) GetByKey(key string) (interface{}, bool, error) {
for _, v := range kl() {
if v.name == key {
return v, true, nil
}
}
return nil, false, nil
}
我朦胧地知道如何阅读,但我敢肯定,我会得到我的术语错误:有一个地方叫keyLookupFunc
类型,kl
是有效的它的实例,并且可以调用名为GetByKey
的此函数。它接受一个key
类型为string
,并返回三个值,等等,等等
(我没有看到BNF在my best guess as to where it should live in the language specification这个特殊的建筑,但我之前,所以见过这种结构好几次我只要相信)
越往上源代码,我注意到这一点:
// keyLookupFunc adapts a raw function to be a KeyLookup.
type keyLookupFunc func() []testFifoObject
OK,所以确实keyLookupFunc
是一种类型,它是用来描述的东西,是需要一个功能零参数并返回一片testFifoObject
s。如此天真,如果我手上有一个keyLookupFunc
-type变量,我应该可以调用GetByKey
“on”。我不完全确定一个函数在这种情况下的行为如何,但我会信赖它。
现在,当我看看,看看这是怎么用的,我see this partial stuff:
func TestDeltaFIFO_requeueOnPop(t *testing.T) {
f := NewDeltaFIFO(testFifoObjectKeyFunc, nil, nil)
f.Add(mkFifoObj("foo", 10))
_, err := f.Pop(func(obj interface{}) error {
if obj.(Deltas)[0].Object.(testFifoObject).name != "foo" {
t.Fatalf("unexpected object: %#v", obj)
}
return ErrRequeue{Err: nil}
})
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if _, ok, err := f.GetByKey("foo"); !ok || err != nil {
t.Fatalf("object should have been requeued: %t %v", ok, err)
}
注意f.GetByKey("foo")
调用。 f
是指向DeltaFIFO
,其中I just happen to know is returned by NewDeltaFIFO
。
鉴于f
是一个指向DeltaFIFO
,怎么还可以是这样keyLookupFunc
,这个代码可以“”它叫GetByKey
?我如何连接这些点?
注意两个GetByKey
方法是在两个不同类型的两个单独的方法中,(两种不同类型的与具有相同名称的方法):
注意最后f.GetByKey
是:
// GetByKey returns the complete list of deltas for the requested item,
// setting exists=false if that list is empty.
// You should treat the items returned inside the deltas as immutable.
func (f *DeltaFIFO) GetByKey(key string) (item interface{}, exists bool, err error) {
f.lock.RLock()
defer f.lock.RUnlock()
d, exists := f.items[key]
if exists {
// Copy item's slice so operations on this slice (delta
// compression) won't interfere with the object we return.
d = copyDeltas(d)
}
return d, exists, nil
}
和这调用一次在这里(在delta_fifo.go
文件在return f.GetByKey(key)
):
// Get returns the complete list of deltas for the requested item,
// or sets exists=false.
// You should treat the items returned inside the deltas as immutable.
func (f *DeltaFIFO) Get(obj interface{}) (item interface{}, exists bool, err error) {
key, err := f.KeyOf(obj)
if err != nil {
return nil, false, KeyError{obj, err}
}
return f.GetByKey(key)
}
而且也叫三这里次(delta_fifo_test.go
文件在f.GetByKey("foo")
):
func TestDeltaFIFO_requeueOnPop(t *testing.T) {
f := NewDeltaFIFO(testFifoObjectKeyFunc, nil, nil)
f.Add(mkFifoObj("foo", 10))
_, err := f.Pop(func(obj interface{}) error {
if obj.(Deltas)[0].Object.(testFifoObject).name != "foo" {
t.Fatalf("unexpected object: %#v", obj)
}
return ErrRequeue{Err: nil}
})
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if _, ok, err := f.GetByKey("foo"); !ok || err != nil {
t.Fatalf("object should have been requeued: %t %v", ok, err)
}
_, err = f.Pop(func(obj interface{}) error {
if obj.(Deltas)[0].Object.(testFifoObject).name != "foo" {
t.Fatalf("unexpected object: %#v", obj)
}
return ErrRequeue{Err: fmt.Errorf("test error")}
})
if err == nil || err.Error() != "test error" {
t.Fatalf("unexpected error: %v", err)
}
if _, ok, err := f.GetByKey("foo"); !ok || err != nil {
t.Fatalf("object should have been requeued: %t %v", ok, err)
}
_, err = f.Pop(func(obj interface{}) error {
if obj.(Deltas)[0].Object.(testFifoObject).name != "foo" {
t.Fatalf("unexpected object: %#v", obj)
}
return nil
})
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if _, ok, err := f.GetByKey("foo"); ok || err != nil {
t.Fatalf("object should have been removed: %t %v", ok, err)
}
}
而另一种方法是:
// GetByKey returns the key if it exists in the list returned by kl.
func (kl keyLookupFunc) GetByKey(key string) (interface{}, bool, error) {
for _, v := range kl() {
if v.name == key {
return v, true, nil
}
}
return nil, false, nil
}
,这是不使用(不叫)。
您的答案的第二部分对我来说似乎不正确,[NewDeltaFIFO](https://github.com/kubernetes/kubernetes/blob/2986b37de06fcd1bf94e68b49b6c8d87c389d3c2/staging/src/k8s.io/client-go/tools/cache/delta_fifo。去#L51)返回'* DeltaFIFO'的实例,而不是'keyLookupFunc'。对我来说''keyLookupFunc'和它的方法'GetByKey'不会在任何地方使用。当然,除非我错过了一些东西。 – mkopriva
嗨;感谢您的回答。我倾向于同意@mkopriva;你引用的三个调用正是我所问的。我不明白这里GetByKey函数调用的“目标”有可能是'keyLookupFunc',这似乎是一个需求。 –
A.R的回答是正确的。您遇到的问题是您在'keyLookupFunc'类型上找到了一个名为'GetByKey'的方法,但很多'GetByKey'方法可以与各种接收器一起存在。事实上,'DeltaFIFO'有它自己的'GetByKey'(在开始时就是A.R引用),所以最初发布的代码中没有任何东西是用'keyLookupFunc'接收器调用'GetByKey'。 – sberry
'DeltaFIFO' **是不是也**'keyLookupFunc',但**它也有一个方法叫**'GetByKey' https://github.com/kubernetes/kubernetes/blob/主/分期/ src目录/ k8s.io /客户去/工具/缓存/ delta_fifo.go#L392-L402。两种不同的类型可以有一个名称相同的方法,在那里没有问题。 – mkopriva
谢谢;我应该看到的;多么尴尬。然而,这意味着这个'GetByKey'函数不会在[this'.go'文件]的其余部分使用(https://github.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io /client-go/tools/cache/delta_fifo.go),对不对? –
看起来好像不是,也许它是遗留的,也许它是为了以后使用的东西,我不知道。如果你[搜索](https://github.com/kubernetes/kubernetes/search?utf8=%E2%9C%93&q=keyLookupFunc&type=),你可以看到该标识符仅用于大约1年的文档。 ..如果你[搜索](https://github.com/kubernetes/kubernetes/search?utf8=%E2%9C%93&q=testFifoObject&type=),你会看到没有实际的功能匹配'keyLookupFunc'类型...顺便说一下,如果你对函数类型感兴趣,可以看看'net/http.HandlerFunc',它很有名。 – mkopriva