英文:
Don't understand composition in Go
问题
在下面的示例中,我将http.ResponseWriter嵌入到了自己的结构体Response中。我还添加了一个额外的字段Status。为什么我不能从我的root处理函数内部访问该字段呢?
当我在root处理函数中打印出w的类型时,它显示为main.Response,这似乎是正确的。当我打印出结构体的值时,我可以看到Status字段存在。为什么我不能通过w.Status来访问它呢?
这是标准输出的内容:
main.Response
{ResponseWriter:0xc2080440a0 Status:0}
代码:
package main
import (
"fmt"
"reflect"
"net/http"
)
type Response struct {
http.ResponseWriter
Status int
}
func (r Response) WriteHeader(n int) {
r.Status = n
r.ResponseWriter.WriteHeader(n)
}
func middleware(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
resp := Response{ResponseWriter: w}
h.ServeHTTP(resp, r)
})
}
func root(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("root"))
fmt.Println(reflect.TypeOf(w))
fmt.Printf("%+v\n", w)
fmt.Println(w.Status) // <--- 这会导致错误。
}
func main() {
http.Handle("/", middleware(http.HandlerFunc(root)))
http.ListenAndServe(":8000", nil)
}
英文:
In the example below I've embedded http.ResponseWriter into my own struct called Response. I've also added an extra field called Status. Why can't I access that field from inside my root handler function?
When I print out the type of w in my root handler function it says it's of type main.Response which seems correct and when I print out the values of the struct I can see that Status is there. Why can't I access by going w.Status?
This is the contents of stdout:
main.Response
{ResponseWriter:0xc2080440a0 Status:0}
Code:
package main
import (
"fmt"
"reflect"
"net/http"
)
type Response struct {
http.ResponseWriter
Status int
}
func (r Response) WriteHeader(n int) {
r.Status = n
r.ResponseWriter.WriteHeader(n)
}
func middleware(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
resp := Response{ResponseWriter: w}
h.ServeHTTP(resp, r)
})
}
func root(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("root"))
fmt.Println(reflect.TypeOf(w))
fmt.Printf("%+v\n", w)
fmt.Println(w.Status) // <--- This causes an error.
}
func main() {
http.Handle("/", middleware(http.HandlerFunc(root)))
http.ListenAndServe(":8000", nil)
}
答案1
得分: 3
w是一个类型为http.ResponseWriter的变量。ResponseWriter没有Status字段或方法,只有你的Response类型有。
http.ResponseWriter是一个接口类型,由于你的Response类型实现了它(因为它嵌入了ResponseWriter),所以w变量可以保存一个动态类型为Response的值(在你的情况下是这样)。
但是要访问Response.Status字段,你需要将其转换为Response类型的值。可以使用类型断言来实现:
if resp, ok := w.(Response); ok {
// resp的类型是Response,你可以访问它的Status字段
fmt.Println(resp.Status) // <--- 正确打印状态
}
英文:
w is a variable of type http.ResponseWriter. ResponseWriter does not have a field or method Status, only your Response type.
http.ResponseWriter is an interface type, and since your Response type implements it (because it embeds ResponseWriter), the w variable may hold a value of dynamic type Response (and in your case it does).
But to access the Response.Status field, you have to convert it to a value of type Response. For that use Type assertion:
if resp, ok := w.(Response); ok {
// resp is of type Response, you can access its Status field
fmt.Println(resp.Status) // <--- properly prints status
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论