[Golang]入門してみて驚いた、PHPやJSとの違い12選

# 1. エラー文が分かりやすい

```golang:Go：誤ったコード
var message int = "Hello, Qiita!"
prinln(message)
```
このコードでは、誤った箇所を2つ残したまま実行しました。
1. 変数messageの型
2. printlnをprinlnとタイポ
その、実行結果が以下です。

```console:実行結果
# command-line-arguments
user/main.go:5: cannot use "Hello, Qiita!" (type string) as type int in assignment
user/main.go:8: undefined: prinln
```
なんと、2つともエラー箇所として、エラー文に反映されています。
そして、エラー文も丁寧！
「Hello, Qiita!」ってそれ、string型じゃね？とまで言ってくれます。

# 2. 変数再代入の際、型が違うとエラーになる
```php5:PHP：型の違う値を変数に再代入
$a = 1;
var_dump($a);
$a = "aaa";
var_dump($a);
```
$aに1を代入して出力。
さらに、$aに"aaa"を再代入して、再出力した場合…

```console:PHP：実行結果
int(1)
string(3) "aaa"
```
しかし、Goだと…

```golang:Go：型の違う値を変数に再代入
b := 2
println(a)
b = "bbb"
println(b)
```

```console:Go：実行結果
# command-line-arguments
./Main.go:6:9: cannot use "bbb" (type string) as type int in assignment
```
型が違うので、再代入できないとのこと。厳格です。

# 3. 複数の変数を、同時にコンソール出力できる

```golang:Go：複数のコンソール出力
a := 1
b := 2
c := 3
println(a,b,c) // => 1 2 3
```
PHPでデバッグしようとした場合、「var_dump」を書きまくるのはあるあるかと思いますが、Goだとめっちゃ簡単。
これで、書きまくった後の消し忘れも心配ない…笑

ちなみに、JavaScriptは同じことが可能です。

```javascript:JS：複数のコンソール出力
var a = 1;
var b = 2;
var c = 3;
console.log(a,b,c); // => 1 2 3
```
# 4. 使わない変数があればエラーになる
JavaScriptやPHPでは

```javascript:JS
var a = 1;
var b = 2;
console.log(a);
```

```php5:PHP
$a = 1;
$b = 2;
var_dump($a);
```
というコードはなんでもないことですが、

```golang:Go
a := 1
b := 2
println(a) // => ./main.go:3:5: b declared and not used
```
Goだとこのようなエラーが出ます。
「変数b使ってねぇぞ」とのこと。

これは、潜在的なバグを無くすための仕様だそうです。
開発時は、変数の仕様を無視して進めがちなので、注意が必要です。

