🔥

Goが好きです。

に公開

はじめに

私は、業務で2年ほどGoを書いています。
私が個人的にGoについて気に入っている点を13個紹介したいと思います。
他の言語との違いや、具体的なソースコード、コマンドも提供していますので、ぜひ試してみてください。

Goとは?

https://en.wikipedia.org/wiki/Go_(programming_language)

Go言語は、2007年ごろにGoogleのエンジニア(Robert Griesemer、Rob Pike、Ken Thompson)によって開発が始まり、2009年にオープンソース化された経緯を持ちます。
その設計思想は、複雑化するソフトウェア開発において「シンプルさ」と「効率性」を追求することにあります。
従来の言語が持つ冗長な記述や複雑な機能の代わりに、Goは読みやすく保守しやすいコードを書くためのシンプルな文法と、わかりやすい型付けを採用しました。
また、現代のマルチコア環境での並行処理の需要に応えるため、goroutineやchannelという革新的な並行処理モデルを導入し、従来のスレッド管理の煩雑さを解消しています。
さらに、Goは内蔵ツールチェーン(go fmt、go build、go test、go doc)や充実した標準ライブラリを持つことで、統一された開発環境と高い実行効率を実現。
Googleという大企業の支援背景も、実運用に耐える堅牢性やクロスプラットフォーム対応を可能とし、従来の言語の複雑性やパフォーマンス問題を解決するための新たな選択肢として誕生しました。

1. シンプルで直感的な文法

Go言語は、設計当初からシンプルさと分かりやすさが重視されています。

他の言語との違い:

  • JavaやC++は冗長な記述が求められることが多いのに対して、Goは必要最小限の構文要素で記述できるため、コードの可読性・保守性が向上します。
  • セミコロン(;)は文末に自動的に挿入されるため、プログラマーが明示的に記述する必要がありません。

ソースコード例:

package main

import "fmt"

func main() {
    // 明確な構造でシンプルに記述
    fmt.Println("Hello, Go!")
}

2. 並行処理モデルの画期性

Goの大きな特徴の一つは、軽量なスレッド「goroutine」および通信機構としての「channel」を活用した並行処理モデルです。

他の言語との違い:

  • JavaやPythonなどではスレッドやプロセスの管理が比較的複雑で、並行性を実現するために外部のライブラリやフレームワークが必要な場合が多いですが、Goは組み込みでシンプルな並行処理手法を提供しています。

ソースコード例:

package main

import (
    "fmt"
    "time"
)

func worker(id int, ch chan string) {
    time.Sleep(time.Second) // 擬似的な処理時間
    ch <- fmt.Sprintf("Worker %d finished", id)
}

func main() {
    ch := make(chan string)

    // goroutineを生成して並行処理を実行
    for i := 1; i <= 3; i++ {
        go worker(i, ch)
    }

    // channelから結果を受け取る
    for i := 1; i <= 3; i++ {
        result := <-ch
        fmt.Println(result)
    }
}

3. クロスプラットフォーム対応とクロスコンパイルの容易さ

Goは主要なOS(Windows、macOS、Linux)だけでなく、さまざまなCPUアーキテクチャ向けのクロスコンパイルがとても容易です。

他の言語との違い:

  • 多くの言語ではプラットフォームごとに環境設定や再ビルドが必要となる場合が多いが、Goでは環境変数を設定するだけで別のプラットフォーム向けのバイナリが簡単に生成できます。

コマンド例:

# Linux/amd64向けにWindowsマシンからビルドする場合
SET GOOS=linux
SET GOARCH=amd64
go build -o myapp_linux

(※Unix系シェルの場合は GOOS=linux GOARCH=amd64 go build -o myapp_linux と記述します)

4. 充実した標準ライブラリ

Goはネットワーク通信、暗号化、入出力、文字列処理など、日常的に使われる機能をほとんどカバーする充実した標準ライブラリを備えています。

他の言語との違い:

  • 例えば、Pythonは豊富なライブラリが存在するが、外部パッケージへの依存が多くなる場合があります。一方、Goでは標準ライブラリだけで多くの機能を実現できるため、サードパーティ依存を最小限に抑えることが可能です。

ソースコード例(HTTPサーバーの実装):

package main

import (
    "fmt"
    "net/http"
)

func helloHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hello, World!")
}

func main() {
    http.HandleFunc("/", helloHandler)
    fmt.Println("Starting server on :8080")
    http.ListenAndServe(":8080", nil)
}

5. 静的型付けによる型安全性

Goは静的型付けの言語であり、コンパイル時に型チェックが行われるため、実行前に多くの潜在的なエラーを検出できます。

