Goのエキスパートが教えるGoの魅力、プログラミング基礎入門

上田拓也(@tenntenn)と申します。私はGoogle Developer ExpertでGoを担当しており、Go Conferenceの主催やgolang.tokyoなど各種コミュニティ活動も行っています。また、Goを採用している各社の技術顧問として開発現場にも携わっています。

今回はGoの基礎をご紹介します。私が公開している「Goで家計簿アプリを作ろう」というハンズオンの内容も一部抜粋して解説しているので、Goをはじめたばかりの初心者の方はぜひ参考にしていただけると嬉しいです。

Goの概要

サーバーサイドで使われる言語

最初に、Goの概要をご説明します。Goは2009年11月にGoogleがオープンソースで公開したプログラミング言語です。2020年2月に最新バージョン1.14がリリースされました。バージョンアップは大体半年ごとのペースです。 Goを利用できる領域はサーバーサイドがメインで、Google App Engine for GoというPaaSを使うことができます。これまで著名なOSSがGoで開発されており、代表的なのがDockerやKubernetes、gVisorなどです。

Goを学ぶ理由

Goはこれまで多くの企業のプロダクトで採用されていますが、静的型付け言語である点、文法がシンプルな点がチーム開発に向いているからです。パフォーマンスの良いコードを書きやすいのもメリットです。スタートアップ段階の企業から大手企業の大規模開発まで幅広く対応できる点も、Goが採用されている理由の一つでしょう。

Goの特徴

強力でシンプルな言語設計と文法

Goは非常にコードが書きやすく、冗長な記述は不要です。しかし、暗黙の型変換など曖昧な記述はできなくなっています。Goはシンプルさを大切にしている言語なため、どんどん機能を増やすことで言語を拡張するということありません。そのため、他の言語に慣れ親しんだ方がGoに触れるとシンプルさに驚くかもしれません。

並行プログラミング

これがGoの一番有名な特徴かもしれません。ゴールーチンと呼ばれる軽量なスレッドに近いものがあり、並行プログラミングが簡単に行えます。具体的には、関数呼び出しの前にgoキーワードをつけると、新しいゴールーチンを作り、そこで処理が行われます。

// 関数fを新しいゴールーチンで呼び出す
go f()

並行プログラミングでは、ゴールーチン間のデータのやりとりが難しい点の一つです。しかし、Goの場合はチャネルというデータ形式があり、それを用いて安全にデータをやりとりできるようになっています。

豊富な標準ライブラリ群

Goは、標準ライブラリが充実しています。標準ライブラリだけを用いてHTTPサーバを作れたり、JSONやXML、CSVなどの形式を扱う事ができます。

fmt書式に関する処理など
net/httpHTTPサーバなど
archive, compress圧縮形式など
encodingJSON, XML, CSVなど
html/templateHTMLテンプレート
os, path/filepathファイル操作など

周辺ツールの充実

標準ライブラリと同様、周辺ツールも充実しています。例えば、gofmtというコードフォーマッターが標準で用意されてる事は有名でしょう。gofmtによってコードの書式が一意に決まるため、プロジェクトごと細かなコーディング規約などを設ける必要がありません。

go buildビルドを行うコマンド
go testxxxx_test.goに書かれたテストコードの実行
go doc, godocドキュメント生成
gofmt, goimportsコードフォーマッター
go vet, golintコードチェッカー、リンター
goplsLanguage Server Protocol (LSP) の実装

シングルバイナリ・クロスコンパイル

最後に特徴として挙げたいのは、シングルバイナリとクロスコンパイルです。Goはコードをコンパイルするとシングルバイナリになります。そのため、生成されたバイナリだけあれば実行環境で処理系など用意しなくても実行が可能です。また、クロスコンパイルもできます。例えば、macOSでWindows向けやLinux向けのバイナリをクロスコンパイルするには以下のようにGOOSとGOARCHの2つの環境変数を設定します。

# Windows(32ビット)向けにコンパイル
$ GOOS=windows GOARCH=386 go build

# Linux(64ビット)向けにコンパイル
$ GOOS=linux GOARCH=amd64 go build

※go buildはGoのソースコードをコンパイルするコマンド

Goを触って家計簿アプリを作ってみよう

言語を学ぶにはハンズオンで触ってみるのが一番なので、GitHubにある家計簿アプリの作り方でご紹介している内容を一部抜粋してご説明します。
全部で11のステップがあり、skeletonディレクトリにあるTODOコメントの部分を問いていく形式になっています。答えがわからないときはsolutionディレクトリにある解答を参照できます。

例1:データの入力(STEP02)

