TourOfGoをやってみた

# GOの基本が知りたくなった
以前、少し書いた（多分interfacesの辺り）が手違いで消してしまった。
やる気が失われたので、基礎をすっ飛ばして
自分が欲しい物を作ってみて学習するスタイルへシフトした。
いや、基本は学んどこう。と反省して復習兼ねて最初からもう一度やる。


# TourOfGoやる

## Packages
GOのプログラムはpackageで構成される。
プログラムのエントリポイントはmainパッケージである必要がある。らしい

パッケージ名はインポートパスと同じ名前にする必要がある。
package/hoge という場所に作るものはhogeというパッケージにする。


## Imports
書き方は２種類

- グループ化して書く方法（基本的にこれでよかろう）
```golang
import (
	"fmt"
	"math"
)
```

- １行ずつ書く方法
```golang
import "fmt"
import "math"
```

## Exported names
goにおいて最初の文字が大文字で始まるものは外部から参照可能なものである。という意味になる
（他の言語でいうところのパブリックですね）
```golang
package main

import (
	"fmt"
	"math"
)

func main() {
	fmt.Println(math.pi)//←これはありえない。「math.Pi」になる
}
```

## Functions 
関数の書き方

### 基本
func 〜〜〜で書く。
多くの多言語との違いとして引数と戻り値の型を名前の後ろに書く。という所。
```golang
func add(x int, y int) int {
	return x + y
}
```

#### 同じ型の引数が２つ以上ある場合は省略できる
```golang
func add(x int, y int, a string, b string) int {
って書いてエラーではないが
↓のように書けば良い。
func add(x, y int, a, b string) int {
	return x + y
}
```
#### 複数の戻り値を返す関数
()で囲んで複数書く
```golang
func swap(x, y string) (string, string) {
	return y, x
}
```

## Named return values
関数の宣言部分で戻り値の変数を宣言できる。
```golang
func split(sum int) (x, y int) {//←ここで宣言されているので内部では宣言せずに利用できる
	x = sum * 4 / 9
	y = sum - x
	return x, y
    //↑これは実は省略できる。
    //↓省略パターン。return x, y と同意味。
    return
    //変数名のチェックまでは行われず型の一致だけチェックされる。
    return 1, 1
    とか
    return y, x
    とかでもOK
}
```
（正直意味わからなくなりそうなのであまり使いたくないかも。と思った）

## Variables

変数宣言
varです。
同じ型の変数はカンマで連結して複数一括で宣言できる（引数と一緒）
```golang
var c, python, java bool
```

## Variables with initializers
変数の初期化子の話
```golang
var i, j int = 1, 2
```
この時に型を省略することが出来ます。との事
```golang
var i, j = 1, 2
//この際には初期化子から型が推論され自動セットされる。
//goをかじったばかりの私はi, j := 1, 2 って出来ないの？と思ってやったら出来なかった。
//↑関数の中ならできる。関数外（パッケージ直下）では出来ない
//関数の外で変数を宣言するときはvarが必要。
```

## Short variable declarations
関数の中ならvar省略して宣言できますよ。の話。
```golang
func main() {
	var i, j int = 1, 2
    //↑こう書き換える事が出来る
    //i, j := 1, 2
	k := 3
	c, python, java := true, false, "no!"

	fmt.Println(i, j, k, c, python, java)
}
```

## Basic types
型の話
```golang
bool

string

int  int8  int16  int32  int64
uint uint8 uint16 uint32 uint64 uintptr

byte // uint8 の別名

rune // int32 の別名
     // Unicode のコードポイントを表す

float32 float64

complex64 complex128
```

## Zero values
型によって初期値が決まっているから初期化子を与えずに変数宣言してもnullにはならんよ。という話
型ごとの初期値
```golang
数値型(int,floatなど): 0
bool型: false
string型: "" (空文字列( empty string ))
```

## Type conversions
型変換の話。
基本 ```変換したい型(値)``` でできる。
```golang
//例
i := 42
f := float64(i)
u := uint(f)
```

## Constants
定数の話。


