入門プログラミングGo（構造体、インターフェイス）

# 構造体の定義
```go
    var curiosity struct {
        lat  float64
        long float64
    }
    // ファミリーの定義
	curiosity.lat = -4.44444
	curiosity.long = 133.333333

    //複合リテラルで定義も可能
    cr := curiosity{-4.44, 133.3333}
```

# メソッドを使用した構造体の例
```go
package main

import (
	"fmt"
)

type coordinate struct {
	d, m, s float64
	h       rune
}

func (c coordinate) decimal() float64 {
	sign := 1.0
	switch c.h {
	case 'S', 'W', 's', 'w':
		sign = -1
	}
	return sign * (c.d*c.m/60 + c.s/3600)
}
func main() {
	lat := coordinate{4, 35, 22.2, 'S'}
	long := coordinate{137, 26, 30.12, 'E'}
	fmt.Println(lat.decimal(), long.decimal())
}
```

# コンストラクタを使用した構造体の初期化
```go
package main

import (
	"fmt"
)

type coordinate struct {
	d, m, s float64
	h       rune
}

type location struct {
	lat, long float64
}

func (c coordinate) decimal() float64 {
	sign := 1.0
	switch c.h {
	case 'S', 'W', 's', 'w':
		sign = -1
	}
	return sign * (c.d*c.m/60 + c.s/3600)
}

func newLocation(lat, long coordinate) location {
	return location{lat.decimal(), long.decimal()}
}

func main() {
	curiosity := newLocation(coordinate{4, 35, 22.2, 'S'}, coordinate{137, 26, 30.12, 'E'})
	fmt.Println(curiosity)
}
```
- コンストラクタの関数の名前は`newType` or `NewType`
    - 外部へエクスポートするなら`NewType`, 内部のみなら`newType`

## (私見)構造体に対するメソッドの利点
- オブジェクト指向：クラス内部で定義されたメソッドがクラスの各プロパティまたはメソッドを使用する
- Golog：構造体をレシーバーで指定してその構造体全部を見られる（まとめが下手かもしれない。。。）

# メソッドの転送
```go
package main

import (
	"fmt"
)

type temperature struct {
	high, low celsius
}

type location struct {
	lat, long float64
}

type celsius float64

type report struct {
	sol         int
	temperature temperature
	location    location
}

func (t temperature) average() celsius {
	return (t.high + t.low) / 2
}

func (r report) average() celsius {
    // メソッドを転送してreportから直接average()を呼べるようにする
    // これにより、ロジックを丸々コピーする必要がない
	return r.temperature.average()
}

func main() {
	bradbury := location{-4.44, 133.33}
	t := temperature{high: -1.0, low: -78.0}
    // 各フィールドを指定して代入
	report := report{sol: 15, temperature: t, location: bradbury}
	fmt.Printf("%+v\n", report.temperature.high)
	fmt.Printf("%+v\n", report.temperature.low)
	fmt.Printf("%+v\n", report.average())
}
```

## 構造体の埋め込み
```go
type report struct {
    sol int
    temperature // report に temperature 型を埋め込む
                // 埋め込み型と同じ名前のフィールドが生成される（この場合はtempareture）
    location
}
```
temperature型のメソッドが使用可能になる

# インターフェース
- <b>それは何か</b>＝オブジェクト
- <b>それで何ができるか</b>＝インターフェース
    - 型が何を行えるかに焦点を絞っている

## interface型
例えば
```go
var t interface {
    talk() string
}
```
「引数を受け取らず、文字列を返す`talk`という名前のメソッド」を指定している方ならば、このインターフェイスは満たされる。

```go
package main

import (
	"fmt"
	"strings"
)

type martian struct{}

func (m martian) talk() string {
	return "nack nack"
}

type laser int

func (l laser) talk() string {
	return strings.Repeat("pew", int(l))
}

func main() {
	var talker interface {
		talk() string
	}
    
    // martian型はtalk()メソッドを持つ
	t = martian{}
	fmt.Println(t.talk())

	t = laser(3)
	fmt.Println(t.talk())
}

```
慣習的に`interface`型には-erをつけるのが一般的
```go
package main

import (
	"fmt"
	"strings"
)

type martian struct{}

func (m martian) talk() string {
	return "nack nack"
}

type laser int

func (l laser) talk() string {
	return strings.Repeat("pew", int(l))
}

type talker interface {
	talk() string
}

func shout(t talker) {
	louder := strings.ToUpper(t.talk())
	fmt.Println(louder)
}

func main() {

	shout(martian{})
	shout(laser(3))
}
```
インターフェースの条件を満たしていれば、適用可能
例えば`laser`はtalk()メソッドを持っている→talkerインターフェイスの要件を満たす→shout()の引数になりうる

laser(3)だけだとわかりずらい
以下のように考える
```go
a := laser(1)
fmt.Println(a)
shout(martian{})
shout(a)
```
- aは`laser`型で1とする
- `shout(a)`によってa(laser型)はインターフェイスが満たされるので`shout()`できる
- インターフェイスの要件を満たせば関数に渡す引数の型を柔軟に選ぶことができる→インターフェイスの要件さえ満たせば、要件を満たす任意の構造体を関数の引数にとれる
- インターフェイスは「君にはこれができますか？」という宣言
- 構造体のメンバにインターフェイスの要件を満たすメソッドを持つものが存在すれば、その構造体のインスタンスはインターフェイスを引数にする関数を使用できる
-