STEP02では変数・型や標準パッケージの使い方、fmtパッケージを使った表示と入力について学びます。

<変数>
Goは静的型付け言語なので変数には型があり、実行前に型の不一致を検出できます。この点はGoの良いところです。

変数定義は全てnに100を入れるという定義で、書き方の基本はこちらになっています。

// 変数定義と代入が一緒
var n int = 100

2行に分けると以下になります。

// 変数定義と代入が別
var n int
n = 100

右辺の値から左辺の型が推論できるので、型を省略もできます。

// 型を省略(int型になる)
var n = 100

// varを省略
// 関数内のみでしかできない
n := 100

まとめる場合は以下です。

// まとめる
var (
    n  = 100
    m = 200
)


最初から使える組込み型は以下のようになります。

整数 int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, uintptr, byte, rune
浮動小数点数 float32, float64
複素数complex64, complex128
文字列 string
真偽値 bool
エラー error


Goの変数は「ゼロ値」とよばれる初期値が必ずあるため、どの変数も定義するだけで使えます。

ゼロ値
intやfloat64などの数値 0
string“”
Boolfalse
errornil


<標準パッケージ>
Goのプログラム構成要素はパッケージ、型、関数、変数、定数で、パッケージ同士を組み合わせることでプログラムを作ります。パッケージの種類はmain、標準、サードパーティの3種類です。標準パッケージはGoが最初から用意しているパッケージで、100種類以上存在しています。

例えば以下ではfmtパッケージをインポートしていて、Println関数を呼び出しています。

package main

import "fmt"

func main() {
    fmt.Println("Hello, 世界")
}

下記ではfmt.Print関数とfmt.Println関数の説明をしています。複数の値を渡せるので、デバッグに使うと便利です。複数の値を渡すとスペース区切りで表示されます。

package main

import "fmt"

func main() {
    fmt.Print("Hello, ")             // 改行されない
    fmt.Println("世界")               // 改行される
    fmt.Println("A", 100, true, 1.5) // スペース区切りで表示される
}

fmt.Printf関数はCのprintf関数と似ていて、書式を指定して標準出力します。Cに無い書式もあるため、一度ドキュメントを読むことをおすすめします。

package main

import "fmt"

func main() {
    fmt.Printf("Hello, 世界\n")      // \nで改行する
    fmt.Printf("%d-%s", 100, "偶数") // %dは整数、%sは文字列
}

引数で指定した変数がある場所(ポインタ)に入力したデータを入れるfmt.Scan関数もあります。下記で家計簿で実際に打ちこむ数値の入力が行えます。

package main
import "fmt"
func main() {
    var price int
    fmt.Print("値段>")
    fmt.Scan(&price)
    fmt.Printf("%d円\n", price)
}

STEP02までの内容で、コマンドラインから計簿における値段と品目を入れて記録する部分ができるようになります。

例2:データの記録(STEP03)

STEP03では制御構文や構造体とユーザー定義型、関数を学びます。

<制御構文>
例えばif文ですね。ここはほかの言語とさして変わりはありません。

if x == 1 {
    println("xは1")
} else if x == 2 {
    println("xは2")
} else {
    println("xは1でも2でもない")
}

GoのifがCやJavaと違うのは()が不要な点です。必ず{}で囲む必要があります。{}を改行はできません。

// ()がいらない
if a == 0 {
}
// できない
if a == 0
{
}
// できない
if (a == 0) fmt.Println(a)

条件分岐の前にセミコロンで区切って、代入文を書くことができます。ここで定義した変数はifとelseのブロックで使えます。

// 代入文を書く
if a := f(); a > 0 {
    fmt.Println(a)
} else {
    fmt.Println(2*a)
}

switchには若干Goならではの特徴があります。まずcaseにカンマ区切りでcase 1,2:のように書くことができます。また、breakも省略できます。caseをまたぐ際はfallthroughを使います。

switch a {
case 1, 2:
    fmt.Println("a is 1 or 2")
default:
    fmt.Println("default")
}

あとはCとは違いcaseに式を使えます。大量のif-elseをつなぐよりは見通しが良くなるでしょう。

switch {
case a == 1:
    fmt.Println("a is 1")
}

Goには繰り返しの構文がforしかありません。

// 初期値;継続条件;更新文
for i := 0; i <= 100; i = i + 1 {
}
// 継続条件のみ
for i <= 100 {
}
// 無限ループ
for {
}
// rangeを使った繰り返し
for i, v := range []int{1, 2, 3} {
}

無限ループから抜け出すためのキーワードとしてbreakを用います。

// breakによる無限ループの脱出
func main() {
    var i int
    for {
        if i%2 == 1 {
            break
        }
        i++
    }
}

