[Go] Methods and Interfaces その2

– Interface values with nil underlying values
If the concrete value inside the interface itself is nil, the method will be called with a nil receiver.

type I interface {
	M()
}

type T struct {
	S string
}

func (t *T) M(){
	if t == nil {
		fmt.Println("<nil>")
		return
	}
	fmt.Println(t.S)
}

func main(){
	var i I

	var t *T
	i = t
	describe(i)
	i.M()

	i = &T{"hello"}
	describe(i)
	i.M()
}

func describe(i I){
	fmt.Printf("(%v, %T)\n", i, i)
}

– Nil interface values
A nil interface value holds neither value nor concrete type.

type I interface {
	M()
}

func main(){
	var i I

	describe(i)
	i.M()
}

func describe(i I){
	fmt.Printf("(%v, %T)\n", i, i)
}

(, )
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x49abcf]

goroutine 1 [running]:
main.main()
/home/vagrant/next/go/hello.go:14 +0x8f

– The empty interface
The interface type that specifies zero methods is known as the empty interface: interface{}

func main(){
	var i interface{}
	describe(i)

	i = 42
	describe(i)

	i = "hello"
	describe(i)
}

func describe(i interface{}){
	fmt.Printf("(%v, %T)\n", i, i)
}

– Type assertions
A type assertion provides access to an interface value’s underlying concrete value.

func main(){
	var i interface{} = "hello"
	
	s := i.(string)
	fmt.Println(s)

	s, ok := i.(string)
	fmt.Println(s, ok)

	f, ok := i.(float64)
	fmt.Println(f, ok)

	f = i.(float64)
	fmt.Println(f)
}

– Type switches
A type switch is a construct that permits several type assertions in series.

func do(i interface{}){
	switch v := i.(type){
	case int:
		fmt.Printf("Twice %v is %v\n", v, v*2)
	case string:
		fmt.Printf("%q is %v bytes long\n", v, len(v))
	default:
		fmt.Printf("I don't know about type %T!\n", v)
	}
}

func main(){
	do(21)
	do("hello")
	do(true)
}

– Stringers
A stringer is a type that can describe itself as a string. The fmt package look for this interface to print values.

type Person struct {
	Name string
	Age int
}

func (p Person) String() string {
	return fmt.Sprintf("%v (%v years)", p.Name, p.Age)
}

func main(){
	a := Person{"Arthur Dent", 42}
	z := Person{"Zaphod Beeblebrox", 9001}
	fmt.Println(a, z)
}

### Errors
Go programs express error state with error values.

type MyError struct {
	When time.Time
	What string
}

func (e *MyError) Error() string{
	return fmt.Sprintf("at %v, %s", e.When, e.What)
}

func run() error {
	return &MyError {
		time.Now(),
		"it didn't work",
	}
}

func main(){
	if err := run(); err != nil {
		fmt.Println(err)
	}
}

### Readers
The io package specifies the io.Reader interface, which represents the read end of a stream of data.

import (
	"fmt"
	"io"
	"strings"
)

func main(){
	r := strings.NewReader("Hello, Reader!")

	b := make([]byte, 8)
	for {
		n, err := r.Raed(b)
		fmt.Printf("n = %v err = %v b= %v\n", n, err, b)
		fmt.Printf("b[:n] = %q\n", b[:n])
		if err == io.EOF {
			break
		}
	}
}

### Images

import (
	"fmt"
	"image"
)

func main(){
	m := image.NewRGBA(image.Rect(0, 0, 100, 100))
	fmt.Println(m.Bounds())
	fmt.Println(m.At(0, 0).RGBA())
}

Methods と Interfaceを使いこなすには 少し時間がかかりそうだ