我學習去了寫GAE的應用程序,這是一個處理函數的簽名:在Go HTTP處理程序中,爲什麼ResponseWriter是一個值,但Request是一個指針?
func handle(w http.ResponseWriter, r *http.Request) {}
我在這裏很指針新手,那麼爲什麼是Request
對象的指針,但ResponseWriter
不?有沒有需要這樣做,或者這只是爲了使某種基於高級指針的代碼成爲可能?
我學習去了寫GAE的應用程序,這是一個處理函數的簽名:在Go HTTP處理程序中,爲什麼ResponseWriter是一個值,但Request是一個指針?
func handle(w http.ResponseWriter, r *http.Request) {}
我在這裏很指針新手,那麼爲什麼是Request
對象的指針,但ResponseWriter
不?有沒有需要這樣做,或者這只是爲了使某種基於高級指針的代碼成爲可能?
你得到的w
是一個指向非導出類型http.response
的指針,但是ResponseWriter
是一個接口,這是不可見的。
type ResponseWriter interface {
...
}
在另一方面,r
是指向一個具體的結構,因此需要精確它明確地:
type Request struct {
...
}
http.ResponseWriter
是一個接口,實現這個接口的現有類型是指針。這意味着不需要使用指向這個接口的指針,因爲它已經被指針「支持」了。這個概念是由開發人員逐一描述的here雖然實現http.ResponseWriter的類型不需要是一個指針,但它並不實際,至少不在go http服務器中。
http.Request
不是一個接口,它只是一個結構,因爲我們想改變這個結構並讓Web服務器看到這些變化,它必須是一個指針。如果它只是一個結構值,我們只需修改它的副本,即調用我們的代碼的Web服務器無法看到。
我認爲Request
對象作爲指針傳遞的主要原因是Body
字段。對於給定的HTTP請求,主體只能讀取一次。如果Request
對象被克隆,如果它不作爲指針傳遞,那麼我們將有兩個對象具有關於從正文中讀取多少信息的不同信息。
它是一個指向Request的指針很簡單:處理程序對Request的更改需要對服務器可見,所以我們只通過引用而不是按值傳遞它。
如果您深入研究net/http庫代碼,您會發現ResponseWriter是一個非入口結構響應的接口,並且我們通過引用傳遞了結構(我們傳遞了一個指向響應的指針)而不是價值。 ResponseWriter是處理程序用來創建HTTP響應的接口。支持ResponseWriter的實際結構是非導出的struct http.response。因爲它沒有出口,所以不能直接使用;您只能通過ResponseWriter界面使用它。
換句話說,兩個參數都通過引用傳入;只是方法簽名需要一個ResponseWriter,它是一個指向結構體的指針的接口,所以它看起來好像是按值傳遞的。
我不認爲這是正確的。指針後面的值可以實現與值相同的接口,因此這裏不需要區分。一個基類型爲int的類型可以滿足一個接口,而不是一個指針或一個接口。 – nemo
那麼,我並不是想暗示所有實現接口的東西都必須是指針。就像一個ResponseWriter,它需要修改接口後面的值的狀態來做任何有用的事情,並且需要這個值是一個指針類型(正如我鏈接到的博客文章中所說的那樣)。但是,是的,http.ResponseWriter理論上可以通過int實現(其方法永遠不會改變該int值)。 – nos