switchの中でbreakするとswitchがbreakされるので、ラベルをつけてbreakするようにしましょう。

// ラベル指定のbreak
func main() {
    var i int
LOOP:
    for {
        switch {
        case i%2 == 1:
            break LOOP
        }
        i++
    }
}


本記事では、データの入力(STEP02)、データの記録(STEP03)のみ抜粋しましたが、是非、GitHubにある 家計簿アプリの作り方に挑戦してみてください。

Goのおすすめ勉強法

勉強法はいくつかありますが、まずはブラウザ上での公式のチュートリアルを利用することをおすすめします。あとはGoチームが運営しているgo.devで学習教材や事例が紹介されていますね。公式ドキュメントを読んでみるのもいいでしょう。書籍で学ぶ場合は以下がおすすめです。

『プログラミング言語Go』(丸善出版)Alan A.A. Donovan (著), Brian W. Kernighan (著), 柴田 芳樹 (翻訳)

『みんなのGo言語』(技術評論社)松木雅幸、mattn、藤原俊一郎、中島大一、上田拓也、牧大輔、鈴木健太

『Goならわかるシステムプログラミング』(ラムダノート)渋川よしき

『Go言語による並行処理』(オライリージャパン)Katherine Cox-Buday (著), 山口 能迪 (翻訳)

日本には全国にGoのコミュニティがあるので、そちらも利用してみるといいでしょう。女性や学生限定のコミュニティもあります。GopherConなど海外のGoのカンファレンスなんかも、YouTubeで動画が公開されていますから、上手く利用してみてくださいね。


上田拓也 Goのエキスパート、上田拓也さん
上田さんが技術顧問として参画されているシェアフル株式会社のCIO・松尾さんと技術顧問3名の対談記事はこちらをご覧ください。

この記事を書いた人
flexy編集部
flexy編集部
ハイスキルIT人材への案件紹介サービス
flexyメディアは、テックメディアとしてテクノロジーの推進に役立つコンテンツを提供しています。flexyメディアを運営するのは、ITに関連するプロシェアリングサービスを提供するflexy。経営課題をITで解決するためのCTOや技術顧問のご紹介、ハイスペックエンジニアやクリエイターと企業をマッチングしています。【flexyのサービス詳細】求人を募集している法人様向け/お仕事をしたいご登録希望の個人様向け

週1日~/リモートの案件に興味はありませんか?

週1日~/リモートの関わり方で、「開発案件」や「企業のIT化や設計のアドバザリーなどの技術顧問案件」を受けてみませんか?副業をしたい、独立して個人で仕事を受けたエンジニア・デザイナー・PM・技術顧問の皆様のお仕事探し支援サービスがあります。

flexyでご案内できる業務委託案件

業務委託契約・開発案件(JavaScriptメイン)

テーマ flexy登録画面から案件詳細の確認と直接応募が可能です
勤務日数 2-3日/週
報酬 4万円/日
必要スキル JavaScript・React
勤務地 東京都内/リモート含む
リモート

外部CTO、技術顧問

テーマ 技術アドバイザリーとして知見と経験を生かす
勤務日数 1日/週
報酬 10万円/日
必要スキル エンジニア組織立ち上げや統括のご経験、コードレビュー経験、技術的なアドバイスが出来る方
勤務地 東京
リモート 相談可

業務委託契約・インフラエンジニア

テーマ flexy登録画面から案件詳細の確認と直接応募が可能です
勤務日数 2-3日/週
報酬 5万円/日
必要スキル それぞれの案件により異なります
勤務地 東京
リモート 相談可

業務委託・フロントエンドエンジニア

テーマ flexy登録画面から案件詳細の確認と直接応募が可能です
勤務日数 週1日〜
報酬 5万/日
必要スキル それぞれの案件により異なります
勤務地 東京
リモート リモートと常駐のMIXなど

人材紹介のCTO案件(非公開求人)

テーマ CTO、技術顧問案件はflexyに登録後、案件をコンサルタントからご紹介します
勤務日数 業務委託から人材紹介への移行
報酬 年収800万以上
必要スキル CTOとして活躍可能な方、エンジニア組織のマネージメント経験
勤務地 東京
リモート 最初は業務委託契約で週3日などご要望に合わせます

業務委託契約・サーバサイドエンジニア

テーマ flexy登録画面から案件詳細の確認と直接応募が可能です
勤務日数 週2-3日
報酬 案件により異なります
必要スキル 案件により異なります
勤務地 東京都内
リモート 相談可能
個人登録

お仕事をお探しの方(無料登録)
法人の方(IT課題の相談)