Goの概要
Rubyと比べたGoの特徴
Ruby
- インタプリタ言語
- 動的型付け言語
- オブジェクト指向言語
- モノリシックアーキテクチャ、モジューラモノリスの中で使われる(RubyというかRails)
- コードの密度が高く、短く書ける
- Goと比べてコード行数が半分から1/3くらいになる(らしい)
Go
- コンパイラ言語
- 静的型付け言語
- クラスや継承の概念がないがオブジェクト指向プログラミング(っぽいこと)が可能
- 構造体やインターフェースをうまいこと使う
- 正直理解がいまいちなので、ここら辺は別記事でいつか詳しくまとめたい
- マイクロサービスアーキテクチャの中で使われる
- クラウドネイティブ言語※1
- 書いていて冗長でコードが長くなるという人もいるらしい
- 「シンプルで要素が少なく、読みやすく、学びやすいことの裏返し」 by 実用Go言語
※1 クラウドネイティブ
クラウドネイティブは、クラウドコンピューティング環境で最新のアプリケーションを構築、デプロイ、および管理するソフトウェアアプローチです。
https://aws.amazon.com/jp/what-is/cloud-native/
クラウドを活用したアプリケーション開発のアプローチ。このアプローチで開発されたアプリをクラウドネイティブアプリケーションという。
クラウドネイティブアプリケーションは、マイクロサービスと呼ばれる相互に依存する複数の小規模なサービスで構成されるソフトウェアプログラムです。(引用元は上と同様)
この引用を見ると、クラウドネイティブアプリケーションはコンテナを使ったマイクロサービスアーキテクチャを採用するものであると考えられるが、文脈によって意味が変わってくるかも知れない。
クラウドネイティブ化(マイクロサービス)の利点としては
- サービスごとの負荷分散が可能
- ある一つのサービスに障害が起きても、影響を局所化できる
などがあるらしい。
(この辺りの話が色々書いてありそうな本があるので、後々読みたい)
Goの長所
- シンプル
- コンパイルがかなり早い。実行速度が早い
- 並行処理が強い
- Rubyでも並行処理を書くことはできるけど割と面倒
Goの短所
- シンプルすぎて他の言語にはあるのにGoにはないものが多い
- 例外処理 など
- ジェネリクスが以前までなかったが、最近追加されたっぽい
- RubyでいうところのRailsのような強いフレームワークがない
マイクロサービスとGo
- httpサーバー機能がデフォルトで実装されている
- goroutine という軽量スレッドのおかげで並行処理が最適化される
これらの特徴に加えて文法もシンプルなので他の言語と比べて簡単にマイクロサービス実装可能
https://jp.quora.com/Goがマイクロサービスと相性が良いと言われているの
その他参考
Rubyとの違いを意識しながらTour of Goやってみた
細かい内容には触れず、「へぇ〜Goではそうやって書くんだ〜」と思ったところを軽く書いてみる。
戻り値を複数持てる
func swap(x, y string) (string, string) { return y, x }
戻り値に名前をつけることができる(named return value)
func add(x, y int) (sum int) { sum = x + y return }
GoのNamed return valueについてメリデメを考える
変数に初期値を与えずに宣言すると、勝手に初期値が入る(zero values)
var b bool ⇒ false
定数は型の宣言が不要(型がない)
暗黙的な型変換を許さないことによる不便さを解消したい。
var num1 int = 3 var num2 float32 = 1.1 func main() { fmt.Println(num1 + num2) } => invalid operation: a + b (mismatched types int and float32)
普通に3 + 1.1したいだけなのに、型が違うだけで拒否られる
const num1 = 3 const num2 = 1.1 func main() { fmt.Println(num1 + num2) } => 4.1
このように定数の型を定義しなくてもいいことによって、柔軟さが生まれる
簡易文付きif
以下のvalueのようにif文の中でしかない変数を定義できる
func three(num int) string { if value := num % 3; value == 0 { return "3の倍数" } else { return "3の倍数ではない" } } func main() { fmt.Println(three(3)) }
例が雑だが以下のようにvalueを参照できない
func three(num int) string { if value := num % 3; value == 0 { "3の倍数" } else { "3の倍数ではない" } return value; }
switch文でbreakがいらない
上から下にcaseが評価され、条件が一致したらそこで終了
func fruit(f string) string { var value string switch f { case "apple": value = "りんご" default: value = "果物を入力せよ" } return value } func main() { fmt.Printf(fruit("apple")) }
ポインタ
package main import "fmt" func main() { i := 30 fmt.Println(i); // ==> 30 fmt.Println(&i) // ==> 0xc00001a090 p := &i fmt.Println(*p) // ==> 30 *p = 100 fmt.Println(i) }
slices
配列は固定長なのに対して、スライスは可変調。配列よりも一般的に使われているらしい。
package main import "fmt" type Dog struct { Name string Age int } func main() { var slice = []int{1, 2, 3, 4 ,5} fmt.Println(slice[1]) var array = [5]int{1, 2, 3, 4, 5 } var s = array[1:4] fmt.Println(s) }
goの連想配列(ハッシュ)はmap
var m = map[string]int{"age": 28, "height": 175}
組み込み関数のmakeを使っても連想配列を作れる
var l = make(map[string]int) l["hoge"] = 3
methods
型に対してメソッドを定義できる。
package main import "fmt" type Dog struct { Name string Age int } func (a Dog) hello(){ fmt.Printf("My name is %s\n", a.Name) } func main() { d := Dog{Name: "dog", Age: 13} d.hello() }
感想
Rubyだとpメソッドだけで済むのをimport "fmt”; fmt.Printf()とか書くのめんどくさいなあというのが正直な第一印象。 でも触るにつれどんどん「確かにシンプルなのかもなあ」と思ったり。まあチューリアルこなしただけだとまだまだ全然よくわかってないので、とりあえず今後Goで何かしらAPI作ってみるところまでやってみたい。