2017-11-11 5 views
4

나는 Go 신인이다.유형이 Go에서 함수가되는 방식은 무엇입니까?

나는 some Kubernetes source code을보고있다.

// 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 
} 

내가 이것을 읽는 방법을 hazily 알고,하지만 난 내 용어의 잘못을 얻을거야 확신 :

나는이 볼이 곳 keyLookupFunc라는 유형, 그리고 kl은 효과적으로이다 그것의 인스턴스이고이 함수는 GetByKey이라 불릴 수 있습니다. 그것은 key 유형이이 string입니다 받아, 그것은 세 가지 값을 반환 등 등

(나는 my best guess as to where it should live in the language specification에서이 특정 건설에 대한 BNF 표시되지 않습니다,하지만 난 그렇게하기 전에이 구성을 여러 번 본 적이 I 믿음에 그것을 가지고) 소스 코드에서 최대 높은

, 나는 이것을주의 사항 :.

// keyLookupFunc adapts a raw function to be a KeyLookup. 
type keyLookupFunc func() []testFifoObject 

좋아, 그럼 실제로 keyLookupFunc 일종이며,받는 함수가 무언가를 설명하는 데 사용되는 0 매개 변수를 반환하고 testFifoObject의 슬라이스를 반환합니다.

내 손에 keyLookupFunc 유형의 변수가있는 경우, GetByKey을 "on"으로 호출 할 수 있어야합니다. 나는이 상황에서 어떻게 함수가 하나의 유형처럼 행동 할 수 있는지 완전히 확신하지는 않지만 믿음으로 받아 들일 것입니다.

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") 호출 :

지금 나는 see this partial stuff,이 모든 사용 방법을 보려면 볼 때. fDeltaFIFO에 대한 포인터이며 I just happen to know is returned by NewDeltaFIFO입니다.

는 어떻게도 할 수있다, fDeltaFIFO에 대한 포인터임을 감안할 keyLookupFunc이 코드는 "의" 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 
} 

+3

'DeltaFIFO' **도 **'keyLookupFunc' 아니라, ** 그것도 방법이있다 **라고'GetByKey' https://github.com/kubernetes/kubernetes/blob/ 마스터/스테이징/src/k8s.io/client-go/tools/cache/delta_fifo.go # L392-L402. 두 개의 다른 유형은 같은 이름의 메소드를 가질 수 있습니다. 아무런 문제가 없습니다. – mkopriva

+0

감사합니다. 나는 그것을보아야 만했다. 얼마나 창피한가. 그러나이'GetByKey' 함수는 [이'.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' type ... 그런데 메소드가있는 함수 유형에 관심이 있다면'net/http.HandlerFunc'를 살펴보십시오. – mkopriva

답변

4

참고 두 GetByKey 방법은 두 개의 서로 다른 유형의 두 개의 방법 (이름이 같은 방법으로 두 가지 종류)이다

// 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) 
} 

을 또한 세 개의 전화 : (return f.GetByKey(key)에서 delta_fifo.go 파일에) 한 번 여기라고 (f.GetByKey("foo")에서 delta_fifo_test.go 파일에) 여기 시간 :

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. go # L51)은'* DeltaFIFO'의 인스턴스를 리턴하고'keyLookupFunc'는 리턴하지 않습니다. 나에게 그것은'keyLookupFunc'와 그 메소드'GetByKey'가 어디에서도 사용되지 않는 것 같습니다. 물론, 나는 뭔가를 놓치지 않았다. – mkopriva

+0

안녕하세요; 당신의 대답에 감사드립니다. 나는 @mkopriva와 동의하는 경향이있다. 당신이 참조하는 세 번의 호출은 제가 묻고있는 것입니다. 나는 여기에'GetByKey' 함수 호출의 "목표"가 아마도 keyLookupFunc 일 수있는 가능성을 보지 못합니다. –

+1

A.R의 답변이 정확합니다. 여러분이 가지고있는 문제는'keyLookupFunc' 타입에서'GetByKey'라는 메소드를 찾았지만,'GetByKey' 메소드가 여러가지 리시버와 함께 존재할 수 있다는 것입니다. 사실, DeltaFIFO는 자신의'GetByKey' (처음에는 A.R 참조)를 가지고 있기 때문에 원래 게시 된 코드의 어떤 것도'keyLookupFunc' 수신기로'GetByKey'를 호출하지 않습니다. – sberry