A Tour of Go メモ 【3】１日目

#　ポインタ、　構造体、　配列、　スライス
[A Tour of Go](https://go-tour-jp.appspot.com/moretypes/1 #)

#ポインタ
[Golangのポインタ渡し初心者を卒業した](https://qiita.com/kotaonaga/items/4a93ec40718c279154f5 #)

```
func main() {
    i, j ;= 10, 200

    # pはiの値を参照する　
    p := &i 

    # iとpのアドレスを取得する
    fmt.Println(&i)
    fmt.Println(&p)

　　 # pが参照している変数、つまり、iを表示する
    fmt.Println(*p)

    # pが参照する変数に21を代入する。つまり、i に 21 を代入する
    *p = 21
    fmt.Println(i)

    #　pはjの値を参照する
    p = &j

    # pが参照する値に”pが参照する値を100で割った値”を代入する。
    # つまり、jに"jを100で割った値"を代入する
    *p　= *p / 100
    fmt.Println(j)
　　　
}
// iを参照したpの値
>10 
//　*pに21を代入した後のi
>21
// iのアドレス
>0xc000100010
// pのアドレス　iを参照して値は同じだが、アドレスは違う
>0xc000102018 
>2
```

#構造体
struct(構造体)はフィールド（field） の集まり

```
type Vertex struct {
  X int
  Y int
}

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

}

> {1, 2}
> 1
> 4
```

#構造体とポインタ

```
type Vertex struct {
	X int
	Y int
}

func main() {
	v := Vertex{1, 2}
  　　　 fmt.Println(v)
        #　pはv(Vertex)を参照する
	p := &v

        # pが参照しているVertexのXに値を代入する
	p.X = 1e9
	fmt.Println(v)
}
> {1 2}
//　ポインタを通して、Xの値が再代入されている
> {1000000000 2}
```

#Struct リテラル

```
type Vertex struct {
	X, Y int
}

var (
        v1 = Vertex{1, 2} 
        
        # Xには1を、Yは０（何も代入されていないので、初期値の０になる）
        v2 = Vertex{X: 1} 

        # X にも Y にも何も代入されていないので、初期値の0になる
        v3 = Vertex{}

        # ちょっとよくわからない・・・
        p  = &Vertex{1, 2}
    
)

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

> {1 2} &{11 2} {1 0} {0 0}
```

#配列
拡張不可なので、append関数で要素を追加できない

```
func main() {
       var a [2]string
       a[0] = "Hello"
       a[1] = "World"
       fmt.Println(a[0], a[1])
       fmt.Println(a)

       primes := [6]int{1,2,3,4,5,6}
       fmt.Println(primes)
}

> Hello World
> [Hello World]
> [2 3 5 7 11 13]

```

#スライス
append関数で要素の追加が可能、つまり、拡張可能
```
func main() { 
        primes := [6]int{2, 3, 5, 7, 11, 13}

        var s []int = primes[1:4]
        fmt.Println(s)
        fmt.Println(primes[:1])
        fmt.Println(primes[2:])
}

> [3 5 7]
> [2 3 ]
> [5 7 11 13]

* スライスした後の配列に値を代入すると元の配列が変わる

func main() {
	names := [4]string{
		"John",
		"Paul",
		"George",
		"Ringo",
	}
	fmt.Println(names)

	a := names[0:2]
	b := names[1:3]
	fmt.Println(a, b)

	b[0] = "XXX"
	fmt.Println(a, b)
	fmt.Println(names)
	fmt.Println(names)
}

> [John Paul George Ringo]
> [John Paul] [Paul George]
> [John XXX] [XXX George]
> [John XXX George Ringo]
//元の配列が変わっている
> [John XXX George Ringo]
```

# スライス　リテラル

```
func main() {
    q := []int{2, 3, 4, 5, 7, 11, 13}
    fmt.Println(q)

    r := []bool{true, false, true, true, false, true}
    fmt.Println(r)

    s := []struct{
        i int
        b bool
    }{
       {2, true}
       {3, false},
       {5, true},
       {7, true},
       {11, false},
       {13, true}
    }
    fmt.Println(s)
}
> [2 3 5 7 11 13]
> [true false true true false true]
> [{2 true} {3 false} {5 true} {7 true} {11 false} {13 true}]
```

#　スライスのlengthとcapacity
length ・・・ 実際に配列に入っている要素の数
capacity ・・・ 確保されているメモリの領域
＊配列とスライスは全くの別物
[Go言語のスライスで勘違いしやすいこところ](https://qiita.com/Kashiwara/items/e621a4ad8ec00974f025 #)

```
func main() {
	s := []int{2, 3, 5, 7, 11, 13}
	printSlice(s)

	// Slice the slice to give it zero length.
	s = s[:5]
	printSlice(s)

	// Extend its length.
	s = s[:6]
	printSlice(s)

	// Drop its first two values.
	s = s[2:]
	printSlice(s)
	
	s = s[:5]
	printSlice(s)
	
	s = append(s, 4)
	printSlice(s)
}

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

> len=6 cap=6 [2 3 5 7 11 13]

//要素を一つ削る、しかし、capacityは減っていない
> len=5 cap=6 [2 3 5 7 11]

//長さを戻すと削ったはずの要素が復活する
> len=6 cap=6 [2 3 5 7 11 13]

// ドロップするとlengthもcapacityも減っている
> len=4 cap=4 [5 7 11 13]

//　capacity以上にlengthを伸ばそうとするとエラーになる
> panic: runtime error: slice bounds out of range [:5] with capacity 4

//　capacityを超えて要素を追加しようとすると、capacityが以前の2倍になる
> len=5 cap=8 [5 7 11 13 4]


#sliceの初期値
func main() {
	var s []int
	fmt.Println(s, len(s), cap(s))
	if s == nil {
		fmt.Println("nil!")
	}
}

> [] 0 0
> nil!
```

#スライスとmake
makeを使って、lengthとcapacityを指定して、スライスを生成できる
要素の初期値は0

```

func main() {
	a := make([]int, 5)
	printSlice("a", a)

	b := make([]int, 0, 5)
	printSlice("b", b)

	c := b[:2]
	printSlice("c", c)

	d := c[2:5]
	printSlice("d", d)
}

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

```
#　スライスの中にスライス

```
import (
	"fmt"
       // 文字列の操作
	"strings"
)

func main() {
	// Create a tic-tac-toe board.
	board := [][]string{
		[]string{"_", "_", "_"},
		[]string{"_", "_", "_"},
		[]string{"_", "_", "_"},
	}
	fmt.Println(board)

	board[0][0] = "X"
	board[2][2] = "O"
	board[1][2] = "X"
	board[1][0] = "O"
	board[0][2] = "X"

	for i := 0; i < len(board); i++ {
        
　　　　　　　　// スライス内の要素を" "でつないで出力
　　　　　　　　fmt.Printf("%s\n", strings.Join(board[i], " "))
	}

}

> [[_ _ _] [_ _ _] [_ _ _]]
> X _ X
> O _ X
> _ _ O
```