2012-12-16 97 views
9

對於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是一個讀者和作家,我期待此代碼工作。 我曾嘗試接口類型轉換有:

readStuff(sl.(buffio.Reader)) 

但它也不起作用。所以我有兩個問題:

  • 它爲什麼不起作用?
  • 這個問題的理念是什麼?

回答

7

它們是不同的類型。然而,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) { 
    [...] 
} 
+0

謝謝!它與readStuff(* sl.Reader) – user1612346

+0

一起工作我會有第二個問題:如果我的所有參數都是切片而不是單個參數會怎麼樣。有沒有什麼優雅的方式將一片ReadWriter轉換爲一片Reader? – user1612346

+2

我認爲你會發現最優雅的解決方案是創建一個新的切片並通過for循環進行填充。 – Daniel

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

(也here


輸出:

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

這樣test可以消耗任何io.ReadWriter,而不僅僅是一個特定的。這是對你的「哲學」問題的暗示。