Go 言語仕様1（変数、型）

## 概要
複数の言語を扱っていると仕様が混ざるので、まとめておく。

## 内容
- 変数
- 型

## 変数
- 変数定義は２種類

①型を明示的に指定する

```Go
// var 変数名 型
var i int
var s string

// 値を代入
i = 100
s = "Golang"

// 変数宣言時に初期値を代入ももちろん可
var i int = 100
var s string = "Golang"
```

②型指定を省略

```Go
// 変数名 := 値
i := 100
s := "Golang"

// 型指定を省略した場合は、初期値の型が適用される
fmt.Printf("%T\n", i) // int

fmt.Printf("%T\n", s) // string
```
　　

- 複数の変数をまとめて宣言可能

```Go
// 明示的に型指定
var i, ii int

// 明示的に型指定して初期値も代入
var x, y int = 100, 200
fmt.Println(x) // 100
fmt.Println(y) // 200

// 型指定を省略
s, ss := "Golang", "TypeScript"
fmt.Println(s) // Golang
fmt.Println(ss) // TypeScript

// 型が異なる場合は、 var (変数名 型)
var (
  i2 int
  s2 string
)
```
　　

- 型が異なる値の代入は不可

```GO
var i int
i = "Golang"
// cannot use "Golang" (type untyped string) as type int in assignment
```
　　

- 使用していない変数がある場合はエラー

```GO
var i int = 100
fmt.Println(i)

var s string = "Golang"
// s declared but not used
```
　　

- スコープについて

```GO
// 型指定を省略パターンは、関数外で定義不可
i := 100
var s string = "Golang"

func main() {
  fmt.Println(i) // syntax error: non-declaration statement outside function body
  fmt.Println(s) // Golang
}
```
　　
## 型

- int型

```GO
int8   8  bit  -128 ~ 127
int16  16 bit  -32768 ~ 32767
int32  32 bit  -2147483648 ~ 2147483647
int64  64 bit  -9223372036854775808 ~ 9223372036854775807

uint8	8  bit   0 ~ 255
uint16	16 bit   0 ~ 65535
uint32	32 bit   0 ~ 4294967295
uint64	64 bit   0 ~ 18446744073709551615
```
```GO
// 明示的にbit数を指定しなければ環境依存となるが、
var i int = 1

// bit数は同じでも、int と int64 では異なる型とみなされる
var ii int64 = 2
ｆｍｔ.Println(i + ii) // invalid operation: iiiii + iiiiii (mismatched types int64 and int)

// 型変換は可能
iii := int64(i)
ｆｍｔ.Println(i + ii) // 3
```
　　

- float型

```GO
// 型を明示的に指定
var f32 float32 = 1.2

// 型を明示的に指定しない場合は、float64型になる（環境依存ではない）
f := 2.4
fmt.Printf("%T", f) // float64

// 型変換
fmt.Println("%T", float64(f32)) // float64
```
　　

- string型

```GO
// stingは、ダブルクォーテーションで定義する
var s string = "Golang"
fmt.Printf("%V %v\n", s, s) // string Golang

// 文字列内の任意の文字を取得する(byte型で取得される)
fmt.Println(s[0]) // 71
fmt.Println(string(s[0])) // G
```
　　

- byte型

```GO
// スライスで定義する
b := []byte{71, 111}
fmt.Println(b) // [71 111]

// byteを文字列に変換
fmt.Println(string(b)) // Go

// 文字列をbyteに変換
fmt.Println([]byte("Go")) // [71 111]
```
　　

- bool型

```GO
var t bool = true
fmt.Println(t) // true

var f bool = false
fmt.Println(f) //false
```
　　

- 配列

```GO
// GOの配列は、要素数が固定される
var arr [5]int
fmt.Println(arr) // [0 0 0 0 0]

sarr := [2]string{"Golang", "TypeScript"}
fmt.Println(sarr) // [Golang TypeScript]

// 要素数を含めてひとつの型(要素数を変更すると別の型となるため、要素数が後から変更できないイメージ)
fmt.Printf("%T\n", arr) // [5]int

// 値を代入
arr[0] = 1
fmt.Println(arr) // [1 0 0 0 0]

// 要素数を超えた代入はNG
arr[5] = 10 // invalid array index 5 (out of bounds for 5-element array)

// 要素数を省略して宣言する
arr2 := [...]int{10, 20, 30, 40} // ...で要素の数をカウントしてくれる
fmt.Printf("%T %v\n", arr2, arr2) // [4]int [10 20 30 40]

// 値の取り出し
fmt.Println(arr2[2]) // 30
// 指定するindex番号を算出することも可
fmt.Println(arr2[3-1]) // 30

// 要素数を取得する
fmt.Println(len(arr2)) // 4
```
　　

- interface型

```GO
// すべての型と互換性がある
var y interface{}

y = 10
fmt.Printf("%T %v\n", y, y) // int 10
y = "Golang"
fmt.Printf("%T %v\n", y, y) // string Golang
```
　　

- strconvパッケージを使用した、intとstring間の型変換

```GO
// int → string(Atoi)
var s string = "100"
i, _ := strconv.Atoi(s)
fmt.Printf("%T %v\n", i, i) // int 100

// intに変換できない文字列の場合はエラー
var ss string = "Golang"
ii, err := strconv.Atoi(ss)
if err != nil {
  fmt.Println(err) // strconv.Atoi: parsing "Golang": invalid syntax
}

// string → int(Itoa)
var i2 int = 100
s2 := strconv.Itoa(i2) // Itoaは戻り値は一つ
fmt.Printf("%T %v\n", s2, s2) // string 100
```

## 次回
[Go 言語仕様2（関数）](https://qiita.com/R_R/items/d8432ddee83ba35769bc)