定数は、文字(character)、文字列(string)、boolean、数値(numeric)のみで使える。
定数は const を使って宣言必須 (変数の様にvar省略して書く。という記法は無い）
```golang
package main

import "fmt"

const Pi = 3.14

func main() {
	const World = "世界"
	World = "hoge"
	fmt.Println("Hello", World)
	fmt.Println("Happy", Pi, "Day")

	const Truth = true
	fmt.Println("Go rules?", Truth)
}
```

## For
ループの話。
GOではループはforのみ。
これがwhileでありforでありforeach。
```golang
func main() {
	sum := 0
    //いわゆるforとして使う場合はいわゆるfor,括弧がないくらいか
	for i := 0; i < 10; i++ {
		sum += i
	}
	fmt.Println(sum)
}
```

## For continued
forの初期化と後処理ステートメントは任意です。
```for ; i < 10; {```
って書けますよ。さらに```;```が省略可能で
```for i < 10 {```と書けますよ。という話。

## Forever
無限ループさせたい時の話。
条件を全部省略すれば無限ループになる
```golang
for true {
    //無限ループ内処理
}
```
としたくなるが
```golang
for {
    //無限ループ内処理
}
```
で良い

## If
IFの話。
```golang
if x < 0 {
    return sqrt(-x) + "i"
}
```
これだけ。括弧は不要

## If with a short statement
if文の中にもforみたいなステートメントが書けますよ。という話

```golang
	if v := math.Pow(x, n); v < lim {
		return v
	}
    //このvはifのカッコ内だけが使える。
```

## If and else
if文ないのステートメントで宣言している変数はelseでも使えますよ。という話
```golang
	if v := math.Pow(x, n); v < lim {
		a := 1
		return v
	} else 
		fmt.Printf("%g >= %g\n", v, lim)
	}
```

## Switch
breakは無いんだよ。という
（各caseのセクションが終わると自動的にブレイクする）
```golang
func main() {
	fmt.Print("Go runs on ")
	switch os := runtime.GOOS; os {
	case "darwin":
		fmt.Println("OS X.")
	case "linux":
		fmt.Println("Linux.")
	default:
		// freebsd, openbsd,
		// plan9, windows...
		fmt.Printf("%s.\n", os)
	}
}
```

## Switch with no condition
条件のないSwitch

IF~ELSE~IF~ELSE~IF系をわかりやすく書くことが出来る（かも）
```golang
    if t.Hour() < 12 {
		fmt.Println("Good morning!")
    } else {
        if t.Hour() < 17 {
    		fmt.Println("Good afternoon.")
        } else {
    		fmt.Println("Good evening.")
        }
    }
    //↑みたいな腐ってきているIFをスッキリと書くことが出来る↓

	switch {
	case t.Hour() < 12:
		fmt.Println("Good morning!")
	case t.Hour() < 17:
		fmt.Println("Good afternoon.")
	default:
		fmt.Println("Good evening.")
	}
```

## Defer
deferをつけて呼び出した関数はfunctionの最後に実行される。
```golang
func main() {
	defer fmt.Println("world")

	fmt.Println("hello")
}
```

## Stacking defers
関数内で複数Deferが使われる場合、それらはスタック（後入先出、LIFO）されて最後に実行される。
最初いきなりTourOfGoやったときは、これ何に使うん？？って思ったけど普通に便利だった。
多言語でのfinaly的な用途で使える。

例えば↓ファイルAをファイルBに書き出すfunction
それぞれファイルを開いた後にすぐdeferをつけてファイルクローズの関数を呼んでいる。
これで関数終了時にはファイルがクローズされる事が約束される。
（いや、何に使うん？からあら便利ねーっに変わった）
```golang
func main() {
	var reader *bufio.Reader
	var writer *bufio.Writer

	read_file, _ := os.OpenFile("A", os.O_RDONLY, 0600)
	defer read_file.Close()　//←最後にファイルAを閉じる
	reader = bufio.NewReader(read_file)

	write_file, _ := os.OpenFile("B", os.O_WRONLY|os.O_CREATE, 0600)
	defer write_file.Close()　//←最後にファイルを閉じる
	writer = bufio.NewWriter(write_file)

	for {
		line, err := reader.ReadBytes('\n')
		if err == io.EOF {
			return
		}
		writer.Write(line)
		writer.Flush()
	}
}
```

## Pointers
### ポインタの宣言
*(アスタリクス)で宣言する。
```golang
var p *int //pはint型の変数を指すポインタである。
```
### 変数のポインタをポインタ変数に代入する時
```golang
&を使う
i := 42
p = &i　//&をつけることでpにはiのポイントが入る。
```
### ポインタの先にある値（変数の中身を使いたい時）
*を使う
```golang
fmt.Println(*p) // ポインタpを通してiから値を読みだす
*p = 21         // ポインタpを通してiへ値を代入する
```

## Structs
構造体。(最初クラスか？と思ったけどクラスとはちょっと話が違う様だ…）
```golang
type Vertex struct {
	X int
	Y int
}
```
## Struct Fields
ドットを使うことでプロパティにアクセスできます。
```golang
type Vertex struct {
	X int
	Y int
}

func main() {
	v := Vertex{1, 2}
	v.X = 4
	fmt.Println(v.X)
}
```

## Pointers to structs
構造体のフィールドはポインタを通してアクセスすることが出来る
↓どういうことか
```golang
func main() {
	v := Vertex{1, 2} //変数としての実態はv
    p := &v           //pにはvのポインタが入っている
	p.X = 1e9         //←これ
    //↑普通に考えるとpはポインタであってstructではないのだからp.Xなんてエラーになりそうなもんだが使える。
    //↑このp.Xは(*p).Xと書くことも出来る。これはまぁそうだろうな。という感じ
    //↑これでは面倒くさかろう（まぁ確かに…）ということで、p.Xでも使えるようにしてくれている模様。

	fmt.Println(v)
}
```

## Struct Literals

> structリテラルは、フィールドの値を列挙することで新しいstructの初期値の割り当てを示しています。

正直、日本語がよくわからない…

↓どういうことか
```golang
type Vertex struct {
	X, Y int
}

var (
    //↓これらのこと
	v1 = Vertex{1, 2}  // has type Vertex
	v2 = Vertex{X: 1}  // Y:0 is implicit
	v3 = Vertex{}      // X:0 and Y:0
	p  = &Vertex{1, 2} // has type *Vertex
)

func main() {
	fmt.Println(v1, p, v2, v3)
}
```

構造体を使う時の初期化方法の話だった
```Vertex{1, 2}```ただ値をカンマで区切ると宣言順に格納
```Vertex{X: 1}```フィールドの値を指定して初期化することもできる
```Vertex{}```していなければ対象の型の初期値が入る（例だとintなので0)
```&Vertex{1, 2}```実体となった構造体のポインタを返す

## Arrays
配列の話
>[n]T 型は、型 T の n 個の変数の配列( array )を表します。

頭が悪いのでこういう書き方をされるとすぐわからなくなる。
↓例を見たらすぐわかった。
```golang
var a [10]int
```
配列は　要素数＋型で宣言する
int型の配列```[10]int```
```golang
//varを省略する場合{}は必須
a := [2]int{}
//→[0 0]
a := [2]int{1,1}
//→[1 1]
a := [2]int{1}
//→[1 0}
```

## Slices
可変長の配列の話
宣言時に要素数を指定すると配列、葉数を指定しないとスライスになる。

```golang
func main() {
    //配列
	primes := [6]int{2, 3, 5, 7, 11, 13}

    //配列からスライスに
	var s []int = primes[1:4]　//配列名[スタートインデックス:終了インデックス]で配列から指定した範囲のスライスを生成出来る
	fmt.Println(s)
}
```

## Slices are like references to arrays
配列から値を引っ張った場合に、スライスに入っている値はコピーではなく参照なんですよ。という話
スライスの値を変更すると参照元の配列も変更される。


## Slice literals

```golang
	q := []int{2, 3, 5, 7, 11, 13}
```

## Slice defaults
スライスするときの省略形について
```golang
var a [10]int
//↓は全て同じ意味
a[0:10]
a[:10] //最初の数字を省略すると先頭を指したのと同意になる
a[0:] //２番めの数字を省略すると最後尾を指したのと同意になる
a[:] //なので両方省略すると全部
```

## Slice length and capacity
スライスは長さ( length )と容量( capacity )の両方を持っています。という話

### スライスの長さとは
スライスの要素数のこと

### スライスの容量とは
スライスの最初の要素から数えたときの配列の要素数

### サンプルコード

```golang
package main

import "fmt"

func main() {
    //printSliceでlen(長さ)cap(容量)スライスの中身を出力する。

	s := []int{2, 3, 5, 7, 11, 13}
	printSlice(s)
	//len=6 cap=6 [2 3 5 7 11 13]
    //↑配列{2, 3, 5, 7, 11, 13}から作成した長さ６、容量６のスライス

	// Extend its length.
	s = s[:2]
	printSlice(s)
	//len=2 cap=6 [2 3]
    //↑最初から２個目までで再スライスする。

	// Drop its first two values.
	s = s[2:]
	printSlice(s)
	//len=0 cap=4 []
    //↑２番目以降から最後までで再スライスすると何もなくなった
	
	s = s[:4]
	printSlice(s)
	//len=4 cap=4 [5 7 11 13]
    //↑値がなくなったように見えるが、省略形ではなく数値を指定したやると後方の値は復活する
    //おそらくもとになる配列が残っているから（多分）ポインタのため、後方には戻れない模様
}

func printSlice(s []int) {
	fmt.Printf("len=%d cap=%d %v\n", len(s), cap(s), s)
}

```

## Nill slices
sliceの初期値に関してはnil(NULL)になってます。という話。


## Creating a slice with make
sliceはmakeで作れるんです。という話

```golang
	a := make([]int, 5)
    //[0 0 0 0 0]

    //３番目の引数としてスライスの容量を指定できる
	b := make([]int, 0, 5)
    //[]
```

## Appending to a slice
スライスへ要素を追加するにはappendを使うんだよ。という話

## Range
foreachみたいな事する時の話。
（途中）
（続く）