最近 Go言語を個人的に勉強しているのですが、そのときに思ったことを Java と比較しながら書いてみようと思います。
Go言語とは
皆さん、そもそも Go言語って知っていますか?
Go言語はGoogleが開発したオープンソースのプログラミング言語です。「Go」や「Golang」と呼ばれます。
特徴としては、「簡潔な記述ができる」、「軽量な並列処理が可能」などがあげられます。
Go言語は色々なところで利用されており、Web だと API サーバの実装に利用されることが多くなっています。
また、クロスコンパイル(Windows/Mac/Linux 用のコンパイル)が可能であるため、CLI ツールの作成などに利用されることも多々あります。有名どころだと「docker」の CLI なんかが go 言語で作成されています。(先程のリンク先を見てみると、「.go」ファイルがちらほらありますね。)
簡潔な記述ができるとは?
先程特徴で「簡潔な記述ができる」と記載したのですが、この点に関して結構勘違いしやすい点なので、Java と比較しながら少し言及しておきます。
ソースコード(オブジェクト)の比較
例えば”Person”というオブジェクトを作成する場合、Java だと以下のような記述方法になります。
package main;
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public void printName() {
System.out.printf("Name(%s) = %s\n", "String", this.name);
}
public void printAge() {
System.out.printf("Age(%s) = %d\n", "int", this.age);
}
}
public class Main {
public static void main(String[] args) {
Person person = new Person("John Smith",24);
person.printName();
person.printAge();
}
}
次に、Go言語バージョンを見てみます。
package main
import "fmt"
// 構造体(≒クラス)の定義
type Person struct {
name string // 名前。
age int // 年齢。
}
// メソッド定義。大文字始まりが「public」
func (m *Person) PrintName() {
fmt.Printf("Name(%T) = %#v\n", m.name, m.name)
}
func (m *Person) PrintAge() {
fmt.Printf("Age(%T) = %#v\n", m.age, m.age)
}
func main() {
person := Person{ "John Smith", 24 }
person.PrintName()
person.PrintAge()
}
このレベルであれば正直差は有りません。むしろ、Java の方がわかりやすいかもしれません。
ソースコード(WebAPI)の比較
では、次に WebAPI の場合を見てみましょう。まずは Java で SpringBoot を利用した場合。
package com.example.demo;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloControler {
@RequestMapping("/hello")
public String helloworld() {
return "Hello World!";
}
}
うん。”簡単”!
だけどよく考えてみると@RestController
とか@RequestMapping("/hello")
とかって何をやっているんだろう??
これって初学者にとっては直感的ではないし、ライブラリの中身を学ばなきゃいけないし、”簡潔” とは言えないかも??
次に Go 言語の場合です。
package main
import (
"fmt"
"net/http"
)
func main() {
handler := http.NewServeMux()
handler.HandleFunc("/hello", SayHello)
http.ListenAndServe("0.0.0.0:8080", handler)
}
func SayHello(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, `Hello world`)
}
ちょっと見慣れない記載があるかもしれませんが、ぱっと見ただけでだいたい何をやっているかは把握できそうです。
また、ライブラリを利用せずとも簡単に API サーバを作成することができるので、Go 標準ライブラリのみを学べば良い状態です。
比較して見ると、こちらのほうが”簡潔”かな?
アーキテクチャの比較
もう 1 点、WebAPI を作成する際のアーキテクチャも見てみます。
まずは Java の場合です。
Java は Web サービス(今回は Spring)を立ち上げる際には、ほとんどすべての場合で何らかのサーブレットコンテナ(今回は Tomcat)が必要になります。このサーブレットコンテナがあるおかげで、“簡単”にサービスを立ち上げられます。
ただ、このサーブレットコンテナ、技術的に正直難しくないですか?中で何をやっているかわかりにくく、黒魔術のようだなぁと感じます。こういう点も Java は”簡潔”ではない、と感じます。
Java の図と比較すると、ものすごく”簡潔”ですね。
Go 言語単体で必要なことを賄うことができるので、余計なことを考える必要がありません。
ここまで比較して見てみると、Goの「簡潔な記述ができる」という特徴がなんとなく見えてくるのではないでしょうか?
また、「Goは”簡潔”」、「Javaは”簡単”」と比較して覚えておくのも良いでしょう。
Simple(簡潔) vs Easy(簡単) ?
Simple な物事と Easy な物事があったとき、皆さんはどちらを選択しますか?
これは中々に悩みどころなので、指針としてt_wadaさんの以下のスライドを覚えておくとよいかと思います。
Simple は、いろんなものをけずってけずって、最後に到達する、1 つのことをうまくやる、という考え方。でも Easy は、いま目の前にある問題に対してどれだけ手数を減らせるか、という考え方です。
手数を減らすというのは、覚えることを増やす、覚えることが増えることで手数が減る。これが Easy の考え方です。例えば Rails は覚えることが多いほど手数を減らせる。
(中略)
ソフトウェアの構造としては Simple なものの方が望ましいのですが、ソフトウェア企業として開発の勢いは Easy なものを選ぶ方がいいこともあります。この 2 つのどっちを選ぶかは、好みの選択になります。
(引用元:技術選定の審美眼。時代を超えて生き続ける技術と、破壊的な変化をもたらす技術を見極める(後編)。デブサミ2018)
確かに、JavaのSpringは覚えてしまえばEasyに書くことができ、非常に便利です。また、他にもいろいろな機能があるので、その点も便利な1要因となっています。
一方、昨今のバックエンドはWebAPIのみにするような構成においては、SimpleなAPIを作成できるというGoが好まれる傾向があるのかと思います。
作るものやチームの状況によって当然異なりますが、上記を参考にして、Simple(簡潔)かEasy(簡単)のどちらを選択するか判断するのが良さそうです。
まとめ
Go言語とJavaの比較を行いました。
"Simple" or "Easy" に関しては、個人的には保守を長くやってきた経験上、Simpleなものを好む傾向があるなぁと思いました。
Simple/Easy の話は、他にも色々と興味深い話があるので、面白いと感じた方はこちらなども読んでみると良いかもしれません。