Golang チュートリアル その３

##概要
「処理が速い」「並行処理」が得意ということから、
今後大規模webサービスなどで重宝されると思いましたので、
学習していきたいと思います。

今回は、ポインタなどを見ていきたいと思います。

##参考サイト
以下を実施してみました。

[Welcome to a tour of Go](https://go-tour-jp.appspot.com/moretypes/1)

##環境
GoogleChrome
※ブラウザ操作だけで学習できるため、　エディタを用意する必要がありません。
※私は、ローカルにCentOS8環境を用意して、チュートリアルを行います。
※Goインストール手順です。よろしければ、ご活用ください。
[CentOS8へのGo言語インストール手順](https://qiita.com/tomotomo3/items/38e7fed248278a3295b9)

##ポインタ

ポインタは値のメモリアドレスを指します。

```go:pointers.go
package main

import "fmt"

func main() {
	i, j := 42, 2701

	//iのメモリアドレスを取得
	p := &i
	//「*」をつけることをポインタで取得した変数の値を出力
	fmt.Println(*p)
	//出力している値を上書き
	*p = 21
	//上書きしたため、iの値が変更されている
	fmt.Println(i)

	//jのメモリアドレスを取得
	p = &j
	//「*」をつけることをポインタで取得した変数の値を出力
	fmt.Println(*p)
	//出力している値を上書き
	*p = *p / 37
	//上書きしたため、jの値が変更されている
	fmt.Println(j)
}

//実行
go run pointers.go

//実行結果
42
21
2701
73
```

##Structs

struct (構造体)は、フィールド( field )の集まりです。

```go:structs.go

package main

import "fmt"

type Vertex struct {
	X int
	Y int
}

func main() {
	fmt.Println(Vertex{1, 2})
}

//実行
go run structs.go

//実行結果
{1 2}
```

 - Struct Fields

structのフィールドは、ドット( . )を用いてアクセスする。

```go:struct-fields.go

package main

import "fmt"

type Vertex struct {
	X int
	Y int
}

func main() {
	v := Vertex{1, 2}
	//Xフィールドへアクセスし、代入
	v.X = 4
	//代入した値が反映されている
	fmt.Println(v.X)
}

//実行
go run struct-fields.go

//実行結果
4
```

 - Pointers to structs

structのフィールドは、structのポインタを通してアクセスすることもできます。

フィールドXを持つstructのポインタ p がある場合、フィールド X にアクセスするには (*p).X のように書くことができます。 
しかし、この表記法は大変面倒ですので、Goでは代わりに p.X と書くこともできます。

```go:struct-pointters.go

package main

import "fmt"

type Vertex struct {
        X int
        Y int
}

func main() {
        v := Vertex{1, 2}
        //structsをポインタに代入
        p := &v
        //structsのXフィールドに値を代入
        p.X = 1e9
        fmt.Println(v)
}
```

##structリテラル

structリテラルは、フィールドの値を代入することで新しいstructの初期値の割り当てを行っている。

Name: 構文を使って、フィールドの一部だけを列挙することができます
(この方法でのフィールドの指定順序は関係ありません)。 
※例： X: 1 として X だけを初期化など

& を頭に付けると、新しく割り当てられたstructへのポインタを戻します。

```go:struct-literals.go

package main

import "fmt"

type Vertex struct {
        X, Y int
}

var (
        //値を代入することで新しいstructの初期値の割り当てを行う
        v1 = Vertex{1, 2}
        //Xだけ初期値割り当てを行う
        v2 = Vertex{X: 1}
        //初期化
        v3 = Vertex{}
        //&を頭に付けると、新しく割り当てられたstructへのポインタを戻す
        p  = &Vertex{1, 2}
)

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

//実行
go run struct-literals.go

//実行結果
{1 2} &{1 2} {1 0} {0 0}
```

##配列（Arrays）

[n]T型で表す。
T型の配列にn個まで変数を入れられるという意味になります。

```go:array.go

package main

import "fmt"

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

	primes := [6]int{2, 3, 5, 7, 11, 13}
	fmt.Println(primes)
}

//実行
go run array.go

//実行結果
Hello World
[Hello World]
[2 3 5 7 11 13]
```

##スライス（Slices）

スライスは可変長です。
より柔軟な配列と見なすこともできます。 
実際には、スライスは配列よりもより一般的とのことです。

[]T型と表す。
T型のスライスという意味になります。

コロンで区切られた二つのインデックス low と high の
境界を指定することによってスライスが形成されます

>例：a[low : high]

```go:slices.go

package main

import "fmt"

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

        //1番目の値から4番目の値の間を取得
        //1番目は含む・4番目は含まない
        var s []int = primes[1:4]
        fmt.Println(s)
}

//実行
go run slices.go

//実行結果
[3 5 7]
```

 - スライスは配列への参照のようなもの

スライスはどんなデータも格納しておらず、
単に元の配列の部分列を指し示しています。

スライスの要素を変更すると、
その元となる配列の対応する要素が変更されます。

同じ元となる配列を共有している他のスライスは、
それらの変更が反映されます。

```go:slice-pointers.go

package main

import "fmt"

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)
}

//実行
go run slice-pointers.go

//実行結果
[John Paul George Ringo]
[John Paul] [Paul George]
[John XXX] [XXX George]
[John XXX George Ringo]
```

 - スライスのリテラル(初期値割り振りの認識）

・配列リテラル
[3]bool{true, true, false}

・スライスリテラル
[]bool{true, true, false}

```go:slice-literals.go

package main

import "fmt"

func main() {
	q := []int{2, 3, 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)
}

//実行
go run slice-literals.go

//実行結果
[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 )

スライスの長さ：スライスに含まれる要素の数。
スライスの容量：スライスの最初の要素から数えて、元となる配列の要素数。

```go:slice-len-cap.go

package main

import "fmt"

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

        //スライスの長さを0にする
        s = s[:0]
        printSlice(s)

        //スライスの長さを伸ばす
        s = s[:4]
        printSlice(s)

        //スライスの値を削除
        s = s[2:]
        printSlice(s)
}

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

//実行
go run slice-len-cap.go

//実行結果
len=6 cap=6 [2 3 5 7 11 13]
len=0 cap=6 []
len=4 cap=6 [2 3 5 7]
len=2 cap=4 [5 7]
```

 - スライスのゼロ値

スライスのゼロ値は nil です。
nil スライスは 0 の長さと容量を持っており、
何の元となる配列も持っていません。
※宣言するだけの時に使用する認識

```go:nil-slices.go

package main

import "fmt"

func main() {
	var s []int
	fmt.Println(s, len(s), cap(s))
	if s == nil {
		fmt.Println("nil!")
	}
}

//実行
go run nil-slices.go

//実行結果
[] 0 0
nil!
```

 - スライスは、組み込みのmake関数を使用して作成

動的サイズの配列を作成する方法です。
make関数はゼロ化された配列を割り当て、その配列を指すスライスを返す。
※make関数が対応する型はslice,map,chanelのみ
※上記は、[Goのnew関数とmake関数の違いを解説する](https://katuo-ai.com/go-new-make)参照

```go:making-slices.go

package main

import "fmt"

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)
}

