将接口传递给方法的正确方法
Correct way to pass interfaces to methods
偏好:我是 Golang 的新手并且渴望改进。
所以我正在尝试从 Dave Cheney 的演讲中学习:https://youtu.be/NwEuRO_w8HE?t=812 我们将接口传递给方法以使代码更清晰、更通用。
我在下面实现了一个示例,其中我有一个可以输出到 std.out 或文件的结构。但是,我觉得只制作空结构(在我的示例中称为“打印”和“保存”)有点多余,这样我就可以附加方法。我该如何改进?
package main
import (
"fmt"
"io"
"io/ioutil"
"log"
)
type file struct {
data string
}
func (f *file) output(w io.Writer) error {
len, err := w.Write([]byte(f.data))
if err != nil {
return err
} else {
log.Println("Bytes Out: ", len)
return nil
}
}
type print struct{}
func (print *print) Write(p []byte) (n int, err error) {
return fmt.Printf("%s\n", p)
}
type save struct{}
func (s *save) Write(p []byte) (n int, err error) {
err = ioutil.WriteFile("./dat1", []byte(p), 0644)
if err != nil {
return -1, err
}
return len(p), nil
}
func main() {
f := file{"test"}
s := save{}
p := print{}
f.output(&s)
f.output(&p)
}
您的意图不明确,但回答您最初的问题:如何将函数作为接口值传递?
您可以创建一个类似适配器的类型来实现 io.Writer
,并且当它的 Write()
方法被调用时,它会转发给您选择的函数。一个典型的例子是 http.HandlerFunc
: it's a function type that implements http.Handler
,因此当需要 http.Handler
实现时可以传递一个函数。
对于 io.Writer
适配器,它可能如下所示:
type WriteFunc func(p []byte) (n int, err error)
func (w WriteFunc) Write(p []byte) (n int, err error) {
return w(p)
}
如果你有这样的功能:
func PrintWrite(p []byte) (n int, err error) {
return fmt.Printf("%s\n", p)
}
func SaveWrite(p []byte) (n int, err error) {
err = ioutil.WriteFile("./dat1", []byte(p), 0644)
if err != nil {
return -1, err
}
return len(p), nil
}
您可以像这样 io.Writer
使用它们:
f.output(WriteFunc(PrintWrite))
f.output(WriteFunc(SaveWrite))
在 Go Playground 上试用。
此处不需要 print
或 save
类型。你有一个方法,output
,需要一个 io.Writer
;关键在于您可以 任何作者 传递它。 stdout 和 files 都是写入器,所以这里的其他一切都是不必要的。你可以:
func main() {
f := file{"test"}
fp,err := os.Create("./dat1")
if err != nil {
panic(err)
}
f.output(fp) // This writes to a file
f.output(os.Stdout) // This writes to stdout
}
偏好:我是 Golang 的新手并且渴望改进。
所以我正在尝试从 Dave Cheney 的演讲中学习:https://youtu.be/NwEuRO_w8HE?t=812 我们将接口传递给方法以使代码更清晰、更通用。
我在下面实现了一个示例,其中我有一个可以输出到 std.out 或文件的结构。但是,我觉得只制作空结构(在我的示例中称为“打印”和“保存”)有点多余,这样我就可以附加方法。我该如何改进?
package main
import (
"fmt"
"io"
"io/ioutil"
"log"
)
type file struct {
data string
}
func (f *file) output(w io.Writer) error {
len, err := w.Write([]byte(f.data))
if err != nil {
return err
} else {
log.Println("Bytes Out: ", len)
return nil
}
}
type print struct{}
func (print *print) Write(p []byte) (n int, err error) {
return fmt.Printf("%s\n", p)
}
type save struct{}
func (s *save) Write(p []byte) (n int, err error) {
err = ioutil.WriteFile("./dat1", []byte(p), 0644)
if err != nil {
return -1, err
}
return len(p), nil
}
func main() {
f := file{"test"}
s := save{}
p := print{}
f.output(&s)
f.output(&p)
}
您的意图不明确,但回答您最初的问题:如何将函数作为接口值传递?
您可以创建一个类似适配器的类型来实现 io.Writer
,并且当它的 Write()
方法被调用时,它会转发给您选择的函数。一个典型的例子是 http.HandlerFunc
: it's a function type that implements http.Handler
,因此当需要 http.Handler
实现时可以传递一个函数。
对于 io.Writer
适配器,它可能如下所示:
type WriteFunc func(p []byte) (n int, err error)
func (w WriteFunc) Write(p []byte) (n int, err error) {
return w(p)
}
如果你有这样的功能:
func PrintWrite(p []byte) (n int, err error) {
return fmt.Printf("%s\n", p)
}
func SaveWrite(p []byte) (n int, err error) {
err = ioutil.WriteFile("./dat1", []byte(p), 0644)
if err != nil {
return -1, err
}
return len(p), nil
}
您可以像这样 io.Writer
使用它们:
f.output(WriteFunc(PrintWrite))
f.output(WriteFunc(SaveWrite))
在 Go Playground 上试用。
此处不需要 print
或 save
类型。你有一个方法,output
,需要一个 io.Writer
;关键在于您可以 任何作者 传递它。 stdout 和 files 都是写入器,所以这里的其他一切都是不必要的。你可以:
func main() {
f := file{"test"}
fp,err := os.Create("./dat1")
if err != nil {
panic(err)
}
f.output(fp) // This writes to a file
f.output(os.Stdout) // This writes to stdout
}