Я изучаю Go, написав приложение для GAE, и это подпись функции обработчика:
func handle(w http.ResponseWriter, r *http.Request) {}
Я новичок в указателе, так почему же Request
объект является указателем, а ResponseWriter
не указателем ? Есть ли необходимость в этом или это просто для того, чтобы сделать возможным какой-то усовершенствованный код, основанный на указателях?
Как правильно упоминалось во многих других ответах здесь и в других местах,
ResponseWriter
это интерфейс, и последствия этого подробно описаны в SO ответах и блогах.Я хотел бы затронуть то, что я считаю большим - и опасным - заблуждением о том, что причина, по которой запрос передается по «ссылке» (хотя на самом деле такой вещи нет в Go ), заключается в том, что «мы хотим внести изменения ему видно серверу ".
Процитирую пару ответов:
Это неправильно ; на самом деле документы явно предостерегают от подделки / изменения запроса :
Совсем наоборот, не так ли? :-)
Если вы хотите изменить запрос, например, добавить заголовок трассировки, прежде чем передать его следующему обработчику в цепочке промежуточного программного обеспечения, вам необходимо скопировать запрос и передать скопированную версию вниз по цепочке.
Запросы на изменение поведения, позволяющие вносить изменения во входящий запрос , были отправлены командой Go, но изменение чего-то вроде этого, вероятно, приведет к неожиданному нарушению по крайней мере некоторого существующего кода.
Зачем использовать указатель, если мы явно говорим людям не изменять запрос? Производительность ,
Request
большая структура и копирование может принести производительность вниз, особенно с длинными цепями промежуточного программного обеспечения в виду. Команде пришлось найти баланс, определенно не идеальное решение, но компромиссы здесь явно на стороне производительности (вместо безопасности API).источник
Причина, по которой это указатель на запрос, проста: изменения в запросе обработчиком должны быть видны серверу, поэтому мы передаем его только по ссылке, а не по значению.
Если вы покопаетесь в коде библиотеки net / http, вы обнаружите, что ResponseWriter - это интерфейс для неэкспортированного ответа структуры, и мы передаем структуру по ссылке (мы передаем указатель на ответ), а не по значению . ResponseWriter - это интерфейс, который обработчик использует для создания HTTP-ответа. Фактическая структура, поддерживающая ResponseWriter, - это неэкспортированная структура http.response. Поскольку он не экспортируется, вы не можете использовать его напрямую; вы можете использовать его только через интерфейс ResponseWriter.
Другими словами, оба параметра передаются по ссылке; просто сигнатура метода принимает ResponseWriter, который является интерфейсом для указателя на структуру, поэтому он выглядит так, как будто он передается по значению.
источник
Я думаю, что основная причина
Request
передачи объекта в качестве указателя - этоBody
поле. Для данного HTTP-запроса тело может быть прочитано только один раз. Если быRequest
объект был клонирован, как если бы он не был передан как указатель, у нас были бы два объекта с разной информацией о том, сколько было прочитано из тела.источник