Data type interface - cruisechang/wiki-golang GitHub Wiki

Basics

The Laws of Reflection

interface 是type中重要的一類。他體現一組固定的methods。

interface variable能儲存任何具體的值,該值是實作了這個interface的methods。

例如 io.Reader / io.Writer from io package.

// Reader is the interface that wraps the basic Read method.
type Reader interface {
    Read(p []byte) (n int, err error)
}

// Writer is the interface that wraps the basic Write method.
type Writer interface {
    Write(p []byte) (n int, err error)
}

任何type只要實作Read(p []byte) (n int, err error),就可稱為它實作io.Reader。

而你只要自訂一個io.Reader的變數,就可儲存這個type。

但是這個io.Reader變數只能呼叫Read這個method。

var r io.Reader
r = os.Stdin           //can store os.Stdin
r = bufio.NewReader(r) //can store bufio.NewReader(r)
r = new(bytes.Buffer)  //can store bytes.Buffer
// and so on

interface type

  • interface type variable儲存兩個部分:實體的value及value's type descriptor.

value就是底層實際資料物件,它本身實作了這個interface的methods set。

type descriptor說明底層實際物件的詳細type。

var r io.Reader
tty, err := os.OpenFile("/dev/tty", os.O_RDWR, 0)
if err != nil {
    return nil, err
}
r = tty

r儲存了the (value, type) pair, (tty, *os.File).

value=tty

type=*os.File

這個type實作了許多io.Reader沒有的method,但是我們只能呼叫io.Reader有的Read這個。

也因為r的type descriptor有完整的*os.File描述,所以我們可以轉型,

把r從io.Reader轉成io.Writer。因為*os.File type,實作了io.Writer的Write method.

var w io.Writer
w = r.(io.Writer)

結論就是interface type決定的該interface variable包含哪些methods,但是variable內實際的資料包括的methods可能更多。

Empty interface type : interface{}

它體現了一組空個methods,所以interface{}的變數可以儲存任何type,無論這個type有沒有methods。

這不代表interface type是dynamic type,實際上它是有固定類型的,它的類型就是interface{},

即便他儲存的資料在runtime改變了type,它本身的type是不變的。

承上例,我們可以轉型成interface{}

var empty interface{}
empty=w

這時不需要assertion,因為interface{} type 能接受任何type。

empty同樣也儲存了(value, type) pair, (tty, *os.File)。

我們隨時可以把empty轉回 empty(io.Writer)

注意的是,empty只儲存了底層資料的value,type。並沒儲存 io.Writer這個interface type的value,type。

因為os.File本身實作的io.Writer,所以不需要再存io.Writer了。