Я просто прорабатываю тур по Go и не понимаю, как насчет указателей и интерфейсов. Почему этот код Go не компилируется?
package main
type Interface interface {}
type Struct struct {}
func main() {
var ps *Struct
var pi *Interface
pi = ps
_, _ = pi, ps
}
т.е. если Struct
есть Interface
, почему бы не *Struct
быть *Interface
?
Я получаю следующее сообщение об ошибке:
prog.go:10: cannot use ps (type *Struct) as type *Interface in assignment:
*Interface is pointer to interface, not interface
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 }
и сделать собственные выводыОтветы:
Когда у вас есть структура, реализующая интерфейс, указатель на эту структуру также автоматически реализует этот интерфейс. Вот почему у вас никогда не было
*SomeInterface
в прототипе функций, так как это ничего бы не добавилоSomeInterface
, и вам не нужен такой тип в объявлении переменной (см. Этот связанный вопрос ).Значение интерфейса - это не значение конкретной структуры (поскольку у него переменный размер, это было бы невозможно), а своего рода указатель (точнее, указатель на структуру и указатель на тип ). Расс Кокс описывает это именно здесь :
Вот почему
Interface
, а не*Interface
правильный тип для хранения указателя на реализацию структурыInterface
.Поэтому вы должны просто использовать
var pi Interface
источник
var pi *Interface
.*SomeInterface
это не просто ошибка компиляции?Возможно, вы имели в виду:
package main type Interface interface{} type Struct struct{} func main() { var ps *Struct var pi *Interface pi = new(Interface) *pi = ps _, _ = pi, ps }
Компилируется нормально. Смотрите также здесь .
источник
Вот очень простой способ назначить структуру интерфейсу:
package main type Interface interface{} type Struct struct{} func main() { ps := new(Struct) pi := Interface(ps) _, _ = pi, ps }
https://play.golang.org/p/BRTaTA5AG0S
источник
Я использую следующий способ,
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
файла Create функция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{}
но на самом деле я отправляю указатель Struct, и он отлично работает.еще один пример здесь
источник