Goアウトプット #01

# 多重代入

```go
var a, b, c int
a, b, c = 10, 20, 30
```
または

```go
a, b, c := 10, 20, 30
```

# 同じ型の複数宣言
- 初期化した値はゼロ値と呼ばれる。  
※数値の場合は0

```go
func main() {
	var (
		x int = 100
		y int = 300
		z int
	)
    // zは初期化されているだけなので、0になる

	fmt.Println("x + y + z =", x+y+z)
}

// -> 400
```

## iota識別子
- 連続した整数型整数を表現することができる<br>
※変数でやったらエラーでた。←定数宣言でしか使えないから、そりゃそう。

```go
func main() {
	const (
		x = iota
		y
		z
	)
	fmt.Println(x, y, z) 
}

// -> 0 1 2
```
```go
func main() {
	const (
		x = 1
		y = iota
		z
	)
	fmt.Println(x, y, z) 
}

// -> 1 1 2
```
```go
func main() {
	const (
		x = 10
		y = iota + 10
		z
	)
	fmt.Println(x, y, z) 
}

// -> 10 11 12
```
```go
func main() {
	const (
		x = iota * iota
		y
		z
		zz
	)
	fmt.Println(x, y, z, zz) 
}

// -> 0 1 4 9
```

# 条件分岐(switch-case)
- fallthroughを使用すれば、直下の処理が実行される<br>
└必ずcase文の最後に記述。
- 論理値、文字列を使用することができる

```go
func main() {
	value := 1
	switch value {
	case 1:
		fmt.Println("value = 1")
		fallthrough
	case 2:
		fmt.Println("value = 2 or 3")
	default:
		fmt.Println("value = other")
	}
} 

//-> value = 1
//   value = 2 or 3
```
```go
func main() {
	value := 15
	switch {
	case value > 0 && value <= 10:
		fmt.Println("1 ~ 10")
	case value > 10 && value <= 20:
		fmt.Println("11 ~ 20")
	case value > 20 && value <= 30:
		fmt.Println("21 ~ 30")
	default:
		fmt.Println("other")
	}
}

// -> 11 ~ 20
```
```go
func main() {
	value := "XYZ"
	switch value {
	case "ABC":
		fmt.Println("ABC")
	case "LMN":
		fmt.Println("LMN")
	case "XYZ":
		fmt.Println("XYZ")
	default:
		fmt.Println("other")
	}
}

// -> "XYZ"
```

# 繰り返し(for)
- break<br>
└ループ処理を強制的に抜ける
- continue<br>
└ループブロックの処理をスキップする

```go
func main() {
	i := 0
	for {
		if i == 20 {
			break
		}
		fmt.Println(i)
		i++
	}
}

// -> 1.....19
```
```go
func main() {
	value := 0
	for {
		if value%2 == 0 {
			fmt.Println(value)
			value++
		} else {
			value++
			continue
		}
		if value > 10 {
			fmt.Println("")
			break
		}
	}
}

//-> 0
//   2
//   4
//   6
//   8
//   10
```

# データ型
## 文字列型

- インデックスに保存されるバイト数は文字によって異なる。<br>
└漢字はものによって4バイト使用するものがある。

```go
func main() {
	str := "abcあいうえお"
	for index, codepoint := range str {
		result := fmt.Sprintf("index=%d, rune=%d, string=%s", index, codepoint, string(codepoint))
		fmt.Println(result)
	}
}

// -> index=0, rune=97, string=a
//  index=1, rune=98, string=b
//  index=2, rune=99, string=c
//  index=3, rune=12354, string=あ
//  index=6, rune=12356, string=い
//  index=9, rune=12358, string=う
//  index=12, rune=12360, string=え
//  index=15, rune=12362, string=お
```

## len()関数

- 文字列や配列のバイト数を取得する時に使用する

```go
func main() {
	str1 := "ABC"
	str2 := "あいう"
	fmt.Println(len(str1), len(str2))
}

// -> 3 9
```

## RuneCountInString()関数

- 文字数を取得する時に使用する
- unicode/utf8パッケージを読み込む必要がある

```go
import (
	"fmt"
	"unicode/utf8"
)

func main() {
	str1 := "ABC"
	str2 := "あいう"
	fmt.Println(utf8.RuneCountInString(str1), utf8.RuneCountInString(str2))
}

// -> 3 3
```

# strconvパッケージ

## Itoa()関数

- int型整数を文字列に変換する

```go
func main() {
	x := 12345
	fmt.Println(strconv.Itoa(x))
}

// -> 12345　※文字列
```

# 配列

- デフォルトではゼロ値で初期化される。
- `[...]`で指定すると、初期化の際に設定されて要素数が自動的に配列の長さになる。

```go
func main() {
	var array [3]int
	for _,value := range array {
		fmt.Println(value)
	}
	fmt.Println("-----")

	array[0] = 100
	array[1] = 200
	array[2] = 300
	for _, value := range array {
		fmt.Println(value)
	}
}
// -> 0
//  0
//  0
//  -----
//  100
//  200
//  300
```

# スライス

