我还是Go的新手,我很惊讶无法使用嵌入式接口的子类型.这是一个小例子来解释我的意思:
func test(sl bufio.ReadWriter){
// cannot use sl(type bufio.ReadWriter) as type bufio.Reader in function argument
readStuff(sl)
[...]
writeStuff(sl) // same kind of error
}
func readStuff(sl bufio.Reader){
[...]
}
Run Code Online (Sandbox Code Playgroud)
由于每个接口都具有相同的内存布局,而ReadWriter是Reader和Writer,因此我希望此代码能够正常工作.我确实尝试将接口类型转换为:
readStuff(sl.(buffio.Reader))
Run Code Online (Sandbox Code Playgroud)
但它也不起作用.所以我有两个问题:
他们是不同的类型.但是,a bufio.ReadWriter
包含指向bufio.Reader
类型和bufio.Writer
类型的指针作为其结构的元素.所以传递正确的一个应该很容易.试试这个:
func test(sl bufio.ReadWriter){
readStuff(sl.Reader)
[...]
writeStuff(sl.Writer)
}
// Changed this bufio.Reader to a pointer receiver
func readStuff(sl *bufio.Reader) {
[...]
}
Run Code Online (Sandbox Code Playgroud)
bufio.ReadWriter是具体类型,而不是接口.但是,它确实满足接口(io.ReadWriter),因此可以将其分配给适当接口类型的变量/函数参数.然后它按照您预期的方式工作(您的代码实际上不使用任何接口):
package main
import (
"bufio"
"bytes"
"fmt"
"io"
"log"
)
func readStuff(r io.Reader) {
b := make([]byte, 10)
n, err := r.Read(b)
if err != nil && err != io.EOF {
log.Fatal(err)
}
fmt.Printf("readStuff: %q\n", b[:n])
}
func writeStuff(w io.Writer) {
b := []byte("written")
n, err := w.Write(b)
if n != len(b) {
log.Fatal("Short write")
}
if err != nil {
log.Fatal(err)
}
}
func test(rw io.ReadWriter) {
readStuff(rw)
writeStuff(rw)
}
func main() {
r := io.Reader(bytes.NewBufferString("source"))
var uw bytes.Buffer
w := io.Writer(&uw)
rw := bufio.NewReadWriter(bufio.NewReader(r), bufio.NewWriter(w))
test(rw)
rw.Flush()
fmt.Printf("The underlying bytes.Buffer writer contains %q\n", uw.Bytes())
}
Run Code Online (Sandbox Code Playgroud)
(还在这里)
输出:
readStuff: "source"
The underlying bytes.Buffer writer contains "written"
Run Code Online (Sandbox Code Playgroud)
这种方式test
可以消耗任何io.ReadWriter
,而不仅仅是特定的.这是对你的"哲学"问题的暗示.