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