Dlaczego nie mogę przypisać struktury *do interfejsu*?

Właśnie pracuję nad Go tour i jestem zdezorientowany co do wskaźników i interfejsów. Dlaczego ten kod nie jest kompilowany?

package main

type Interface interface {}

type Struct struct {}

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

    _, _ = pi, ps
}

Czyli jeśli Struct jest Interface, Dlaczego *Struct nie jest *Interface?

Otrzymywany komunikat o błędzie to:

prog.go:10: cannot use ps (type *Struct) as type *Interface in assignment:
        *Interface is pointer to interface, not interface
 143
go
Author: Simon Nickerson, 2012-11-22

4 answers

Gdy masz strukturę implementującą interfejs, wskaźnik do tej struktury implementuje również automatycznie ten interfejs. Dlatego nigdy nie masz *SomeInterface w prototypie funkcji, ponieważ nie dodałoby to nic do SomeInterface i nie potrzebujesz takiego typu w deklaracji zmiennej(zobacz to powiązane pytanie ).

Wartość interfejsu nie jest wartością konkretnej struktury (ponieważ ma zmienną wielkość, nie byłoby to możliwe), ale jest rodzajem wskaźnika (dokładniej wskaźnik do struktury i wskaźnik do typu). Russ Cox opisuje to dokładnie tutaj :

Wartości interfejsu są reprezentowane jako para dwóch słów dająca wskaźnik do informacji o typie przechowywanym w interfejsie oraz wskaźnik do powiązane dane.

Tutaj wpisz opis obrazka

Dlatego Interface, a nie *Interface jest właściwym typem do przechowywania wskaźnika do struktury implementującej Interface.

Więc musisz po prostu użyć

var pi Interface
 191
Author: Denys Séguret,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 10:31:37

To chyba miałeś na myśli:

package main

type Interface interface{}

type Struct struct{}

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

        _, _ = pi, ps
}

Kompiluje OK. Zobacz też tutaj .

 8
Author: zzzz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-22 11:20:04

Oto bardzo prosty sposób przypisania struktury do interfejsu:

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
Author: Miguel Mota,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-12-27 23:42:05

Im używa następującego sposobu interface{} podczas gdy im tylko zużywa eventsI interface{} jako argumenty, im nadal w stanie wysłać wskaźnik struktury, jak widać poniżej.

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)

Teraz wewnątrz storyboard.go Funkcja tworzenia pliku

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
}

Jak widać powyżej Storyboard.go zużywa tylko Events []interface{}, ale w rzeczywistości Im sending jest wskaźnikiem struktury i działa dobrze.

Kolejny przykład tutaj

 0
Author: STEEL,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-01-11 10:38:59