Interface 可以說是 golang 的精髓之一。golang interface 特殊的語法以及概念也是工程師常常犯錯的地方。此題只是用來釐清自己的概念。

題目

請問以下程式輸出結果為何

package main

import "fmt"

type S struct{
    val int
}

func (s S) F() {}

type IF interface {
	F()
}

func InitType() S {
	var s S
	return s
}

func InitPointer() *S {
	var s *S
	return s
}
func InitEfaceType() interface{} {
	var s S
	return s
}

func InitEfacePointer() interface{} {
	var s *S
	return s
}

func InitIfaceType() IF {
	var s S
	return s
}

func InitIfacePointer() IF {
	var s *S
	return s
}

func main() {
	// fmt.Println(InitType() == nil) // type mismatch
	fmt.Println(InitPointer() == nil)
	fmt.Println(InitEfaceType() == nil)
	fmt.Println(InitEfacePointer() == nil)
	fmt.Println(InitIfaceType() == nil)
	fmt.Println(InitIfacePointer() == nil)
}

回歸基本

在回答問題之前先複習什麼是 Interface SatisfactionInterface Values ,分別在 The Go Programming Language 章節 7.3 和 7.5。

Interface Satisfaction

直接給出書上的解釋,這兩段句子及範例程式已經淺顯易懂,不多作解釋:

A type satisfies an interface if it possesses all the methods the interface requires.

The assignability rule for interfaces is very simple: an expression may be assigned to an interface only if its type satisfies the interface.

/*
package io
type Writer interface {
    Write(p []byte) (n int, err error)
}
*/

var w io.Writer
w = os.Stdout           // OK: *os.File has Write method
w = new(bytes.Buffer)   // OK: *bytes.Buffer has Write method
w = time.Second         // compile error: time.Duration lacks Write method

Interface Values

The Go Programming Language 7.5 第一句開門見山地馬上給出概念:

Conceptually, a value of an interface type, or interface value has two components, a concrete type and a value of that type . These are called the interface’s dynamic type and dynamic value.

並且用一個例子做出了很棒的解釋:

var w io.writer
w = os.Stdout
w = new(bytes.Buffer)
w = nil

另一個例子:

var w io.Writer
var buf *bytes.Buffer
w = buf

fmt.Printf("%v %T\n", w, w) // <nil>  *bytes.Buffer
if w != nil {
    fmt.Println("w not nil") // This line will be executed
}

w != nil 要成立則 dynamic typedynamic value 皆為 non-nil 才會成立。 因為 w 的 dynamic value 是 *bytes.Buffer 不為 nil 所以 w != nil 就會成立。

解答

題目的 Line 43, 44 難度不高,直接跳過 剩下的看下圖

Line 50 牽扯到了 method set 的細節,留著下篇解釋,可以參考 Reference 1, 2

Reference

  1. https://golang.org/ref/spec#Method_sets
  2. https://stackoverflow.com/questions/33587227/method-sets-pointer-vs-value-receiver