Go中http.Response接收函数的语义方式
Semantic way of http.Response receiver functions in Go
我刚开始学习 GO 并编写了这段代码,将 http.Response.Body
写入 os.Stdout
或文件,但我对此的语义不满意。
我希望 http.Response
结构具有这些接收函数,这样我就可以在整个应用程序中更轻松地使用它。
我知道答案可能会被标记为自以为是,但我仍然想知道,是否有更好的写法?
是否有某种最佳实践?
package main
import (
"fmt"
"io"
"io/ioutil"
"net/http"
"os"
)
type httpResp http.Response
func main() {
res, err := http.Get("http://www.whosebug.com")
if err != nil {
fmt.Println("Error: ", err)
os.Exit(1)
}
defer res.Body.Close()
response := httpResp(*res)
response.toFile("stckovrflw.html")
response.toStdOut()
}
func (r httpResp) toFile(filename string) {
str, err := ioutil.ReadAll(r.Body)
if err != nil {
panic(err)
}
ioutil.WriteFile(filename, []byte(str), 0666)
}
func (r httpResp) toStdOut() {
_, err := io.Copy(os.Stdout, r.Body)
if err != nil {
panic(err)
}
}
附带说明一下,有没有办法让 http.Get
方法吐出一个自定义类型,该类型已经可以访问这些接收器函数而无需强制转换?所以我可以这样做:
func main() {
res, err := http.Get("http://www.whosebug.com")
if err != nil {
fmt.Println("Error: ", err)
os.Exit(1)
}
defer res.Body.Close()
res.toFile("stckovrflw.html")
res.toStdOut()
}
谢谢!
您不必实现这些功能。 *http.Response
已经 implements io.Writer
:
Write writes r to w in the HTTP/1.x server response format, including the status line, headers, body, and optional trailer.
package main
import (
"net/http"
"os"
)
func main() {
r := &http.Response{}
r.Write(os.Stdout)
}
在上面的例子中,零值打印:
HTTP/0.0 000 status code 0
Content-Length: 0
游乐场:https://play.golang.org/p/2AUEAUPCA8j
如果您需要在写入方法中添加额外的业务逻辑,您可以在您定义的类型中嵌入 *http.Response
:
type RespWrapper struct {
*http.Response
}
func (w *RespWrapper) toStdOut() {
_, err := io.Copy(os.Stdout, w.Body)
if err != nil {
panic(err)
}
}
但是你必须用 *http.Response
:
构造一个 RespWrapper
类型的变量
func main() {
// resp with a fake body
r := &http.Response{Body: io.NopCloser(strings.NewReader("foo"))}
// or r, _ := http.Get("example.com")
// construct the wrapper
wrapper := &RespWrapper{Response: r}
wrapper.toStdOut()
}
is there a way to make the http.Get method spit out a custom type
不,http.Get
的return类型是(resp *http.Response, err error)
,那是函数签名的一部分,你不能改变它。
我刚开始学习 GO 并编写了这段代码,将 http.Response.Body
写入 os.Stdout
或文件,但我对此的语义不满意。
我希望 http.Response
结构具有这些接收函数,这样我就可以在整个应用程序中更轻松地使用它。
我知道答案可能会被标记为自以为是,但我仍然想知道,是否有更好的写法? 是否有某种最佳实践?
package main
import (
"fmt"
"io"
"io/ioutil"
"net/http"
"os"
)
type httpResp http.Response
func main() {
res, err := http.Get("http://www.whosebug.com")
if err != nil {
fmt.Println("Error: ", err)
os.Exit(1)
}
defer res.Body.Close()
response := httpResp(*res)
response.toFile("stckovrflw.html")
response.toStdOut()
}
func (r httpResp) toFile(filename string) {
str, err := ioutil.ReadAll(r.Body)
if err != nil {
panic(err)
}
ioutil.WriteFile(filename, []byte(str), 0666)
}
func (r httpResp) toStdOut() {
_, err := io.Copy(os.Stdout, r.Body)
if err != nil {
panic(err)
}
}
附带说明一下,有没有办法让 http.Get
方法吐出一个自定义类型,该类型已经可以访问这些接收器函数而无需强制转换?所以我可以这样做:
func main() {
res, err := http.Get("http://www.whosebug.com")
if err != nil {
fmt.Println("Error: ", err)
os.Exit(1)
}
defer res.Body.Close()
res.toFile("stckovrflw.html")
res.toStdOut()
}
谢谢!
您不必实现这些功能。 *http.Response
已经 implements io.Writer
:
Write writes r to w in the HTTP/1.x server response format, including the status line, headers, body, and optional trailer.
package main
import (
"net/http"
"os"
)
func main() {
r := &http.Response{}
r.Write(os.Stdout)
}
在上面的例子中,零值打印:
HTTP/0.0 000 status code 0
Content-Length: 0
游乐场:https://play.golang.org/p/2AUEAUPCA8j
如果您需要在写入方法中添加额外的业务逻辑,您可以在您定义的类型中嵌入 *http.Response
:
type RespWrapper struct {
*http.Response
}
func (w *RespWrapper) toStdOut() {
_, err := io.Copy(os.Stdout, w.Body)
if err != nil {
panic(err)
}
}
但是你必须用 *http.Response
:
RespWrapper
类型的变量
func main() {
// resp with a fake body
r := &http.Response{Body: io.NopCloser(strings.NewReader("foo"))}
// or r, _ := http.Get("example.com")
// construct the wrapper
wrapper := &RespWrapper{Response: r}
wrapper.toStdOut()
}
is there a way to make the http.Get method spit out a custom type
不,http.Get
的return类型是(resp *http.Response, err error)
,那是函数签名的一部分,你不能改变它。