A Tour of Go メモ 【7】五日目

# A Tour of GO
[A Tour of Go](https://go-tour-jp.appspot.com/methods/9 #)


#interface

インターフェース型と同じ関数を実装していない物はインターフェース型に代入できない

```
func main() {
	var a Abser
	f := MyFloat(-math.Sqrt2)
	v := Vertex{3, 4}

        // MyFloatにはAbser（）が実装されている
	a = f
        // *VertexにもAbser（）は実装されている
	a = &v

　　　　 // aは*Vertexではないため、Aber()が実装されていない
	a = v

	fmt.Println(a.Abs())
}

type MyFloat float64

func (f MyFloat) Abs() float64 {
	if f < 0 {
		return float64(-f)
	}
	return float64(f)
}

type Vertex struct {
	X, Y float64
}

// *vertexにはAbserと同じAbs()関数が実装されている
// Vertexのポインタ型に対して、実装している
func (v *Vertex) Abs() float64 {
	return math.Sqrt(v.X*v.X + v.Y*v.Y)
}
```

#メソッドを実装し、インターフェースを実装する

```
type I interface {
	M()
}

type T struct {
	S string
}

// T に I（インターフェース）と同じメソッドを実装する
func (t T) M() {
	fmt.Println(t.S)
}

func main() {
    //TはIと同じメソッドを持っているので、I型と判断されるため、i(I型)に代入できる
	var i I = T{"hello"}
	i.M()
}
```

#Interface Values

```
type I interface {
	M()
}

type T struct {
	S string
}

func (t *T) M() {
	fmt.Println(t.S)
}

type F float64

func (f F) M() {
	fmt.Println(f)
}

func main() {
	var i I

	i = &T{"Hello"}
	describe(i)
	i.M()    // (&{Hello}, *main.T） Hello
    //M（） は元となるT型に宣言した同名のメソッドが呼び出される

	i = F(math.Pi)
	describe(i)
	i.M()   //(3.141592653589793, main.F) 3.141592653589793
　　 //M（） は元となるT型に宣言した同名のメソッドが呼び出される
}
```

# Interface values with nil underlying values

```
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() {
    //　この時点ではiはnilである
	var i I

    // Tには何も入っていない,nilである
	var t *T
    // しかし、 iにはnilであるT型が入っているので、i自体は非nilである
	i = t
	describe(i)  // (<nil>, *main.T) <nil> 
	i.M()

	i = &T{"hello"}
	describe(i)  // (&{hello}, *main.T) <nil>
	i.M()
}
func describe(i I) {
	fmt.Printf("(%v, %T)\n", i, i)
}
```
#Nil interface values

```
type I interface {
	M()
}

func main() {
    //値も具体的な型も持っていない
	var i I
	describe(i)
	i.M()  // 何も値も持たないインターフェース型からはメソッドを呼べない
}

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

```

#The empty 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
 string型をインターフェース型に変換した場合、
インターフェース型の中身が"hello"だったとしても、string型として扱うことができない。
そのため、再度インターフェース型からstring型に戻す作業が必要になる

```
func main() {
	var i interface{} = "hello"

	s := i.(string)
	fmt.Println(s)
    //　okがiの中身がstring型値を保持しているかをboolで返す
	s, ok := i.(string)
	fmt.Println(s, ok)

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

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

```

#Stringers
[fmtパッケージのソース](https://golang.org/src/fmt/print.go #)
Printlnメソッドが実行された時、引数がStringer型だったらstring()が実行されるはず
574行目あたりだろうか・・・

```
type Person struct {
	Name string
	Age  int
}

//fmtのパッケージに以下の Stringer インターフェースの記述がある
************************************************************
type Stringer interface {
    String() string
}
************************************************************

//Stringer型と同じString()メソッドを宣言すると Person型にStringerインターフェースを実装できる
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
組み込みのerrorインターフェースを実装し、エラーメッセージをカスタマイズする

```
type MyError struct {
	When time.Time
	What string
}

// error型のインターフェースを実装
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() {
    // もし、run()で戻り値があったら、戻り値を出力
	if err := run(); err != nil {
		fmt.Println(err)
	}
}
```
#Readers

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

	b := make([]byte, 8)
	for {
	    // Readメソッドはint型とerror型の戻り値がある
		n, err := r.Read(b)
		fmt.Printf("n = %v err = %v b = %v\n", n, err, b)
		fmt.Printf("b[:n] = %q\n", b[:n])
		//ストリームが終わったら、Readメソッドが返すio.EOFというエラーがerrに入るので、
		//それを判定して、ループを抜ける
		if err == io.EOF {
			break
		}
	}
}
```

#Images

```

import (
	"fmt"
	"image"
)
*****************************************************************
*imageパッケージの中身

type Image interface {
    ColorModel returns the Image's color model.
    ColorModel() color.Model
    //Bounds returns the domain for which At can return non-zero color.
    // The bounds do not necessarily contain the point (0, 0).
    Bounds() Rectangle
    // At returns the color of the pixel at (x, y).
    // At(Bounds().Min.X, Bounds().Min.Y) returns the upper-left pixel of the grid.
    // At(Bounds().Max.X-1, Bounds().Max.Y-1) returns the lower-right one.
    At(x, y int) color.Color
}

type RGBA struct {
    // Pix holds the image's pixels, in R, G, B, A order. The pixel at
    // (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*4].
    Pix []uint8
    // Stride is the Pix stride (in bytes) between vertically adjacent pixels.
    Stride int
    // Rect is the image's bounds.
    Rect Rectangle
}
//RGBAにはAt, Boundes ColorModel()などのメソッドがあるので、Imageインターフェースが実装されている
func (p *RGBA) At(x, y int) color.Color
func (p *RGBA) ColorModel() color.Model
func (p *RGBA) Bounds() Rectangle


func Rect(x0, y0, x1, y1 int) Rectangle
//Rect is shorthand for Rectangle{Pt(x0, y0), Pt(x1, y1)}.

func NewRGBA(r Rectangle) *RGBA
//NewRGBA returns a new RGBA image with the given bounds.

*colorのパッケージ
type Color interface {
    // RGBA returns the alpha-premultiplied red, green, blue and alpha values
    // for the color. Each value ranges within [0, 0xffff], but is represented
    // by a uint32 so that multiplying by a blend factor up to 0xffff will not
    // overflow.
    //
    // An alpha-premultiplied color component c has been scaled by alpha (a),
    // so has valid values 0 <= c <= a.
    RGBA() (r, g, b, a uint32)
}
*****************************************************************


func main() {
    // Rect()でRectange型の構造体を作成
    // Rectange型を引数として、RGBA型の構造体を作成
	m := image.NewRGBA(image.Rect(0, 0, 100, 100))
	fmt.Println(m.Bounds())
	fmt.Println(m.At(0, 0).RGBA())
}
```