Don't understand composition in Go

huangapple go评论73阅读模式
英文:

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 (
	&quot;fmt&quot;
	&quot;reflect&quot;

	&quot;net/http&quot;
)

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(&quot;root&quot;))
	fmt.Println(reflect.TypeOf(w))
	fmt.Printf(&quot;%+v\n&quot;, w)
    fmt.Println(w.Status) // &lt;--- This causes an error.
}

func main() {
	http.Handle(&quot;/&quot;, middleware(http.HandlerFunc(root)))
	http.ListenAndServe(&quot;:8000&quot;, 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) // &lt;--- properly prints status
}

huangapple
  • 本文由 发表于 2015年5月15日 15:12:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/30253621.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定