英文:
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
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论