他の言語との違い:

  • 動的型付けの言語(例:Python、Ruby)と比べ、型に関するエラーが少なく、より堅牢なコードが実現できます。また、型推論(:=構文)により、記述もシンプルでありながら型安全性が保たれます。

ソースコード例:

package main

import "fmt"

func main() {
    // 型推論による変数宣言(型はintと推論される)
    count := 10
    fmt.Printf("count is of type %T\n", count)
}

6. 内蔵ツールチェーンの一体感

Goは開発効率を高める一連のツールを標準で提供しています。

他の言語との違い:

  • JavaではMavenやGradle、Pythonではpip、pytestなど複数のツールに依存することが多いですが、Goでは一つのコマンド群でコードの整形、ビルド、テスト、ドキュメント生成がシームレスに行えます。

コマンド例:

# コードの自動整形
go fmt

# プログラムのビルド
go build

# テストの実行(ユニットテスト、ベンチマークテスト)
go test -v

# ドキュメントの生成(閲覧用)
go doc fmt

7. シンプルなエラーハンドリング

Goのエラーハンドリングは、例外処理に依存せず、戻り値としてのエラーをチェックするシンプルなモデルを採用しています。

他の言語との違い:

  • JavaやC++は例外処理を多用しますが、Goは明示的なエラーチェックを行うことで、エラー発生箇所がコード中で明確になり、デバッグが容易です。

ソースコード例:

package main

import (
    "fmt"
    "os"
)

func main() {
    file, err := os.Open("nonexistent.txt")
    if err != nil {
        fmt.Println("Error opening file:", err)
        return
    }
    defer file.Close()
    // ファイル処理
}

8. シンプルなパッケージ管理

Go Modules(go mod)は依存関係の管理を簡潔にする仕組みです。

他の言語との違い:

  • JavaScriptのnpmやPythonのpipと比べ、Goはバージョン管理と依存性解決がシンプルで、プロジェクト単位で管理しやすくなっています。

コマンド例:

# プロジェクトルートでモジュールを初期化
go mod init github.com/username/myproject

# 依存パッケージの取得
go mod tidy

9. 組み込みのテストフレームワーク

Goには標準でテストフレームワークが組み込まれており、ユニットテストやベンチマークテストの記述が容易です。

他の言語との違い:

  • 外部ツールなしで、シンプルな関数を書く感覚でテストを記述できるため、品質向上のサイクルが短くなります。

ソースコード例:

// mymath.go
package mymath

// 単純な足し算関数
func Add(a, b int) int {
    return a + b
}
// mymath_test.go
package mymath

import "testing"

func TestAdd(t *testing.T) {
    result := Add(2, 3)
    expected := 5
    if result != expected {
        t.Errorf("Expected %d, got %d", expected, result)
    }
}

// ベンチマークテスト
func BenchmarkAdd(b *testing.B) {
    for i := 0; i < b.N; i++ {
        Add(i, i)
    }
}

実行コマンド例:

go test -v       # ユニットテスト実行
go test -bench=. # ベンチマークテスト実行

10. 静的解析ツールの充実

Goは、静的解析ツールである go vet やサードパーティ製の linter との組み合わせで、ソースコードのバグやスタイルの問題を早期に検出可能です。

他の言語との違い:

  • 静的型付けと合わせ、コンパイル前に多くのエラーを指摘してくれるため、リリース前の品質保証が徹底できます。

コマンド例:

# ソースコードの静的解析
go vet ./...

11. Gopher君が可愛い

[1]

Go言語の公式マスコット「Gopher君」は、コミュニティ内で広く親しまれており、言語自体のブランディングにも一役買っています。

他の言語との違い:

  • マスコットの存在は一見遊び心のようですが、コミュニティ内での認知度向上やドキュメント、イベントなどの統一感に貢献しており、開発者同士の親近感を醸成しています。

12. GoはGoで書かれている

Goのコンパイラやツールチェーンの一部はGo自身で書かれているため、言語仕様や挙動を深く理解したい開発者にとって学習資料や参照のしやすさが向上しています。

他の言語との違い:

  • 例えば、多くの言語のコンパイラはC/C++で書かれており、内部の理解が難しいケースが多いですが、Goは同じ言語で記述されているため、コードリーディングやカスタマイズが比較的容易です。

参考情報:

  • Goのリポジトリ(Go GitHub リポジトリ)では、コンパイラやツールチェーンのソースコードが公開されており、学習や貢献がしやすくなっています。

13. Googleが作っている

他の言語との違い:

  • Googleの巨大なバックアップを受け、実運用での信頼性やサポート体制、エコシステムが充実しています。
  • 開発事例として、DockerやKubernetesなど、多くのプロジェクトがGoで実装されている点からも、その実績が伺えます。

まとめ

脚注
  1. https://reneefrench.blogspot.com/ ↩︎

Discussion