//実行
go run making-slices.go

//実行結果
a len=5 cap=5 [0 0 0 0 0]
b len=0 cap=5 []
c len=2 cap=5 [0 0]
d len=3 cap=3 [0 0 0]
```

 - Slices of slices

スライスは、他のスライスを含む任意の型を含むことができる。

```go:slices-of-slices.go

package main

import (
	"fmt"
	"strings"
)

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

	// The players take turns.
	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], " "))
	}
}

//実行
go run slices-of-slices.go

//実行結果
X _ X
O _ X
_ _ O
```

 - スライスへ新しい要素を追加

Goの組み込みの append を使います。

```go:append.go

package main

import "fmt"

func main() {
        var s []int
        printSlice(s)

        s = append(s, 0)
        printSlice(s)

        s = append(s, 1)
        printSlice(s)

        s = append(s, 2, 3, 4)
        printSlice(s)
}

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

//実行
go run append.go

//実行結果
len=0 cap=0 []
len=1 cap=1 [0]
len=2 cap=2 [0 1]
len=5 cap=6 [0 1 2 3 4]
```

##Range

for ループに利用する range は、スライスや、マップ( map )を
ひとつずつ反復処理するために使います。

スライスをrangeで繰り返す場合、rangeは反復毎に2つの変数を返します。 
1つ目の変数はインデックス( index )で、2つ目はインデックスの場所の要素のコピーです。

```go:range.go

package main

import "fmt"

var pow = []int{1, 2, 4, 8, 16, 32, 64, 128}

func main(){
        for i, v := range pow{
                fmt.Printf("2**%d = %d\n", i,v)
        }
}

//実行
go run range.go

//実行結果
2**0 = 1
2**1 = 2
2**2 = 4
2**3 = 8
2**4 = 16
2**5 = 32
2**6 = 64
2**7 = 128
```

 - Range continued

インデックスや値は、 " _ "(アンダーバー) へ代入することで捨てることができます。

※ソースは一部変更しております。

```go:range-continued.go

package main

import "fmt"

func main(){
        pow := make([]int, 10)

        for i := range pow {
                pow[i] = 1 << uint(i)
                fmt.Println(pow)
        }

        for _, value := range pow{
                fmt.Printf("%d\n", value)
        }
}

//実行
go run range-continued.go

