【Go】基本文法メモまとめ

# 概要
[A Tour of Go](https://tour.golang.org/)の順番に沿ってGoの基本で個人的に学習したことをまとめています。


| No | 記事 |
|------|---------|
|    1  |   [【Go】基本文法①(基礎)](https://qiita.com/k-penguin-sato/items/1d0e1c6b4bf937996cd3)|
|    2  |   [【Go】基本文法②(フロー制御文)](https://qiita.com/k-penguin-sato/items/31b45fd3914797b654f0)|
|    3  |  [【Go】基本文法③(ポインタ・構造体)](https://qiita.com/k-penguin-sato/items/62dfe0f93f56e4bf9157)|
|    4  |  [【Go】基本文法④(配列・スライス)](https://qiita.com/k-penguin-sato/items/daad9986d6c42bdcde90)|
|    5  |   [【Go】基本文法⑤(Maps・ Range)](https://qiita.com/k-penguin-sato/items/a320072fa09502bde3e9)|
|    6  |    [【Go】基本文法⑥(インターフェース)](https://qiita.com/k-penguin-sato/items/885a61d819cc431304f5)     |
|    7  |     [【Go】基本文法⑦(並行処理)](https://qiita.com/k-penguin-sato/items/5b09fa89d8d231bcdac8)    |
|    8  |   __〜〜【Go】基本文法総まとめ「今ココ」〜〜__     |

# パッケージ
__`パッケージ(package)`ポイント__

- Goのプログラムは`パッケージ(package)`によって成り立っている。
- importを使用する事で必要な`パッケージ(package)`をインポートする事が可能。
- Goでは最初の文字が大文字で始まるものは、外部パッケージから参照が可能(`Exported names`)。
（例えば以下の`Pi`はmathパッケージからエクスポートされたもの。）

__参考コード__

```Golang
package main

import (
    "fmt"
    "math"
)
//import "fmt"
//import "math" の様に個別でもimportが可能

func main() {
   fmt.Println(math.Pi) //=> 3.141592653589793
}
```

# Functions(関数）
Goでは関数は以下の様に定義される。

__参考コード__

```Golang
func  <関数名>([引数]) [戻り値の型] {
    [関数の本体]
}
```
__`Functions(関数)`のポイント__

- 引数の戻り値の型を書く必要がある。(ex1)
- 関数が２つ以上の同種類の引数を伴う場合、以下の様に型の省略する事が可能。(ex2)
- 関数は複数の値を返すことができる。(ex3)

__参考コード__

```Golang
func main() {
	fmt.Println(hello("Hello World")) //=> Hello World
	fmt.Println(hello2("Hello", "World")) //=> Hello World
	fmt.Println(multipleArgs("Hello", "World")) //=> World Hello
}
//ex1:引数の戻り値の型を書く必要がある
func hello(arg string) string{
     return arg
}
//ex2:関数が２つ以上の同種類の引数を伴う際、型の省略する事が可能
func hello2(arg1, arg2 string) string {
     return arg1 + " " + arg2
}
//ex3:関数は複数の値を返すことができる
func multipleArgs(arg1, arg2 string)(string, string){
    return arg2, arg1
}
```

# Variables(変数)
__`Variables(変数)`ポイント__

- `var`によって変数を宣言し、型の明示が必要である。(ex1)
- 初期値を渡した状態で変数を宣言すると型の明示を省略が可能。(ex2)
- 関数内では`:=`を利用することでより短いコードで変数の宣言を行うことが可能。(ex3)

__参考コード__

```Golang
//ex1:`var`によって変数を宣言し、型の明示が必要である。
var lang string 
//※変数に初期値を与えないとゼロ値（Zero values)が設定されます。(数値型には0、bool型にはfalse、string型には""(空の文字列)が与えられる。

//ex2:初期値を渡した状態で変数を宣言すると型の明示を省略が可能。
var lang2 = "Golang"//初期値を渡す。

func main() {
	//ex3:関数内では｀:=`を利用することでより短いコードで変数の宣言を行うことが可能
	lang3 := "JS" 
	fmt.Println(lang, lang2, lang3) //=> Golang JS
}
```
# Constants(定数)
__`Constants(定数)`ポイント__

- 定数は、`const`キーワードを使用して宣言する。
- 定数は、`文字(character)`、`文字列(string)`、`boolean`、`数値(numeric)`のみで使用可能。
- 定数は`:=`を使用して宣言することはできない。

__参考コード__

```Golang
const Num = 2

func main(){
    const Greetings = "Hello World"
    fmt.Println(Greetings) // => Hello World
    fmt.Println(Num) // => 2
}
```
# Forループ

__`Forループ`ポイント__

- 使用時に条件式等を囲む`()`は必要ありませんが処理を囲む`{}`は必要。

__参考コード__

```Golang
func main(){
	sum := 0
	for i := 0; i < 5; i++ {
		sum += i 
	}
	fmt.Println(sum) //=> 10
}
```

# If（条件分岐）
`if`ステートメントは、`for`のように、条件の前に、評価するための簡単なステートメントを書くことができる。（ここで宣言された変数は、`if`のスコープ内だけで有効。）

__参考コード__

```Golang
package main 

import "fmt"

func condition(arg string)string{
  if v := "GO"; arg == v {
    return "This is Golang"
  }else{
    return "This is not Golang"
  }
}
func main(){
    fmt.Println(condition("Swift")) //=> This is not Golang
}
```

# Switch（条件分岐）
__`Switch(条件分岐)`ポイント__

- 選択された`case`だけを実行してそれに続く全ての`case`や`default`は実行されない。
- `switch`の前に何も条件を書かない場合は`switch true`と書くのと同じ。

__参考コード__

```Golang
func main(){
	fmt.Println(condition("Go")) //This is Go
}

func condition(arg string) string{
	switch arg {
	case "Ruby":
		return "This is Ruby"
	case "Go": //これ以降のcaseやdefaultは実行されない。
		return "This is Go"
    case "JS":
        return "This is JS"
	default:
		return "I don't know what this is"
	}
}
```

# Defer（遅延実行）
`defer`へ渡した関数の実行を呼び出し元の関数の終わり(returnする)まで遅延させる。

__`Defer(遅延実行)`ポイント__

- deferへ渡した関数が複数ある場合、その呼び出しはスタックされ、新しいデータ→古いデータの順番で実行される。（=最初にdeferされた行が一番最後に実行される。)

__参考コード__

```Golang
package main 

import "fmt"

func main(){
	defer fmt.Println("Golang") //defer1
	defer fmt.Println("Ruby") //defer2
	fmt.Println("JS") 
	//=> JS
	//=> Ruby
	//=> Golang
}
```
# ポインタ
__`ポインタ(pointer)`ポイント__

- ポインタはメモリのアドレス情報のこと。
- Goでは`&`を用いることで変数のアドレスの取得が可能。(ex1)
- `*`を使用する事でポインタを値にとったポインタ変数の宣言が可能。(ex2)
- ポインタ型変数名の前に`*`をつけることで変数の中身へのアクセスが可能。(ex3)

__参考コード__

```Golang
func main(){
	var lang string 
	lang = "Go" 
	//ex1:`&`を用いることで変数のアドレスの取得が可能
	fmt.Println(&lang) //=> 0x1040c128
	
	//ex2:`*`を使用する事でポインタを値にとったポインタ変数の宣言が可能
	var langP *string 
	langP = &lang
	fmt.Println(langP)//=> 0x1040c128
	
	//ex3:ポインタ型変数名の前に`*`をつけることで変数の中身へのアクセスが可能
	fmt.Println(*langP) //=> Go
}
```

# Structs(構造体)

__`Structs(構造体)`ポイント__

- `class`に似た役割を提供する。(関連する変数をひとまとめにする。)
-  `type`と`struct`を使用して定義する。(参考コード① ex1)
-  複数の初期化方法が存在する。(参考コード① ex2)
-  構造体内にメソッド`method`を定義できる。(参考コード② ex3)
-  継承に似た機能として構造体の埋め込みが可能(参考コード③ ex4)

__参考コード①__

```Golang
// ex1: typeとstructを使用して定義する。
type Person struct {
   name string 
   age int
}

func main(){
//ex2:複数の初期化方法が存在する
	//初期化方法①:変数定義後にフィールドを設定する
	var mike Person
	mike.name = "Mike"
	mike.age = 23
	
	//初期化方法②: {} で順番にフィールドの値を渡す
	var bob = Person{"Bob", 35}
	
	//初期化方法③:フィールド名を ： で指定する方法
	var sam = Person{age:89, name: "Sam"}
	
	fmt.Println(mike, bob, sam) //=> {Mike 23} {Bob 35} {Sam 89}
}
```

__参考コード②__

```Golang
//ex3:構造体内にメソッドを定義できる
//普通の関数と違うのはレシーバ引数(下記の「(ele Person)」)の部分だけ。
func(ele Person)intro(arg string) string {
	return arg + " I am" + " " + ele.name
}

func main(){
	bob := Person{"Bob", 85}
	fmt.Println(bob.intro("Hello!")) //=>Hello! I am Bob
}
```

__参考コード③__

```Golang
type Person struct {
	name string 
	age int
} 

func(ele Person)intro(arg string) string {  //Personのメソッド
	return arg + " I am" + " " + ele.name
}

//ex4:継承に似た機能として構造体の埋め込みが可能
  //構造体UserにPersonを組み込む。
type User struct {
	Person
}

func(ele User)intro(arg string) string { //Userのメソッド
	return "User No." + arg + " " + ele.name
}

func main(){
	bob := Person{"Bob", 85}
	
	var user1 User
	//組み込みによりnameの定義が可能
	user1.name = "Bob"
	
	fmt.Println(bob.intro("Hello!")) //=> Hello! I am Bob
	fmt.Println(user1.intro("1")) //=> User No.1 Bob
}
```
# Arrays(配列)
__`Arrays(配列)`ポイント__

- 配列とは、同じ型を持つ値（要素）を並べたもの。(ex1) 
- 複数の宣言方法がある。(ex2)
- 最初に宣言した配列のサイズを変えることはできない。(ex3)

__配列の基本的な宣言方法__

```Golang
① var 変数名 [長さ]型
② var 変数名 [長さ]型 = [大きさ]型{初期値1, 初期値n} 
③ 変数名 := [...]型{初期値１, 初期値n}
```
__参考コード__

```Golang
//ex1:配列とは、同じ型を持つ値（要素）を並べたもの
//ex2:複数の宣言方法がある

//宣言方法(1)
var arr1 [2]string 
//宣言方法(2)
var arr2 [2]string = [2]string{"Golang", "Ruby"}
//宣言方法(3)
var arr3 = [...]string{"Golang", "Ruby"}

func main(){
	arr1[0] = "Golang"
	arr1[1] = "Ruby"
	fmt.Println(arr1, arr2, arr3) //=> [Golang Ruby] [Golang Ruby] [Golang Ruby]
}
```

# Slices(スライス)

__`Slices(スライス)`ポイント__

- 配列とは異なり長さ指定の必要なし。(参考コード① ex1)
- 別の配列から要素を取り出し参照する形での宣言や`make()`を利用した宣言が可能。(参考コード① ex2)
- 配列とは異なり要素の追加が可能。(参考コード① ex3)
- `長さ(length)`と`容量(capacity)`の両方を持っている。(参考コード② ex4)
- 型が一致している場合、他のスライスに代入することが可能。(参考コード② ex5)
- スライスのゼロ値は`nil`。(参考コード② ex6)

__参考コード①__

```Golang
func main(){
	//参照用配列
	var arr[2]string = [2]string{"Ruby","Golang"}
	
	//ex1:配列とは異なり長さ指定の必要なし
	var slice1 []string //スライス(1)
	var slice2 []string = []string{"Ruby", "Golang"} //スライス(2)
     
    //ex2:配列から要素を取り出し参照する形での宣言が可能
	var slice3 = arr[0:2] //スライス(3)
	
    //ex2:make()を利用した宣言が可能
	var slice4 = make([]string,2,2)	//スライス(4)
	
	//ex3:配列とは異なり要素の追加が可能
	//append は新しいスライスを返すことに注意
	slice5 := [] string{"JavaScript"}
    newSlice := append(slice5, "Ruby") //sliceに"Ruby"を追加
	
	fmt.Println(slice1,slice2,slice3,slice4, slice5, newSlice) //=>[] [Ruby Golang] [Ruby Golang] [ ] [JavaScript] [JavaScript Ruby]
}
```

__参考コード②__

```Golang
func main(){
	slice := []string{"Golang", "Ruby"}
	
	//ex4:長さ(length)と容量(capacity)の両方を持っている。
	//長さ(length) は、それに含まれる要素の数
	//容量(capacity) は、スライスの最初の要素から数えて、元となる配列の要素数
	fmt.Println(len(slice)) //=> 2
	fmt.Println(cap(slice)) //=> 2
	
	//ex5:型が一致している場合、他のスライスに代入することが可能。
	var slice2[]string //sliceと同型slice2を作成
	slice2 = slice //sliceをslice2に代入
	fmt.Println(slice2) //=>[Golang Ruby]
	
	//ex6:スライスのゼロ値は nil
	var slice3 []int
    fmt.Println(slice3, len(slice), cap(slice)) //=> [] 0 0

    if slice3 == nil {
        fmt.Println("nil!") //=> nil! 
        //sliceの値がnilの場合にnil!を表示する。
    }
}
```

# Maps(連想配列)

__`Maps(連想配列)`ポイント__

- `Maps(連想配列)`は`キー (key)`というデータを使って要素を指定するデータ構造である。
- 複数の宣言方法が存在する。(参考コード① ex1)
- 初期値を指定しない場合、変数は`nil(nil マップ)`に初期化される。(参考コード① ex2)
- 要素の挿入や削除が行える。(参考コード② ex3)

__参考コード①__

```Golang
func main(){
	//ex1複数の宣言方法が存在する
	
	//①組み込み関数make()を利用して宣言
	//make(map[キーの型]値の型, キャパシティの初期値)
	//make(map[キーの型]値の型)
	
	map1 := make(map[string]string)
	map1["Name"] = "Mike"
	map1["Gender"] = "Male"
	
	//②初期値を指定して宣言
	//var 変数名 map[key]value = map[key]value{key1: value1, key2: value2, ..., keyN: valueN}
	map2 := map[string]int{"Age":25,"UserId":2}
	
	//ex2初期値を指定しない場合、変数はnil(nil マップ)に初期化される
	var map3 map[string]string
	
	fmt.Println(map1, map2, map3) //=>map[Gender:Male Name:Mike] map[Age:25 UserId:2] map[]
}
```

__参考コード②__

```Golang
func main(){
	//ex3:要素の挿入や削除が行える
	
	//連想配列の作成
	var mapEx = map[int]string{1:"Go",2:"Ruby"}
	fmt.Println(mapEx) //=> map[2:Ruby 1:Go]
	
	//要素の挿入や更新
	mapEx[3] = "Javascript"
	fmt.Println(mapEx) //=> map[1:Go 2:Ruby 3:Javascript]
	
	//要素の取得
	fmt.Println(mapEx[2]) //=> Ruby
	
	//要素の削除
	delete(mapEx,3)
	fmt.Println(mapEx) //=> map[2:Ruby 1:Go]
}
```
# Range(`for`の`range`節)

__`Range`ポイント__

- スライスやマップに使用すると反復毎に2つの変数を返す。(ex1)
- スライスの場合、1つ目の変数は `インデックス(index)`で、`2つ目は要素(value)`である。(ex2)
- マップの場合、1つ目の変数は`キー(key)`で、２つ目の変数は`バリュー(value)`である。(ex3)
- インデックスや値は、`_`へ代入することで省略することが可能。(ex4)

__参考コード__

```Golang
//スライスとマップの作成	
var slice1 = []string{"Golang", "Ruby"}
var	map1 = map[string]string{"Lang1":"Golang", "Lang2":"Ruby"}

func main(){
	//ex1:スライスやマップに使用すると反復毎に2つの変数を返す。
	//ex2:スライスの場合、1つ目の変数は `インデックス(index)`で、`2つ目は要素(value)`である。
	for index, value := range slice1{
		fmt.Println(index,value)
		//=> 0 Golang
		//=> 1 Ruby
	}
	
	//ex3:マップの場合、1つ目の変数は`キー(key)`で、２つ目の変数は`バリュー(value)`である。
	for key, value := range map1{
		fmt.Println(key, value)
		//=> Lang1 Golang
		//=> Lang2 Ruby
	}
	
	//ex4:インデックスや値は、 _ へ代入することで省略することが可能。
	
	for _,value := range map1{
		fmt.Println(value)
		//=> Golang
		//=> Ruby
	}
}
```

# Interface(インターフェース)

__`Interface(インターフェース)`ポイント__

- 任意の型が__「どのようなメソッドを実装するべきか」__を規定するためのもの。
- インターフェースの定義の内容は、単なるメソッドリストである。
- オブジェクト指向言語でいうところのポリモーフィズムと同様の機能を実現可能。

__参考コード①__では`Person`と`Person2`という構造体があり、各構造体に`intro()`メソッドが定義されており、各構造体がそれぞれ`intro()`を実行するための`IntroForPerson()`と`IntroForPerson2()`と呼ばれるメソッドを持っている。

__参考コード①__

```Golang
type Person struct {} //Person構造体
type Person2 struct {} //Person2構造体

//Person構造体のメソッドintro()
func (p Person) intro() string{ 
    return "Hello World"
}

//Person2構造体のメソッドintro()
func (p Person2) intro() string{
     return "Hello World"
}

//Person構造体のメソッドintro()を実行するメソッド
func IntroForPerson(arg *Person){
    fmt.Println(arg.intro())
}

//Person2構造体のメソッドintro()を実行するメソッド
func IntroForPerson2(arg *Person2){
    fmt.Println(arg.intro())
}

func main(){
  bob := new(Person)
  mike := new(Person2) 

  IntroForPerson(bob) //=> Hello World
  IntroForPerson2(mike) //=> Hello World
}
```
現状では`IntroForPerson`と`IntroForPerson2`の同じ動きをするメソッドが存在しており冗長である。
そこで、__参考コード②__の様に重複するメソッドを`Interface(インターフェース)`に括り出す事ができる。

__参考コード②__

```Golang
type Person struct {} //Person構造体
type Person2 struct {} //Person2構造体

type People interface{
    intro()
}

func IntroForPerson(arg People) {
     arg.intro();
}

//Person構造体のメソッドintro()
func (p *Person) intro() { 
    fmt.Println("Hello World")
}

//Person2構造体のメソッドintro()
func (p *Person2) intro() {
     fmt.Println("Hello World")
}

func main(){
  bob := new(Person)
  mike := new(Person2) 

  IntroForPerson(bob) //=> Hello World
  IntroForPerson(mike) //=> Hello World
}
```

# goroutine(ゴルーチン)

__`goroutine(ゴルーチン)`ポイント__

- Go言語のプログラムで並行に実行されるもののこと。
- 関数(またはメソッド)の呼び出しの前に`go`を付けると、異なる`goroutine`で関数を実行することが可能。(ex1)
- `runtime.NumGoroutine()`を使用する事で現在起動している`goroutine(ゴルーチン)`の数を知ることが可能。(ex2)

__参考コード__

```Golang
package main 

import( 
 "fmt"
 "log"
 "runtime"
)
func main(){
	fmt.Println("Hello World")
	//ex1:関数(またはメソッド)の呼び出しの前にgoを付けると、異なるgoroutineで関数を実行することが可能。
	go hello()
	go goodMorning()
	//ex2:runtime.NumGoroutine()を使用する事で現在起動しているgoroutine(ゴルーチン)の数を知ることが可能。
	log.Println(runtime.NumGoroutine()) 
	//=> Hello World
	//=> 2009/11/10 23:00:00 3
	//3がgoroutineの数。
	//ここではmain, hello, goodMorningの３つを指す。
}

func hello(){
	fmt.Println("Hello")
}

func goodMorning(){
	fmt.Println("Good Morning")
}
```

# channel(チャネル)
__`channel(チャネル)`ポイント__

- 組み込み関数`make()`を使用する事で生成可能。(参考コード① ex1)
- チャネルオペレータの`<-`を用いる事で値の送受信が可能。(参考コード① ex2)
- 送信が`channel<-value`で受信が`<-channel`(参考コード① ex2+)
- `channel(チャネル)`は値の交換および同期という通信機能を兼ね備えており、ゴルーチンが予期しない状態とならないことを保証する。(参考コード② ex3)

__参考コード①__

```Golang
func main(){
	//ex1:組み込み関数`make()`を使用する事で生成可能。
	ch := make(chan string) 
	
	//ex2:<-を用いる事で値の送受信が可能。
	//ex2+:作成したチャネルchに値を送信。
	go func(){ ch <- "str"}()
	
	//ex2+:チャネルchから値を受信
	msg := <- ch
	fmt.Println(msg) //=>str
}
```

__参考コード②__

```Golang
func main(){
	//ex3:ゴルーチンが予期しない状態とならないことを保証する。

	ch := make(chan bool) //bool型のチャネルchを作成
	
	// ゴルーチンとして以下の関数を起動。
	//完了時にchannelの型であるboolの値を送信する事で、チャネルへ通知。
	go func(){
		fmt.Println("Hello")
		ch <- true // 通知を送信。値は何でも良い(boolの型であれば)
	}()
	
	<- ch //=>Hello  
	// channelの型であるboolの値を受け取るまでの完了待ち。送られてきた値は破棄
}
```