簡潔なGoと簡単なJavaのどちらを選択するか

最近 Go言語を個人的に勉強しているのですが、そのときに思ったことを Java と比較しながら書いてみようと思います。

# Go言語とは

皆さん、そもそも [Go言語](https://go.dev/)って知っていますか?
Go言語はGoogleが開発したオープンソースのプログラミング言語です。「Go」や「Golang」と呼ばれます。

特徴としては、「<font color="red">簡潔な記述ができる</font>」、「軽量な並列処理が可能」などがあげられます。

Go言語は色々なところで利用されており、Web だと API サーバの実装に利用されることが多くなっています。
また、クロスコンパイル(Windows/Mac/Linux 用のコンパイル)が可能であるため、CLI ツールの作成などに利用されることも多々あります。有名どころだと「[docker](https://github.com/docker/cli)」の CLI なんかが go 言語で作成されています。(先程のリンク先を見てみると、「.go」ファイルがちらほらありますね。)

# 簡潔な記述ができるとは?

先程特徴で「<font color="red">簡潔な記述ができる</font>」と記載したのですが、この点に関して結構勘違いしやすい点なので、Java と比較しながら少し言及しておきます。

## ソースコード(オブジェクト)の比較

例えば”Person”というオブジェクトを作成する場合、Java だと以下のような記述方法になります。

```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();
	}
}
```

<br/>
次に、Go言語バージョンを見てみます。

```go:Personオブジェクト(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 を利用した場合。
```java: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!";
 	}
 }
```
うん。<font color="red">”簡単”</font>!
だけどよく考えてみると`@RestController`とか`@RequestMapping("/hello")`とかって何をやっているんだろう??
<font color="red">これって初学者にとっては直感的ではないし、ライブラリの中身を学ばなきゃいけないし、”簡潔” とは言えないかも??</font>

次に Go 言語の場合です。
```go:WebAPI(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`)
}
```
ちょっと見慣れない記載があるかもしれませんが、ぱっと見ただけでだいたい何をやっているかは把握できそうです。
また、<font color="red">ライブラリを利用せずとも簡単に API サーバを作成することができるので、Go 標準ライブラリのみを学べば良い状態</font>です。
比較して見ると、<font color="red">こちらのほうが”簡潔”</font>かな?

## アーキテクチャの比較

もう 1 点、WebAPI を作成する際のアーキテクチャも見てみます。

まずは Java の場合です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202800/70df0e65-f2cb-8405-e3e8-ea7c7ad0f72e.png)
Java は Web サービス(今回は Spring)を立ち上げる際には、ほとんどすべての場合で何らかのサーブレットコンテナ(今回は Tomcat)が必要になります。このサーブレットコンテナがあるおかげで、<font color="red">“簡単”</font>にサービスを立ち上げられます。
<font color="red">ただ、このサーブレットコンテナ、技術的に正直難しくないですか?中で何をやっているかわかりにくく、黒魔術のようだなぁと感じます。こういう点も Java は”簡潔”ではない、と感じます。</font>

次に、Go の場合です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202800/1f43023e-8a93-f9f5-7e79-00dc1250e86e.png)

Java の図と比較すると、ものすごく<font color="red">”簡潔”</font>ですね。
Go 言語単体で必要なことを賄うことができるので、余計なことを考える必要がありません。

ここまで比較して見てみると、Goの「<font color="red">簡潔な記述ができる</font>」という特徴がなんとなく見えてくるのではないでしょうか?
また、「Goは<font color="red">”簡潔”</font>」、「<font color="red">Javaは”簡単”</font>」と比較して覚えておくのも良いでしょう。

# Simple(簡潔) vs Easy(簡単) ?

Simple な物事と Easy な物事があったとき、皆さんはどちらを選択しますか?
これは中々に悩みどころなので、指針としてt_wadaさんの以下のスライドを覚えておくとよいかと思います。
<script async class="speakerdeck-embed" data-slide="32" data-id="e893d56d34364e3fb84e599f5667fd67" data-ratio="1.77777777777778" src="//speakerdeck.com/assets/embed.js"></script>

>Simple は、いろんなものをけずってけずって、最後に到達する、1 つのことをうまくやる、という考え方。でも Easy は、いま目の前にある問題に対してどれだけ手数を減らせるか、という考え方です。
>
>手数を減らすというのは、覚えることを増やす、覚えることが増えることで手数が減る。これが Easy の考え方です。例えば Rails は覚えることが多いほど手数を減らせる。
>(中略)
> <font color="red">ソフトウェアの構造としては Simple なものの方が望ましいのですが、ソフトウェア企業として開発の勢いは Easy なものを選ぶ方がいいこともあります。この 2 つのどっちを選ぶかは、好みの選択になります。</font>

(引用元:[技術選定の審美眼。時代を超えて生き続ける技術と、破壊的な変化をもたらす技術を見極める（後編）。デブサミ2018](https://www.publickey1.jp/blog/18/2018_1.html))

確かに、JavaのSpringは覚えてしまえばEasyに書くことができ、非常に便利です。また、他にもいろいろな機能があるので、その点も便利な1要因となっています。

一方、昨今のバックエンドはWebAPIのみにするような構成においては、SimpleなAPIを作成できるというGoが好まれる傾向があるのかと思います。

作るものやチームの状況によって当然異なりますが、上記を参考にして、Simple(簡潔)かEasy(簡単)のどちらを選択するか判断するのが良さそうです。

# まとめ

Go言語とJavaの比較を行いました。
"Simple" or "Easy" に関しては、個人的には保守を長くやってきた経験上、Simpleなものを好む傾向があるなぁと思いました。
<font color="red">Simple/Easy の話は、他にも色々と興味深い話があるので、面白いと感じた方は[こちら](https://logmi.jp/tech/articles/321962)なども読んでみると良いかもしれません。</font>