2014-04-07 2 views
3

최근에 net/http 패키지에서 가장 혼란스러워하는 사용 패턴이 있습니다. 함수형 변환입니다. 그것은 다음과 같이이다 :Go에서 다른 유형으로 기능 변환 (함수 캐스팅)

(function a) ->convert to-> (type t) 
(type t) ->implentments-> (interface i) 

그래서 그 매개 변수로 인터페이스 i을받는 함수가 있다면, 그것은 함수 a를 호출합니다,이 net/http이 그것을 구현하는 방법입니다.

하지만 내 자신의 코드를 작성할 때이 패턴에 대해 많은 오해가있었습니다. 내 코드는 다음과 같이 진행됩니다

package main 

import (
    "fmt" 
) 

type eat interface { 
    eat() 
} 
type aaa func() 

func (op *aaa) eat() {//pointer receiver not right 
    fmt.Println("dog eat feels good") 
} 

/////////////////////////////////////////////// 
func dog() { 
    fmt.Println("I'm a dog") 
} 
/////////////////////////////////////////////// 

func feelsGood(a eat) { 
    a.eat() 
} 

func main() { 
    b := aaa(dog) 
    feelsGood(b) 
} 

//error:aaa does not implement eat (eat method has pointer receiver) 

유형 AAA는 방법은 인터페이스 먹고의 규칙을 준수 동일한 기능의 이름과 매개 변수 서명을 먹고, 그러나 왜 그 오류를 주는가? 수신기가 중요합니까?

또 다른 질문은, 단지 기능과 유형 인 인터페이스를 제외하고, 코드는 다음과 같이 진행됩니다

package main 

import (
    "fmt" 
) 

type aaa func() 

func (op *aaa) eat() { 
    op() 
} 

/////////////////////////////////////////////// 
func dog() { 
    fmt.Println("I'm a dog") 
} 
/////////////////////////////////////////////// 

func main() { 
    obj:=aaa(dog) 
    obj.eat() 
} 
//error:cannot call non-function op (type *aaa) 

첫째, op이 오류에 관계없이, 익명 함수인가?

둘째, 별표를 제거한 후에도 잘 작동하지만 그 이유는 무엇입니까? opaaa의 인스턴스이고 수신기는 op이고 op은 dog() 함수를 의미합니까? http 패키지는 같은 방법으로 f(w,r)을 사용하지만, 이해하기가 약간 어렵습니다. op은 유형, 인스턴스 또는 익명의 함수입니까?

기능 변환에 대한 내 이해가 옳지 않은 것 같지만 Google에서 여러 게시물을 확인했으며 그 중 아무도 내게 어떻게 생각하고 올바르게 사용하는지 가르쳐 줄 수 없습니다. 감사합니다!

답변

1

질문의 첫 번째 부분은 다음과 같습니다. http://golang.org/doc/faq#different_method_sets을 참조하십시오. stackoverflow 및 golang-nuts 메일 링리스트에서이 질문을 검색 할 수도 있습니다. 자주 발생합니다.

두 번째 것은 단지 동일합니다. aaa에는 eat -method (*aaa 만 있음)이 없습니다.

7

질문 1 : 이동에

(귀하의 경우 AAA 등) 타입 T에 대해, T*T 다른 방법 세트를 가지고있다.

그래서, 형 T의 값을 할 수있는 전용 액세스 방법 :

func(t T)Foo() { ... } 

형 *의 T의 값이 두 방법 모두에 액세스 할 수 있지만 : 귀하의 경우

func(t T)Foo() { ... } 
func(t *T)Bar() { ... } 

을 두 가지 옵션이 있습니다 .어느 쪽이든 당신은 aaa에 대한 eat 방법 대신 *aaa 중독 선언

func (op aaa) eat() { 
    op() 
} 

을 또는 당신은 bfeelsGood에 대한 포인터를 전달합니다

feelsGood(&b) 

질문 2 : 예,이 질문은

한다 첫 번째와 관련이있다. 그러나이 경우 obj.eat()(&obj).eat()의 줄임말이기 때문에 메소드에 액세스 할 수 있습니다.

여기서 문제는 함수 포인터 (op * aaa)에서 함수를 호출 할 수 없다는 것입니다.

func (op aaa) eat() { 
    op() 
} 

또는이 op 값에 기능하지에게 포인터 전화 : 귀하의 옵션 aaa 대신 *aaa의하는 방법을 만드는 중입니다,

func (op *aaa) eat() { 
    (*op)() 
} 
+0

을하지만 난 단지 T 유형을 선언했습니다 , * T 타입이 존재하지 않는다면, 존재하지 않는 * T 타입이 어떻게 인터페이스를 구현할 수 있을까요? 그리고 더 이상, * T 타입이 존재하더라도, T와 * T의 차이점은 무엇입니까? 생각해 보니 * T는 T에 대한 포인터입니다. 포인터의 메서드 대 일반적인 메서드는 무엇을 의미합니까? 생각 해봐요! – user3505400

+0

T 기능을 사용해야 할 때와 T 기능을 사용해야하는 경우에 대한 다른 글을 읽었습니다. 수신자 자체를 수정하려면 * T를 사용해야합니다. 그렇지 않으면 T를 사용해야하지만,이 경우 T 또는 * T 방법이 사용되어야하는지 여부를 설명하기 위해 앞서 언급 한 고려 사항을 어떻게 사용합니까? – user3505400

+0

@ user3505400 :'T'는 선언 될 때'T'에 대한 포인터로 암시 적으로 선언되므로 존재합니다. 그리고 네, 차이점은 주로 수신기를 수정할 수 있는지 여부입니다. 그렇다면 왜 포인터가 인터페이스의 값으로 이동하지 않습니까? 왜냐하면 (afaIk) 함수에 값을 전달하면,'a : = struct {42}; Foo (a)'를 사용하면'a'가 변경되지 않는다는 것을 확신 할 수 있어야합니다. – ANisus

관련 문제