Голанг адрес интерфейса и интерфейс разница - PullRequest
0 голосов
/ 28 августа 2018

Я нашел много подобных проблем, но не то, что я хочу пожалуйста, смотрите следующие коды.

(1)

var buf bytes.Buffer
fmt.Fprint(&buf,"test")

(2)

var w http.ResponseWriter
http.Error(w,http.StatusText(http.StatusBadRequest),http.StatusBadRequest)

и http.ResponseWriter, и bytes.Buffer реализуют интерфейс io.Writer, поэтому я думаю, что они должны иметь одинаковое поведение.

когда я перехожу на

http.Error(&w,http.StatusText(http.StatusBadRequest),http.StatusBadRequest)

реактивный мозг Голанд скажи мне

Cannot use '&w' (type *http.ResponseWriter) as type ResponseWriter

Интересно, почему buf может '&' может работать, а другой не работает?

Я погуглил, кто-то скажет, когда передают значение в функцию, оно может ссылаться на &w

но другое слово, если вы передадите указатель, он может использовать значение

от https://github.com/golang/go/wiki/MethodSets#variables

Чтобы упростить запоминание этих правил, может быть полезно просто рассмотреть методы указателя и получателя значения отдельно от набора методов. Разрешается вызывать метод со значением указателя для всего, что уже является указателем или чей адрес может быть взят (как в случае с приведенным выше примером). Допустимо вызывать метод-значение для всего, что является значением или чье значение может быть разыменовано (как в случае с любым указателем; этот случай явно указан в спецификации).

Я полностью сбит с толку, я не могу понять сам. Я бы хотел, чтобы вы мне помогли, спасибо!

1 Ответ

0 голосов
/ 29 августа 2018

Может быть, я могу попытаться объяснить более подробно, что все очень хорошие комментарии уже говорят:

Интерфейсы - это (в основном) указатели на ходу

Интерфейсы в go реализованы (удовлетворены), если другой тип реализует все методы, которые определяет интерфейс. Обычно это делается путем добавления методов к указателю типа, , а не типа напрямую.

type SomeInterface interface {
    SomeMethod string
}

type SomeStruct struct {} // often is a struct but does not have to be

// a method on the structs pointer
func (s *SomeStruct) SomeMethod string {
    return ""
}

Результаты этого:

  1. SomeStruct НЕ реализует SomeInterface, *SomeStruct делает!
  2. Интерфейс (обычно) уже является указателем.

Ваш пример

var b bytes.Buffer
fmt.Fprintf(&b, "some text")

var w http.ResponseWriter
http.Error(w, "some error", 1)

Переменная b типа bytes.Buffer является struct, как вы можете видеть из исходного кода:

type Buffer struct {
    buf       []byte   // contents are the bytes buf[off : len(buf)]
    off       int      // read at &buf[off], write at &buf[len(buf)]
    bootstrap [64]byte // memory to hold first slice; helps small buffers avoid allocation.
    lastRead  readOp   // last read operation, so that Unread* can work correctly.

    // FIXME: it would be advisable to align Buffer to cachelines to avoid false
    // sharing.
}

Если вы хотите использовать его как тип io.Writer (интерфейс), вам нужно получить указатель bytes.Buffer, поскольку (обычно) методы указателя используются в go: fmt.Fprintf(&b, "some text")

Переменная w типа http.ResponseWriter является interface:

type ResponseWriter interface {
    Header() Header
    Write([]byte) (int, error)
    WriteHeader(statusCode int)
}

Поскольку интерфейсы (обычно) уже являются указателями на некоторую базовую реализацию, мы можем использовать их без указания указателя: http.Error(w, "some error", 1).

Инициализация интерфейса

Сам интерфейс не может быть инициализирован и использован! Для реализации интерфейса вам всегда требуется структура или другой тип, а затем вы можете инициализировать его и использовать его как тип SomeInterface. Например, - это реализация gin для http.ResponseWriter. Как вы можете видеть из кода, он использует приемники указателей для своих методов. Так что http.ResponseWriter уже является указателем на структуру.

Отказ от ответственности

Это всего лишь один из способов сделать эту сложную тему простой (надеюсь). Это не технически полное или совершенно точное объяснение. Пытаться оставаться простым и в то же время максимально точным.

...