以io.Writer爲例看go中的interface{}

閱讀該文後的一些理解golang

###1 io.Writer接口 io.Writer接口有以下定義ui

package io    

type Writer interface {
    Write(p []byte) (n int, err error)
}
//根據go中接口的特色,全部實現了Write方法的類型,咱們都說它實現了io.Writer接口。

###2 somepkg.abc類型實現了io.Writer接口unix

package somepkg

type 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爲例看看方法的定義:code

func Fprintln(w io.Writer, a ...interface{}) (n int, err error)

方法的第一個參數是io.Writer,也就是說,任何實現了io.Writer接口的類型實例均可以傳遞進來;
咱們再看看Println方法內部實現:blog

func Println(a ...interface{}) (n int, err error) {
    return Fprintln(os.Stdout, a...)
}

咱們不妨追溯一下os.Stdout接口

Stdout = NewFile(uintptr(syscall.Stdout), "/dev/stdout")

也就是標準輸出.
從這裏能夠看出get

  1. NewFile方法new出來的os.FileWrite方法,那麼os.File這個Struct就已經實現了io.Writer接口
  2. 上面的=號說明了os.Stdout就是NewFile方法new出來的,他是os.File
  3. 結合前面的1和2,若是某個方法須要一個io.Writer接口做爲參數傳入的話,徹底能夠拿os.Stdout做爲一個io.Writer接口來用

再看一遍Fprintln方法的定義:it

func Fprintln(w io.Writer, a ...interface{}) (n int, err error)

若是第一個參數傳遞的是一個os.Stdout,內容便會被輸出到標準輸出,也就是屏幕上。
若是第一個參數傳遞的是一個普通文件,內容便會被輸出到該文件。
若是第一個參數傳遞的是bytes.Buffer,那麼,內容便輸出到了buffer中。io

###4 與上面的somepkg結合import

package main
import "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方法)

抱歉,比較囉嗦,爲了之後能看懂

相關文章
相關標籤/搜索