Go 基本文法【基礎編】

## はじめに
Goプログラムで使われる基本文法を学習したのでまとめておきます。
できるだけ簡潔明瞭に書いたつもりです。これからGoを始める方の参考になれば幸いです。

今回は「基礎」として、Goプログラミングの概念や仕組みを含む以下に関する内容となります。

## 目次
1. [Packages ： パッケージ](#packages--パッケージ)
2. [Exported Names ： 外部パッケージからのエクスポート](#exported-names--外部パッケージからのエクスポート)
3. [Functions ： 関数](#functions--関数)
4. [Variables ： 変数](#variables--変数)
5. [Zero Values ： ゼロ値](#zero-values--ゼロ値)
6. [Basic Types ： 基本型](#basic-types--基本型)
7. [Type Conversions ： 型変換](#type-conversions--型変換)
8. [Constants ： 定数](#constants--定数)
9. [Scope ： スコープ](#scope--スコープ)
10. [参考文献](#参考文献)

## Packages ： パッケージ
Goプログラムは、パッケージで構成されています。
・プログラムのエントリポイント(一番最初に実行)は ```main``` パッケージ
・パッケージ名はインポートパスの最後の要素と同名
　　"math/rand" ⇨ ```package rand```ファイル群の import を行なっている
・パッケージのインポート方法は2種類
　　① "fmt" と "math/rand" パッケージを一括インポート(factored import statement)
　　② "fmt" と "math/rand" パッケージを個別インポート
```golang:main.go
package main

// ①
import (
	"fmt"
	"math/rand"
)

func main() {
    // rand.Intn()で乱数を出力
	fmt.Println("My favorite number is", rand.Intn(10)) // => My favorite number is ランダム値
}
```
```golang:main.go
// ②
import "fmt"
import "math/rand"
```
```fmt```：データの入出力機能がまとめられたパッケージ
https://pkg.go.dev/fmt#pkg-functions
```math```：計算機能がまとめられたパッケージ
https://pkg.go.dev/math

## Exported Names ： 外部パッケージからのエクスポート
Goでは、最初の文字が大文字で始まる名前は```Exported Names```と呼ばれ、外部パッケージからエクスポートされたものです。
・```Pi``` は math パッケージからエクスポートされたもので円周率を示す定数名
```golang:main.go
package main

import (
	"fmt"
	"math"
)

func main() {
    fmt.Println(math.Pi) // => 3.141592653589793
}
```
![スクリーンショット 2023-06-20 15.16.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3427082/04ac6348-35b1-4f9e-ec09-c467211c4576.png)
ちなみに、```math.pi```とパッケージ内でエクスポートされていない(存在しない)名前へアクセスした場合は```undefined: math.pi```エラーとなります。


## Functions ： 関数
関数は0個以上の引数を取ることができます。
関数の定義は以下です。
```golang:
func  <関数名>(引数) 戻り値の型 {
    関数の本体
}
```
引数が複数でそれらが同種類の場合は```x, y int```の通り、<b>型の省略</b>が可能です。

```golang:main.go
package main

import "fmt"

// 引数1つ
func str(i string) string{
     return i
}

// 引数2つ
func add(x, y int) int {
	return x + y
}

func main() {
	fmt.Println(str("Hello World")) // => Hello World
	fmt.Println(add(42, 13)) // => 29
}
```
複数の戻り値を返すことも可能です。

```golang:main.go
package main

import "fmt"

// 文字列を入れ替える関数
func swap(x, y string) (string, string) {
	return y, x
}

func main() {
	a, b := swap("hello", "world")
	fmt.Println(a, b) // => world hello
}
```

## Variables ： 変数
変数の定義は2種類で、<b>明示的な定義</b>と<b>暗黙的な定義</b>があります。
・明示的な定義 ： ```var 変数名 変数の型```
・暗黙的な定義 ： ```変数名 := 変数の値```もしくは```var 変数名 = 変数の値```
　　⇨ <b>型推論</b>が行われ、型指定の必要がない
　　⇨ <b>関数の外では宣言できない</b>

変数の種類は2種類で<b>ローカル変数</b>と<b>パッケージ変数</b>があります。
・ローカル変数 ： 任意の関数の中に定義された変数
・パッケージ変数 ： 関数定義の外部に定義された変数
```golang:main.go
package main

import (
	"fmt"
)

var p = 100 // パッケージ変数

func main() {
    // 明示的な定義
    // 型別に個別宣言
	var a, b, c, d int
	var e string
	a, b, c, d = 1, 3, 5, 7
    e = "golang!"
	fmt.Println(a, b, c, d) // => 1, 3, 5, 7
	fmt.Println(e) // => golang!

    // 複数の型を一括宣言
	var (
		f, g, h, i int
		j string
	)
	f, g, h, i = 2, 4, 6, 8
	j = "hello world"
	fmt.Println(f, g, h, i) // => 2, 4, 6, 8
	fmt.Println(j) // => hello world



	// 暗黙的な定義
	// 個別宣言
	w1 := 1
	x1 := true
	y1 := 12.3
	z1 := "abc"
	fmt.Println(w1, x1, y1, z1) // => 1, true, 12.3, abc
	
	// 一括宣言
	var (
		w2 = 2
		x2 = false
		y2 = 56.7
		z2 = "def"
	)
	fmt.Println(w2, x2, y2, z2) // => 2, false, 56.7, def



    // ローカル変数、パッケージ変数参照
    var l = 50 // ローカル変数
    pl = p + l  // パッケージ変数は参照可能
    fmt.Printf("p=%d\n", p) // => p=150
}
```

## Zero Values ： ゼロ値
変数へ初期値を与えずに宣言すると、<b>ゼロ値</b>が与えられます。
ゼロ値は型によって以下の通りとなります。
・数値型(int,floatなど) ： 0
・bool型 ： false
・string型 ： "" (空文字列)
```golang.main.go
package main

import "fmt"

func main() {
	var i int
	var f float64
	var b bool
	var s string
	fmt.Printf("%v %v %v %q\n", i, f, b, s) // => 0 0 false ""
}
```

## Basic Types ： 基本型
Goで扱われる型の種類です。
・```int``` , ```uint``` , ```uintptr```型は、32-bitシステムでは32 bit、64-bitシステムでは64 bit
・整数の変数が必要な場合、基本的には```int```を使うべし!!!
・変数宣言は、インポートステートメントと同様に、まとめて( factored )宣言可能
```golang
bool

string

int  int8  int16  int32  int64
uint uint8 uint16 uint32 uint64 uintptr

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

float32 float64

complex64 complex128
```

## Type Conversions ： 型変換
静的言語であるGoでは<b>暗黙的な型変換は行われない</b>ので、異なる型の変数への代入はエラーとなります。
```golang:
var i int = 10
var f float32 = i  // => cannot use i (type int) as type float32
```

型変換の定義は以下です。
```golang:
var 変数名 変数後の型 = 変数後の型(変換する値)
```
```golang:
var i uint32 = 1234567890
var f uint8 = uint8(i) // uint32 ⇨ uint8 への型変換
fmt.Println(f)  // => 210（情報が欠落する）
```

## Constants ： 定数
定数は const キーワードを使って変数と同様に宣言します。
・<b>型なし定数(untyped)</b>と<b>型あり定数(typed)</b>の2種類が存在
・文字(character)、文字列(string)、boolean、数値(numeric)のみで使用可能
・```:=```で宣言することはできない
```golang:main.go
package main

import "fmt"

// 型なし定数
const Pi = 3.14

func main() {
	const Constants = "定数"
	fmt.Println("Hello", Constants) // => Hello 定数
	fmt.Println("Happy", Pi, "Day") // => Happy 3.14 Day

	const Truth = true
	fmt.Println("Go rules?", Truth) // => Go rules? true

    // 型あり定数
    const (
        X int64 = -1
        Y float64 = 1.2
    )
    fmt.Println(X, Y) // => -1, 1.2
}
```

## Scope ： スコープ
パッケージに定義された定数、変数、関数などの<b>識別子の1文字目を大文字にする</b>ことで他のパッケージからそれらの値を参照できる。
・スコープ対象は```[スコープ対象のパッケージ名] [インポートパス]```の定義でインポート
・スコープ対象の識別子1文字目が小文字の場合は<b>エラー扱い</b>
```golang:scope_target.go
package scope_target

const (
	MAX = 100
	internal_val = 1
)

func Scope(i int) int {
	return internalAdd(i)
}

func internalAdd(i int) int {
	return i + 1
}
```
```golang:main.go
package main

import (
    "fmt"
	scope_target "go_next_app/test" // scope_target パッケージをインポート
)

func main() {
	// scope_target パッケージで定義された定数、変数、関数を参照(スコープ)
	w := scope_target.MAX
	x := scope_target.internal_val
	y := scope_target.Scope(5)
	z := scope_target.internalAdd(5)

    fmt.Println(w) // => 100
    fmt.Println(x) // => error：「undefined: scope_target.internal_const」
    fmt.Println(y) // => 6
    fmt.Println(z) // => error：「internalFunc not exported by package scope_target」
}
```

## 参考文献
<a href="https://go-tour-jp.appspot.com/">A Tour of Go</a>
<a href="https://pkg.go.dev/std">Standard Library - Go Packages</a>