英文:
Golang RedirectHandler() returns interface, ends up with *http.redirectHandler
问题
请不要对我的帖子进行攻击,我正在尝试学习Go语言,但在理解上遇到了一些挑战。
这是我的示例代码:
package main
import (
"log"
"net/http"
"reflect"
"fmt"
)
func main() {
mux := http.NewServeMux()
rh := http.RedirectHandler("http://example.org", 307)
fmt.Println("RedirectHandler返回的对象的类型是:")
fmt.Println(reflect.TypeOf(rh))
fmt.Println("类型观察结束")
mux.Handle("/foo", rh)
log.Println("监听中...")
http.ListenAndServe(":3000", mux)
}
我的问题是:
RedirectHandler
返回一个Handler
接口,这是一种常见的模式,有什么好处?- 这是否意味着在函数内部应该有一个实现该接口的结构体,然后返回该结构体?如果不是这样,那么我们如何返回一个接口,因为本质上它只是一组未实现的方法?
- 如果你运行我的代码,你会发现变量
rh
的类型是*http.redirectHandler
。对于这样一个指针,我在http
包中找不到任何信息,所以我们从“返回一个接口”开始,最终得到的是“这是你的指针,在文档中不存在”。 - 这些只是我困惑的想法,我希望能得到帮助解决困惑的评论。
英文:
Please do not be aggressive with my post, I am trying to learn Go, but facing some challenges in my understanding.
This is my sample code:
package main
import (
"log"
"net/http"
"reflect"
"fmt"
)
func main() {
mux := http.NewServeMux()
rh := http.RedirectHandler("http://example.org", 307)
fmt.Println("The type of the object, returned by the RedirectHandler is")
fmt.Println(reflect.TypeOf(rh))
fmt.Println("End with type observation")
mux.Handle("/foo", rh)
log.Println("Listening ...")
http.ListenAndServe(":3000", mux)
}
My questions are:
- RedirectHandler returns a Handler interface, is this a common pattern and what is the benefit ?
- Does that mean that the inside the function you schould have a struct that implements that interface and then return the struct ? If not, how in the world do we return an interface, as essentially it's just a set of non-implemented methods ?
- If you run my code, you would see that the type of the variable 'rh' is *http.redirectHandler. For such a pointer I am not able to find anything in the http package, so we started from 'returns an interface' to end up with 'here's your pointer, that does not exists in the doc'.
- Those are just my confusing thoughts, I would appreciate comments who want to help me with my confusion.
答案1
得分: 1
> 1. RedirectHandler返回一个Handler接口,这是一种常见的模式吗?有什么好处?
虽然有一个经验法则是返回具体类型而不是接口(通常被称为“接受接口返回结构体”),但有时隐藏实现是可取的,出于各种原因。其中之一是为了在将来的包版本中自由地更改实现方式。另一个原因是防止误用返回值,例如并发访问结构体字段。
使所有这些函数(RedirectHandler、NotFoundHandler、TimeoutHandler等)返回http.Handler也使它们在文档中易于发现:它们都作为http.Handler的构造函数一起出现,而不是分散在函数列表中。我假设这可能在决定采用这种方式时起到了一定的作用,但你需要问问作者(你可以在邮件列表上提问)。
> 2. 这是否意味着[RedirectHandler返回]一个实现该接口的结构体?
可能。它也可以返回任何其他实现该接口的类型,尽管在Go 1.15中确实是一个结构体类型。但这可能会改变,因为该函数返回的是接口而不是具体类型。
> 3. 如果你运行我的代码,你会发现变量'rh'的类型是*http.redirectHandler。对于这样的指针,我在http包中找不到任何内容。
默认情况下,未导出的标识符的文档不会被渲染(因为你无法使用它们)。在查询字符串中添加m=all
以显示它们:https://golang.org/pkg/net/http/?m=all#redirectHandler
英文:
> 1. RedirectHandler returns a Handler interface, is this a common pattern and what is the benefit?
While there is a rule of thumb to return concrete types instead of interfaces (often stated as "Accept interfaces return structs"), it is sometimes desirable to hide the implementation, for any number of reasons. One of them is to be free to change the implementation in any way in future versions of a package. Another is to prevent misuse of the return value; accessing struct fields concurrently, for instance.
Making all these functions (RedirectHandler, NotFoundHandler, TimeoutHandler, etc.) return http.Handler also makes them easily discoverable in the docs: they all appear together as constructors for http.Handler instead of scattered around in the list of functions. I'm assuming (!) that may have played a role when deciding to do it this way, but you'd have to ask the authors (you can do this on the mailing list).
> 2. Does that mean that [RedirectHandler returns] a struct that implements that interface?
Maybe. It can also return any other type that implements the interface, although it is indeed a struct type in Go 1.15. But that can change, precisely because the function returns an interface instead of a concrete type.
> 3. If you run my code, you would see that the type of the variable 'rh' is *http.redirectHandler. For such a pointer I am not able to find anything in the http package.
The docs for unexported identifiers are not rendered by default (because you can't use them anyway). Add m=all
to the query string to show them: https://golang.org/pkg/net/http/?m=all#redirectHandler
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论