Передача указателя интерфейса в параметре функции - PullRequest
0 голосов
/ 09 октября 2019

Я пытаюсь понять интерфейсы Golang (1.12). Я обнаружил, что указатели на интерфейсы должны быть явно разыменованы, в отличие от структур:

import "fmt"

// A simple interface with one function
type myinter interface {
    hello()
}

// Implement myinter
type mystruct struct {}

func (mystruct) hello() {
    fmt.Println("I am T!")
}

// Some function that calls the hello function as defined by myinter
func callHello(i *myinter) {   
    i.hello()  // <- cannot resolve reference 'hello'
}

func main() {
    newMystruct := &mystruct{}
    callHello(newMystruct)
}

Здесь моя функция callHello не может разрешить ссылку на мою функцию hello, как определено в интерфейсе. Конечно, разыменование интерфейса работает:

func callHello(i *myinter) {   
    (*i).hello()  // <- works!
}

Но в структурах мы можем вызвать функцию напрямую, Нет необходимости в этой громоздкой записи разыменования :

func callHello(s *mystruct) {   
    s.hello()  // <- also works!
}

Почему это так? Есть ли причина, по которой мы должны явно разыменовывать указатели interface? Go пытается отговорить меня от передачи interface указателей в функции?

Ответы [ 2 ]

1 голос
/ 09 октября 2019

Это связано с тем, как работает система типов. Тип интерфейса I определяет набор методов. Набор методов определен для типа I, а не для типа *I. Из-за этого использование *I ограничено. Его можно использовать, когда функция устанавливает значение интерфейса, но это редко:

func f(x *error) {
  *x = fmt.Errorf("Some error")
}

Обратите внимание, что сам интерфейс может иметь базовое значение указателя:

func f(x someInterface) {
   *x.(*someType) = value
}

func main() {
   x := someType{}
   f(&x)
}

Этоотличается для неинтерфейсных типов. Когда вы определяете метод для неинтерфейсного типа T, метод определяется для T и *T. Если вы определяете метод для *T, он определяется только для *T, а не для T.

0 голосов
/ 10 октября 2019

Go пытается отговорить меня от передачи указателей интерфейса в функции?

Да.

Указатель на интерфейс os Неправильно в(почти *) во всех случаях.

(* В очень редких и деликатных случаях указатель на интерфейс имеет смысл, но велики шансы, что вы не увидите их чаще, чем раз в 5 лет.)

(Nitpick: язык называется «Go». «Golang.org» - это веб-сайт. Подобные основы охватываются обещанием совместимости и не зависят от версии: Go 1.0, 1.12 и 1.16 ведут себя точното же самое в этом отношении.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...