- ポインタ(ptr)、長さ(len)、容量(cap)からデータ構造を保持している
- 長さをlen()関数、容量をcap()関数で取得できる
- 配列からスライスを作成するだけでなく、スライスからスライスを作成することができる<br>
※スライスは参照型

```go
// スライス構造体
type SliceHeader struct {
  Data unitptr  //配列の参照
  Len  int      //長さ
  Cap  int      //容量
}
```

## 配列からの取得

`スライス := 配列またはスライス[下限:上限]`

※個人的にいいと思った考え方は`:`をスライスと捉える。
└`x:`だとx以降のスライス。`:x`だとxまでのスライス。
※下限は含み、上限は含まない

```go
func main() {
	array := [...]string{"A", "B", "C", "D", "E"}
	slice1 := array[:]
	slice2 := array[1:3]
	slice3 := array[:3]
	fmt.Println("参照(Data) ", slice1, slice2, slice3)
	fmt.Println("長さ(Len)  ", len(slice1), len(slice2), len(slice3))
	fmt.Println("容量(Cap)  ", cap(slice1), cap(slice2), cap(slice3))
}

// -> 参照(Data)  [A B C D E] [B C] [A B C]
//    長さ(Len)   5 2 3
//    容量(Cap)   5 4 5
```

### 容量(capacity)

- スライス全体の容量を表す。
- append()で参照元の容量を越すと、倍の容量になる

## make()関数

- 配列とスライスを同時に作成することができる
- マップやチャネルを作成する時にも利用される

`make([]配列の型, 長さ [,容量])`

```go
func main() {
	slice1 := make([]int, 3)
	slice2 := make([]int, 3, 5)
	fmt.Println(slice1, slice2)
	fmt.Println(len(slice1), len(slice2))
	fmt.Println(cap(slice1), cap(slice2))
}

// -> [0 0 0] [0 0 0]
//  3 3
//  3 5
```

## append()関数

- スライスに値を追加する時に使用する
- 追加することはできるが、削除することはできない。

```go
func main() {
	slice1 := make([]int, 3, 5)
	slice1 = append(slice1, 100, 200)
	fmt.Println(slice1, len(slice1), cap(slice1))

	slice2 := make([]int, 2)
	slice2[0] = 1000
	slice2[1] = 2000
	fmt.Println(slice2, len(slice2), cap(slice2))

	slice3 := append(slice1, slice2...)
    // slice1の方にslice2を追加するイメージ
    // 容量もslice1に合わせた形になるため、5*2の10になる
	fmt.Println(slice3, len(slice3), cap(slice3))
}

// -> [0 0 0 100 200] 5 5
//  [1000 2000] 2 2
//  [0 0 0 100 200 1000 2000] 7 10
```

## copy()関数

- スライスの値をコピーすることができる<br>
※下限や上限を設定すれば、コピーする部分を指定することができる

```go
func main() {
	slice1 := []int{100, 200}
	slice2 := []int{201, 202, 203, 204}
	fmt.Println(slice1, slice2)

	copyCount := copy(slice2, slice1)
    // slice2にslice1をコピーするイメージ
    // copyCountはコピーした要素を入れた変数のみ。変数を宣言しなくてもコピーはできる
	fmt.Printf("%v コピーした要素の数=%d \n", slice2, copyCount)
}

// -> [100 200] [201 202 203 204]
//    [100 200 203 204] コピーした要素の数=2
```
```go
func main() {
	slice1 := []int{100, 200}
	slice2 := []int{201, 202, 203, 204}
	fmt.Println(slice1, slice2)

	copyCount := copy(slice2[3:], slice1)
	fmt.Printf("%v コピーした要素数=%d \n", slice2, copyCount)
}

// -> [100 200] [201 202 203 204]
//    [201 202 203 100] コピーした要素数=1
```
```go
func main() {
	slice1 := []int{100, 200}
	slice2 := []int{201, 202, 203, 204}
	fmt.Println(slice1, slice2)

	copyCount := copy(slice2[:1], slice1)
	fmt.Printf("%v コピーした要素数=%d \n", slice2, copyCount)
}

// -> [100 200] [201 202 203 204]
//    [100 202 203 204] コピーした要素数=1
```
```go
func main() {
	slice1 := []int{100, 200}
	slice2 := []int{201, 202, 203, 204}
	fmt.Println(slice1, slice2)

	copyCount := copy(slice2[1:3], slice1)
	fmt.Printf("%v コピーした要素数=%d \n", slice2, copyCount)
}

// -> [100 200] [201 202 203 204]
//    [201 100 200 204] コピーした要素数=2
```

### 値の削除を行う関数はサポートされていないので、関数を自作する必要がある。

```go
func DeleteSlice(slice []int, i int) []int {
	slice = append(slice[:i], slice[i+1:]...)
	newSlice := make([]int, len(slice))
	copy(newSlice, slice)
	return newSlice
}

func main() {
	slice := []int{1, 2, 3, 4, 5}
	fmt.Println(slice, len(slice), cap(slice))
	slice = DeleteSlice(slice, 1) 
  //1番目の値を削除する
	fmt.Println(slice, len(slice), cap(slice))
}

// -> [1 2 3 4 5] 5 5
//    [1 3 4 5] 4 4
```