2017-11-11 112 views
4

我是個新手。我正在尋找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?我如何連接這些點?

+3

'DeltaFIFO' **是不是也**'keyLookupFunc',但**它也有一個方法叫**'GetByKey' https://github.com/kubernetes/kubernetes/blob/主/分期/ src目錄/ k8s.io /客戶去/工具/緩存/ delta_fifo.go#L392-L402。兩種不同的類型可以有一個名稱相同的方法,在那裏沒有問題。 – mkopriva

+0

謝謝;我應該看到的;多麼尷尬。然而,這意味着這個'GetByKey'函數不會在[this'.go'文件]的其餘部分使用(https://github.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io /client-go/tools/cache/delta_fifo.go),對不對? –

+1

看起來好像不是,也許它是遺留的,也許它是爲了以後使用的東西,我不知道。如果你[搜索](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

回答

4

注意兩個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 
} 

,這是不使用(不叫)。

+1

您的答案的第二部分對我來說似乎不正確,[NewDeltaFIFO](https://github.com/kubernetes/kubernetes/blob/2986b37de06fcd1bf94e68b49b6c8d87c389d3c2/staging/src/k8s.io/client-go/tools/cache/delta_fifo。去#L51)返回'* DeltaFIFO'的實例,而不是'keyLookupFunc'。對我來說''keyLookupFunc'和它的方法'GetByKey'不會在任何地方使用。當然,除非我錯過了一些東西。 – mkopriva

+0

嗨;感謝您的回答。我傾向於同意@mkopriva;你引用的三個調用正是我所問的。我不明白這裏GetByKey函數調用的「目標」有可能是'keyLookupFunc',這似乎是一個需求。 –

+1

A.R的回答是正確的。您遇到的問題是您在'keyLookupFunc'類型上找到了一個名爲'GetByKey'的方法,但很多'GetByKey'方法可以與各種接收器一起存在。事實上,'DeltaFIFO'有它自己的'GetByKey'(在開始時就是A.R引用),所以最初發布的代碼中沒有任何東西是用'keyLookupFunc'接收器調用'GetByKey'。 – sberry

相關問題