# 5. if文の三項演算子や省略形が使えない
残念ながらGoでは、PHPやJavaScriptではよく出てくる、[if文の省略形や、三項演算子](https://qiita.com/riotam/items/a68c11461a155ca9f999)が使えません。

```golang:Go：if文三項演算子
score := 100
score > 80 ? println("合格！") : ""
// => エラー
```

```golang:Go：if文省略形
score := 100
if score > 80 println("合格！")
// => エラー
```

```golang:Go：普通にif文を書く
score := 100
if score > 80 {
    println("合格！")
}
// => 合格！
```

これも可読性を上げるためみたいですが、…こうなると逆に読みにくいのでは…？なんて思います。笑

# 6. 「null」ではなく「nil」
…これ、なんか慣れるまで「null」って書いてしまいそうです。笑
「null」ではないので、ご注意を！

# 7. ポインタの利用
入門したところで、理解が乏しいかと思いますが、Golangは変数のアドレスが確認できるようです。

ちょっと使い所が分かりませんが、おそらく学習を進めていくと、変数のアドレスが必要になることがあるのでしょう…
とりあえず、PHPやJavaScriptにはない概念ですので、サンプルコードだけ載せておききます。

```golang:Go：ポインタのサンプル
package main
import "fmt"

func main() {
	a := 5
	var pa *int
	pa = &a
	fmt.Println(pa)  // => 0xc0000140c0
	fmt.Println(*pa) // => 5
}
```
ちなみに、好奇心で試したらこれでもできました。
普通こんな書き方はしないのかもですが…

```golang:Go：ポインタの省略版サンプル
package main
import "fmt"

func main() {
	a := 5
	pa := &a
	fmt.Println(pa)  // => 0xc0000140c0
	fmt.Println(*pa) // => 5
}
```

# 8. 関数の返り値には型指定が必須
```golang:Go
package main
import "fmt"

func hi(name string) string{
	msg := "hi!" + name + "さん!"
	return msg
}

func main() {
	fmt.Println(hi("maeda"))
}
```
この関数は単純で、hi関数の中でmsg変数を宣言・確認し、returnしてます。
基本的な書き方は、PHPやJavaScriptと似てますが、1つだけやたらに**異彩を放っている部分**があります。

そうです。
`func hi(name string) string{`
この、引数の後ろのstring型です。

実はこれ、返り値の型指定を行っているそうです。
なんでこんなところ…

ちなみに、この型指定をしないで実行すると、

```console:返り値の型指定なしの場合のエラー
./test.go:6:2: too many arguments to return
	have (string)
	want ()
./test.go:10:16: hi("maeda") used as value
```
このような、エラーが出ます。
「返す引数が多いよ。ほら、引数は1個のはずなのに、返りの方は0個だ。」的な感じです。

# 9. 1つの関数内で2つ以上の値をreturnできる
以下は、2つの引数の値を、反対にして返している処理です。

```golang:Go：返り値2つreturnできる
package main
import "fmt"

func swap(a, b int) (int, int) {
	return b, a
}

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

// => 2 1
```
これは、すごい画期的！
PHPやJavaScriptなら、
「一度、引数の値2つを配列化させて、それを一旦返して…」みたいなことになりがちですが、Goだとめちゃめちゃ簡単です。

ちなみに、3つ以上もいけました。

```golang:Go：返り値3つreturnも可能
package main
import "fmt"

func swap(a, b, c int) (int, int, int) {
	return c, a, b
}

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

// => 3 1 2
```

#10. 配列の宣言・代入がなんかややこしい
たとえばPHPの場合、

```php5:PHP：配列宣言・代入
$a = [10, 20, 30];
```
PHPの場合は。宣言らしい宣言不要で、`[]`とか古い形式だと`array()`で囲ってやると、簡単に配列に代入できました。
非常に分かりやすい。
JavaScriptでも、はじめに「let」や「const」、「var」がつくだけで、基本的に同じです。
しかし、Goだと

```golang:Go：配列の宣言・代入(省略形)
a := [...]int{10, 20, 30}
```
となる。なんか、多いですね。
しかし実はこれ、

```golang:Go：配列の宣言・代入(ちょっと省略形)
a := [3]int{10, 20, 30}
```
↑これの省略形で、さらにこれは、

```golang:Go：配列の宣言と代入
var a[3]int
a[0] = 10
a[1] = 20
a[2] = 30
```
↑これの省略形だそうです。
Goでの配列は、**原則として、宣言時に配列の個数を指定しておく必要がある**ということですね。

ちなみに、一度配列の個数が決まったのに、後から強引に入れようとすると…

```golang:Go：配列宣言と違う添字に代入
package main
import "fmt"

func main() {
	a := [...]int{1, 2, 3} // 配列aは3つと指定されるのに…
	a[3] = 40              // 無理やり4つめに代入してみると…
	fmt.Println(a)
}
```

```console:返り値の型指定なしの場合のエラー
# command-line-arguments
./test.go:6:3: invalid array index 3 (out of bounds for 3-element array)
```
「配列のインデックス3が無効だよ。」とこれまた丁寧なエラー文がでます。
やはり、ここでも厳格なイメージ。

# 11. 配列ではなく、スライスを使う
PHPでは特に、配列を扱いやすい便利なメソッドが多く、とりあえず配列にして…みたいな処理にしがちです。
しかしGoでは、違うそうです。
たとえば

```golang:Go：配列の一部を利用
package main
import "fmt"

func main() {
	a := [...]int{0, 10, 20, 30, 40, 50, 60, 70, 80, 90, ..., 10000} // 「a[1000] = 10000」まであるとする
	fmt.Println(a[5]) // => 50
	fmt.Println(a[6]) // => 60
	fmt.Println(a[7]) // => 70
}
```
↑このようにした場合、
配列aには1000個の値が入っており、`a[5]、a[6]、a[7]`と3回呼び出すことで、これら1000個の値を3回使うことになります。
Goでは、この非効率をよしとしないんですね。
なので、**Go言語では配列の一部または全部を切り出した、スライスという参照型のデータをよく使う**そうです。

 - 配列をスライスして、使う部分だけ切り出しておく。
 - 切り出した値を使って、処理を行うので、使わない値を持たなくて良い。
ということです。

```golang:Go：配列をスライスして利用
package main
import "fmt"

func main() {
	a := [...]int{0, 10, 20, 30, 40, 50, 60, 70, 80, 90, ..., 10000} // 「a[1000] = 10000」まであるとする
	s := a[5:8] // => [50, 60, 70]にスライス。値は3つしかない状態に。
	fmt.Println(s[0]) // => 50
	fmt.Println(s[1]) // => 60
	fmt.Println(s[2]) // => 70
}
```
これによって、先ほどは1000個の値を3回使っていましたが、今回は3個の値を3回使うだけで済んだため、メモリの節約ができました。

# 12.連想配列ではなく、mapというものを使う
Goでは、キーと値のペアで管理する方法を、**map**というものを使って行う。
宣言の仕方等は、[こちら](https://qiita.com/riotam/items/9c871f6e1963380caa2d)で詳しく書いてます。

#さいごに
最後まで読んでいただき、ありがとうございました。
まだまだペーペーながら、PHPやJSの常識で新しいことを学ぶと面白いですね。
また、間違えているところ等あればご連絡頂けると幸いです。

最後までありがとうございました。

# 参考
[Progate](https://prog-8.com)
[ドットインストール](https://dotinstall.com)