//実行結果
[1 0 0 0 0 0 0 0 0 0]
[1 2 0 0 0 0 0 0 0 0]
[1 2 4 0 0 0 0 0 0 0]
[1 2 4 8 0 0 0 0 0 0]
[1 2 4 8 16 0 0 0 0 0]
[1 2 4 8 16 32 0 0 0 0]
[1 2 4 8 16 32 64 0 0 0]
[1 2 4 8 16 32 64 128 0 0]
[1 2 4 8 16 32 64 128 256 0]
[1 2 4 8 16 32 64 128 256 512]
1
2
4
8
16
32
64
128
256
512
```

##Maps
map はキーと値とを関連付けます。

マップのゼロ値は nil です。 nil マップはキーを持っておらず、
またキーを追加することもできません。
make 関数は指定された型のマップを初期化して、使用可能な状態で返します。

```go:maps.go

package main

import "fmt"

type Vertex struct{
        Lat, Long float64
}

var m map[string]Vertex

func main(){
        m = make(map[string]Vertex)
        m["Bell Labs"]  = Vertex{
                40.68433, -74.39967,
        }
        fmt.Println(m["Bell Labs"])
}

//実行
go run maps.go

//実行結果
{40.68433 -74.39967}
```

 - Map literals

mapリテラルは、structリテラルに似ていますが、 キー ( key )が必要です。

```go:map-literals.go

package main

import "fmt"

type Vertex struct {
	Lat, Long float64
}

var m = map[string]Vertex{
	"Bell Labs": Vertex{
		40.68433, -74.39967,
	},
	"Google": Vertex{
		37.42202, -122.08408,
	},
}

func main() {
	fmt.Println(m)
}

//実行
go run map-literals.go

//実行結果
map[Bell Labs:{40.68433 -74.39967} Google:{37.42202 -122.08408}]
```

 - Map literals continued

もし、mapに渡すトップレベルの型が単純な型名である場合は、
リテラルの要素から推定できますので、その型名を省略することができます。

```go:map-literals-continued.go

package main

import "fmt"

type Vertex struct {
	Lat, Long float64
}

var m = map[string]Vertex{
	"Bell Labs": {40.68433, -74.39967},
	"Google":    {37.42202, -122.08408},
}

func main() {
	fmt.Println(m)
}

//実行
go run map-literals-continued.go

//実行結果
map[Bell Labs:{40.68433 -74.39967} Google:{37.42202 -122.08408}]
```

 - Mapsの操作

■m へ要素(elem)の挿入や更新の場合
m[key] = elem

■要素の取得:
elem = m[key]

■要素の削除:
delete(m, key)

■キーに対する要素が存在するかどうか
※2つの目の値で確認します

elem, ok = m[key]
※もし、 m に key があれば、変数 ok は true となり、
　存在しなければ、 ok は false となります。

```go:mutating-maps.go

package main

import "fmt"

func main() {
	m := make(map[string]int)

	//挿入
	m["Answer"] = 42
	fmt.Println("The value:", m["Answer"])

	//更新
	m["Answer"] = 48
	fmt.Println("The value:", m["Answer"])

	//削除
	delete(m, "Answer")
	fmt.Println("The value:", m["Answer"])

	//検索
	v, ok := m["Answer"]
	fmt.Println("The value:", v, "Present?", ok)
}

//実行
go run matating-maps.go

//実行結果
The value: 42
The value: 48
The value: 0
The value: 0 Present? false
```

##関数（Function values）

関数も変数です。他の変数のように関数を渡すことができます。
関数値( function value )は、関数の引数に取ることもできますし、戻り値としても利用できます。

```go:function-values.go

package main

import (
	"fmt"
	"math"
)

func compute(fn func(float64, float64) float64) float64 {
	return fn(3, 4)
}

func main() {
	hypot := func(x, y float64) float64 {
		return math.Sqrt(x*x + y*y)
	}
	fmt.Println(hypot(5, 12))

	fmt.Println(compute(hypot))
	fmt.Println(compute(math.Pow))
}

//実行
go run function-values.go

//実行結果
13
5
81
```

 - Function closures

Goの関数は クロージャ( closure ) です。 
クロージャは、それ自身の外部から変数を参照する関数値です。 
この関数は、参照された変数へアクセスして変えることができ、
その意味では、その関数は変数へ"バインド"( bind )されています。

```go:function-closures.go

package main

import "fmt"

func adder() func(int) int {
	sum := 0
	return func(x int) int {
		sum += x
		return sum
	}
}

func main() {
	pos, neg := adder(), adder()
	for i := 0; i < 10; i++ {
		fmt.Println(
			pos(i),
			neg(-2*i),
		)
	}
}

//実行
go run function-closures.go

//実行結果
0 0
1 -2
3 -6
6 -12
10 -20
15 -30
21 -42
28 -56
36 -72
45 -90
```

##まとめ

次回はメソッドなどを見ていきたいと思います。