8

我对 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){
    [...]
}

由于每个接口都具有相同的内存布局,并且 ReadWriter 是 Reader 和 Writer,因此我希望这段代码能够正常工作。我确实尝试使用以下方式转换接口类型:

readStuff(sl.(buffio.Reader))

但它也不起作用。所以我有两个问题:

  • 为什么它不起作用?
  • 关于这个问题的围棋哲学是什么?
4

2 回答 2

7

他们是不同的类型。但是,abufio.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) {
    [...]
}
于 2012-12-16T21:03:00.377 回答
6

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())
}

(也在这里


输出:

readStuff: "source"
The underlying bytes.Buffer writer contains "written"

这种方式test可以消耗任何io.ReadWriter,而不仅仅是一个特定的。这暗示了您关于“哲学”的问题。

于 2012-12-17T07:09:19.057 回答