這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
閱讀該文後的一些理解
1 io.Writer介面
io.Writer介面有如下定義
package io type Writer interface { Write(p []byte) (n int, err error)}//根據go中介面的特點,所有實現了Write方法的類型,我們都說它實現了io.Writer介面。
2 somepkg.abc類型實現了io.Writer介面
package somepkgtype Abc struct { id int}func (a *Abc) Write(p []byte) (n int, err error){ //writing.... return 1,nil //類比返回,n表示寫了幾個位元組,err表示是否有錯誤}//根據go中介面的特點,由於abc類型實現了Write方法,我們就說abc類型實現了io.Writer介面。
3 io.Writer的應用
通常,我們在使用fmt包的時候是使用Println/Printf/Print方法。其實,在fmt包中還有Fprint序列方法,而且,Print序列方法內部調用的是Fprint序列方法。以Fprintln為例看看方法的定義:
func Fprintln(w io.Writer, a ...interface{}) (n int, err error)
方法的第一個參數是io.Writer,也就是說,任何實現了io.Writer介面的類型執行個體都可以傳遞進來;
我們再看看Println方法內部實現:
func Println(a ...interface{}) (n int, err error) { return Fprintln(os.Stdout, a...)}
我們不妨追溯一下os.Stdout:
Stdout = NewFile(uintptr(syscall.Stdout), "/dev/stdout")
也就是標準輸出.
從這裡可以看出
- NewFile方法new出來的os.File有Write方法,那麼os.File這個Struct就已經實現了io.Writer介面
- 上面的=號說明了os.Stdout就是NewFile方法new出來的,他是os.File
- 結合前面的1和2,如果某個方法需要一個io.Writer介面作為參數傳入的話,完全可以拿os.Stdout作為一個io.Writer介面來用
再看一遍Fprintln方法的定義:
func Fprintln(w io.Writer, a ...interface{}) (n int, err error)
如果第一個參數傳遞的是一個os.Stdout,內容便會被輸出到標準輸出,也就是螢幕上。
如果第一個參數傳遞的是一個普通檔案,內容便會被輸出到該檔案。
如果第一個參數傳遞的是bytes.Buffer,那麼,內容便輸出到了buffer中。
4 與上面的somepkg結合
package mainimport "somepkg"import "fmt"func main(){ a := &somepkg.abc{1} i,e :=fmt.Fprintln(a,"hello world") fmt.Println(i) // 1}
“hello world"會寫入到a裡,具體是如何寫的,調用的是abc裡的Write方法
當然目前樣本abc裡的Write方法根本就沒有還沒寫,只是返回了1和nil,所以後面的1會被列印出來
5 最後
介面命名一般以“動作+er”,理解為可以怎麼怎麼樣的“人”,比如Writer為可以理解為“會Write的人”
一旦某人(某個Struct)有能力Write了(實現Write方法了),我們就自動的認為他是個“會寫的人”,是個Writer
任何實現Write方法的Struct都可以當做io.Writer來傳遞給相關方法(如Fprintln方法)
抱歉,比較囉嗦,為了以後能看懂