왜 * Struct를 * Interface에 할당 할 수 없습니까?


142

나는 Go tour를 통해 일하고 있으며 포인터와 인터페이스에 대해 혼란스러워합니다. 이 Go 코드는 왜 컴파일되지 않습니까?

package main

type Interface interface {}

type Struct struct {}

func main() {
    var ps *Struct
    var pi *Interface
    pi = ps

    _, _ = pi, ps
}

즉,이 경우 StructInterface, 이유는 않을 것 *Struct*Interface?

내가 얻는 오류 메시지는 다음과 같습니다.

prog.go:10: cannot use ps (type *Struct) as type *Interface in assignment:
        *Interface is pointer to interface, not interface


인터페이스가 암시 적 포인터처럼 동작 할 수있는 것처럼 보입니다 ...
Victor

나는 당신의 놀이터를 풍요롭게 func main() { var ps *Struct = new(Struct) var pi *Interface var i Interface i = ps pi = &i fmt.Printf("%v, %v, %v\n", *ps, pi, &i) i = *ps fmt.Printf("%v, %v, %v\n", *ps, pi, i) _, _, _ = i, pi, ps }하고 자신의 결론을 내릴 것을 제안 할 수 있습니다.
Victor

답변:


183

인터페이스를 구현하는 구조체가 있으면 해당 구조체에 대한 포인터가 해당 인터페이스도 자동으로 구현합니다. 그렇기 때문에 *SomeInterface함수 프로토 타입에 절대로 아무것도 추가 SomeInterface되지 않으므로 변수 선언에 이러한 유형이 필요하지 않습니다 ( 이 관련 질문 참조 ).

인터페이스 값은 콘크리트 구조체의 값이 아니며 (크기가 가변적이므로 불가능할 수 있음) 일종의 포인터입니다 (구조체에 대한 포인터 및 유형에 대한 포인터) ). Russ Cox는 정확히 여기에 설명합니다 .

인터페이스 값은 인터페이스에 저장된 유형에 대한 정보를 가리키는 포인터와 관련 데이터를 가리키는 2 워드 쌍으로 표시됩니다.

여기에 이미지 설명을 입력하십시오

그렇기 때문에 구조체 구현에 대한 포인터를 보유하는 올바른 유형이 Interface아닙니다 .*InterfaceInterface

그래서 당신은 단순히 사용해야합니다

var pi Interface

8
알았어요. 나는 왜 (이 경우) 단순히 컴파일 시간 오류가 아닌지 궁금 var pi *Interface합니다.
Simon Nickerson

1
나는 그것을 설명하기 위해 더 자세한 내용을 보았습니다. 편집을 참조하십시오. 필자가 링크 한 Russ Cox의 기사를 읽는 것이 좋습니다.
Denys Séguret

1
이것은 단지 나 방법으로 포인터의 느낌이 나는 없었다 만들어 주었다 결코 :-)이 우아하고 간단한 설명을 너무 많이 주셔서 감사합니다 ... C 또는 C ++에서 할 수
mindplay.dk

2
그래도 여전히 *SomeInterface컴파일 오류가 아닌 이유 를 얻지 못합니까?
sazary

2
@charneykaye 여기가 완전히 정확하지는 않습니다. 인터페이스 변수를 선언 하거나 함수 선언의 일부로 인터페이스 유형을 리턴 할 때 * SomeInterface 없습니다 . 그러나 함수의 매개 변수 내에 * SomeInterface를 가질 수 있습니다 .
arauter

7

이것은 아마도 당신이 의미 한 것입니다 :

package main

type Interface interface{}

type Struct struct{}

func main() {
        var ps *Struct
        var pi *Interface
        pi = new(Interface)
        *pi = ps

        _, _ = pi, ps
}

컴파일합니다. 여기도 참조 하십시오 .


이것은 받아 들여 져야하고, 다른 것은 실제로 질문에 대답하지 않습니다.
DrKey

0

인터페이스에 구조체를 할당하는 매우 간단한 방법은 다음과 같습니다.

package main

type Interface interface{}

type Struct struct{}

func main() {
    ps := new(Struct)
    pi := Interface(ps)

    _, _ = pi, ps
}

https://play.golang.org/p/BRTaTA5AG0S


0

나는 인수로 interface{}소비하는 동안 다음과 같은 방법을 사용 하지만 eventsI interface{}아래에서 볼 수 있듯이 여전히 구조 포인터를 보낼 수 있습니다.

func Wait(seconds float64) *WaitEvent {
    return WaitEventCreate(seconds)
}

main.go

var introScene = []interface{}{
        storyboard.Wait(5),
        storyboard.Wait(2),
    }

    var storyboardI = storyboard.Create(stack, introScene)
    stack.Push(&storyboardI)

이제 storyboard.go파일 내부 작성 기능

type Storyboard struct {
    Stack  *gui.StateStack
    Events []interface{} //always keep as last args
}

func Create(stack *gui.StateStack, eventsI interface{}) Storyboard {
    sb := Storyboard{
        Stack: stack,
    }

    if eventsI != nil {
        events := reflect.ValueOf(eventsI)
        if events.Len() > 0 {
            sb.Events = make([]interface{}, events.Len())
            for i := 0; i < events.Len(); i++ {
                sb.Events[i] = events.Index(i).Interface()
            }
        }
    }

    return sb
}

위에서 볼 수 있듯이 Storyboard.go는 소비하고 Events []interface{}있지만 실제로 Im 전송은 Struct 포인터이며 제대로 작동합니다.

여기 또 다른 예

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.