不了解 Go 中的组合

Don't understand composition in Go

在下面的示例中,我将 http.ResponseWriter 嵌入到我自己的名为 Response 的结构中。我还添加了一个名为 Status 的额外字段。为什么我不能从我的 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) // <--- This causes an error.
}

func main() {
    http.Handle("/", middleware(http.HandlerFunc(root)))
    http.ListenAndServe(":8000", nil)
}

whttp.ResponseWriter 类型的变量。 ResponseWriter 没有字段或方法 Status,只有您的 Response 类型。

http.ResponseWriter 是一种接口类型,并且由于您的 Response 类型实现了它(因为它嵌入了 ResponseWriter),因此 w 变量可能包含动态值输入 Response (在你的情况下它确实如此)。

但是要访问 Response.Status 字段,您必须将其转换为 Response 类型的值。为此使用 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
}