トップ画像イメージ

Go の学習を開始!!

最近転職した筆者ですが、転職させていただいたおかげで、プライベートの自習時間が増えて大喜びです。

まだまだ Ruby とかも言って、1年くらいしか使ってないのですが、ここいらで静的型付けのコンパイル型言語も学んでおいたほうが、自身の今後にも良い経験になるかな〜と思っておりました。

それでモダンな Go 言語に目をつけたわけですが、

  • go buildでマルチプラットフォームなバイナリファイルを簡単に出力できる(windows でも linux でも!)
  • シンプルな機能を組み合わせて作るという開発思想(Linux の開発思想と似てる)
  • 動的型付けのように記述できる(Ruby から入っているけど、基礎文法は割とすっと入ってきてます)

と、ちょっとしか触っていないのに これはいい!と感じ、早速基本の勉強を初めて見ることにしましたので、今回はそのまとめ的内容となります。

Go の文法でへぇ〜ってなったところ

return で戻り値を省略する

Go で関数を定義する時に、どんな型の引数をもらって、どんな方の戻り値を返すか func の定義の時に決めることができます。

その変数内でreturnすると ↓ のように値を返してくれます。

package main

import "fmt"

func split(sum int) (x, y int) {
	x = sum * 4 / 9
	y = sum - x
  return
  // ↑戻り値で名前をつけた変数を使うと、returnでその値を返してくれる
}

func main() {
	fmt.Println(split(17))
}

変数の宣言色々

package main

import "fmt"

// var宣言ならfuncの外でも宣言化(このpacakge内のグローバルな変数になる)
var i, j int = 1,2

// := (ショートというらしい)はfunc外(グローバルスコープ)では使えない
// i := 1 は↓のようなエラーをコンパイラが教えてくれる
// syntax error: non-declaration statement outside function body

func main() {
  // 変数宣言で初期値を入れると、型を省略できる
  var bool, str, int = true, "test", 3
  short := "short!"
  fmt.Println(i, j, bool,str, int, short)
}

変数のゼロ値

var i intのように変数の宣言だけして、初期値を与えないと、型によってそれぞれの初期値(ゼロ値)が与えられる。

物の本によると「Go においてのnilは指し示す先がない状態」であるとのこと。 つまり、ポインター型の nil は、「メモリのアドレスが設定されてない」状態とのこと。

Go に Null は無く、変数を宣言した時に型に応じたゼロ値(初期値)が代入されるのは、そういった曖昧な状況を許容しないということだと理解した

package main

import "fmt"

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

定数もある

constで定数の宣言もできる。

constには文字、文字列、boolean、数値のみ使えるとのこと。(そりゃ complex の定数はないよなぁ)

pacakge main

import "fmt"

const Pi = 3.14

func main() {
  const World = "世界"
  fmt.Println("Hello", World)
  fmt.Println("円周率:", Pi)
}

switch 文で条件省略

switch文で条件を省略すると、switch trueと書くのと同じらしい。

package main

import (
	"fmt"
	"time"
)

func main() {
  //
	t := time.Now()
	switch {
	case t.Hour() < 12:
		fmt.Println("Good morning!")
	case t.Hour() < 17:
		fmt.Println("Good afternoon.")
	default:
		fmt.Println("Good evening.")
  }

  // ↓と同じことを簡単にかける
  if t.Hour() < 12 {
		fmt.Println("Good morning!")
	} else if t.Hour() < 17 {
		fmt.Println("Good afternoon.")
	} else {
		fmt.Println("Good evening.")
	}

}


Go の繰り返し処理は for 文だけ

Go においては、While 文も、ForEach 文も無く、for文で処理する。

といっても、↓ のように拡張 for 文のように記述することで、ForEach も、While も再現できる。

逆に色々覚える必要がなくていいかも


func main() {
  sum := 0
  // 基本形(所謂for文)
	for i := 0; i < 10; i++ {
		sum += i
	}
  fmt.Println(sum)

  //while文
  for sum < 1000 {
		sum += sum
	}
  fmt.Println(sum)

  // forEach文
  strArray := [5]string{"taro", "jiro", "hanako", "ken", "tom"}
 for i, s := range strArray {
    fmt.Printf("index: %d, name: %s\n", i, s)
  }

  // 無限ループ
  for {
    fmt.Println("無限ループ中")
  }
}

Go のポインター

こちらの記事がわかりやすかった。

自分に飲み込みやすくすごくシンプルに考えると、ポインタは「宣言した変数のデータを格納しているメモリの番地」ということかと。

プログラミング初めたばかりの頃は、str = "test"とかいう変数の宣言・変数への代入している時、この test というデータがどこに保持されているのか考えられなかったけど、 マシンのメモリに格納しているということを普段から念頭においておけば、概念としてはわかりやすい気がする。

開発支援用のツール

goimports

goimports .goファイルで、コードのフォーマットに加え、import文を補完してくれる!!

package main

func main() {
fmt.Println("テスト")
}

//↑のインデントもなく、fmtのインポートもしていないgoファイルを↓に整形してくれる

package main

import "fmt"

func main() {
	fmt.Println("テスト")
}

ちなみに vscode では拡張機能を入れることで、 goimportsの機能を自動で実行してもらうこともできます。

linter としてgo lintもあるので、.go ファイル保存時に自動じっこうするようにしておけば、 色々と捗りそうですね。

gofmtというフォーマットツールもあるけど、こちらのほうがより使えるイメージ・・・(どう違うのか要学習)

余談

  • go run main.goでインタプリタ言語のように実行できるし、Ruby みたいに気軽に触れる
  • 公式が文法や、フォーマットをかっちり決めているので、ルールがしっかりしている
  • 標準パッケージの充実がすごい"net/http"少しだけ触ったけど、nginx やアパッチを立てなくても簡単に、簡単な WebApi 機能が作れた

以上、ほんの触りですが、もっともっと学習していきたいと思います。