Uczę się Go, pisząc aplikację dla GAE, a to jest sygnatura funkcji obsługi:
func handle(w http.ResponseWriter, r *http.Request) {}
Jestem początkującym wskaźnikiem, więc dlaczego Request
obiekt jest wskaźnikiem, ale ResponseWriter
nie? Czy jest jakakolwiek potrzeba, aby to mieć w ten sposób, czy jest to tylko po to, aby umożliwić jakiś rodzaj zaawansowanego kodu opartego na wskaźnikach?
Jak słusznie wspomniano w wielu innych odpowiedziach tutaj i gdzie indziej,
ResponseWriter
interfejs, a jego konsekwencje zostały szczegółowo opisane w odpowiedziach SO i na blogach.Chciałabym odnieść się do tego, co uważam za duże - i niebezpieczne - błędne przekonanie, że powód żądania jest przekazywany przez „odniesienie” (chociaż coś takiego nie istnieje w Go ) jest takie, że „chcemy wprowadzić zmiany widoczne dla serwera ”.
Cytując kilka odpowiedzi:
To jest złe ; w rzeczywistości dokumenty wyraźnie ostrzegają przed manipulowaniem / modyfikowaniem żądania :
Wręcz przeciwnie, nie? :-)
Jeśli chcesz zmienić żądanie, np. Dołączyć nagłówek śledzenia przed przekazaniem go do następnego programu obsługi w łańcuchu oprogramowania pośredniego , musisz skopiować żądanie i przekazać skopiowaną wersję w dół łańcucha.
Żądania zmiany zachowania, aby umożliwić modyfikacje przychodzącego żądania , zostały zgłoszone przez zespół Go, ale zmiana czegoś takiego prawdopodobnie doprowadziłaby do nieoczekiwanego uszkodzenia przynajmniej części istniejącego kodu.
Po co używać wskaźnika, jeśli wyraźnie mówimy ludziom, aby nie modyfikowali żądania? Wydajność ,
Request
jest duża struktura i kopiowanie może przynieść wyniki w dół, zwłaszcza z długich łańcuchów middleware w umyśle. Zespół musiał znaleźć równowagę, zdecydowanie nie jest to idealne rozwiązanie, ale kompromisy są tutaj wyraźnie po stronie wydajności (zamiast bezpieczeństwa API).źródło
Powód, dla którego jest to wskaźnik do Request, jest prosty: zmiany w Request przez procedurę obsługi muszą być widoczne dla serwera, więc przekazujemy je tylko przez odwołanie, a nie przez wartość.
Jeśli zagłębisz się w kod biblioteki net / http, przekonasz się, że ResponseWriter jest interfejsem do niewyeksportowanej odpowiedzi struct i przekazujemy strukturę przez odwołanie (przekazujemy wskaźnik do odpowiedzi), a nie przez wartość . ResponseWriter to interfejs, którego program obsługi używa do tworzenia odpowiedzi HTTP. Rzeczywista struktura tworząca kopię zapasową ResponseWriter to niewyeksportowana struktura http.response. Ponieważ nie jest eksportowany, nie możesz go używać bezpośrednio; można go używać tylko za pośrednictwem interfejsu ResponseWriter.
Innymi słowy, oba parametry są przekazywane przez odniesienie; po prostu sygnatura metody przyjmuje ResponseWriter, która jest interfejsem do wskaźnika do struktury, więc wygląda na to, że jest przekazywana przez wartość.
źródło
Myślę, że głównym powodem przekazania
Request
obiektu jako wskaźnika jestBody
pole. Dla danego żądania HTTP treść możemy odczytać tylko raz. GdybyRequest
obiekt został sklonowany, tak jak by to było, gdyby nie został przekazany jako wskaźnik, mielibyśmy dwa obiekty z różnymi informacjami o tym, ile zostało odczytane z ciała.źródło