Goのエキスパートが教えるGoの魅力、プログラミング基礎入門
※本記事は2020年3月に公開された内容です。
上田拓也(@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/http | HTTPサーバなど |
archive, compress | 圧縮形式など |
encoding | JSON, XML, CSVなど |
html/template | HTMLテンプレート |
os, path/filepath | ファイル操作など |
周辺ツールの充実
標準ライブラリと同様、周辺ツールも充実しています。例えば、gofmtというコードフォーマッターが標準で用意されてる事は有名でしょう。gofmtによってコードの書式が一意に決まるため、プロジェクトごと細かなコーディング規約などを設ける必要がありません。
go build | ビルドを行うコマンド |
---|---|
go test | xxxx_test.goに書かれたテストコードの実行 |
go doc, godoc | ドキュメント生成 |
gofmt, goimports | コードフォーマッター |
go vet, golint | コードチェッカー、リンター |
gopls | Language 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 | “” |
Bool | false |
error | nil |
<標準パッケージ>
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名の対談記事はこちらをご覧ください。
Vue.js、Go、Kotlinのエキスパートが集結!シェアフル社が迎え入れた技術顧問3名とCIOの対談
FLEXYがお取り扱いするフリーランスエンジニア向けGo案件
FLEXYではフリーランスや副業でご活躍されるエンジニアの方向けにGo関連の求人案件をご紹介しています。こちらの項目ではその一部を記載していますので、お仕事をお探しの方はご覧いただき、気になる案件がありましたら是非お気軽にご相談ください。
【Golang/PHP】脱炭素に関するコンサルティングなどを行う企業で自社プロダクトのバックエンド開発支援(フルリモート・ビジネスタイム外可)
サステナブル社会の実現にコミットすることができる案件です。市場リーダーになりうるプロダクトを一緒にグロースして頂ける方はぜひご応募ください。
■案件概要
- 職種:サーバサイドエンジニア
- 稼働日数:週4〜5日、ビジネスタイム以外の空き時間
- 報酬:〜90万円/月
- 勤務地:田町
- リモート:可
■募集背景
CO2排出量の算出・可視化 SaaSを開発されている企業様です。2023年2月にはシリーズAで24.4億円の資金調達を実施されており、社員数は100名超、導入社数も2000社を突破しています。サービスグロースのためエンジニアを追加募集されています。ドメイン知識のキャッチアップに時間がかかるため、長期で稼働して頂ける方を優先しています。
■業務内容
企業活動によって排出されたCO2量を算出・可視化できるSaaSのバックエンド設計・実装をしていただきます。
- サプライチェーン全体の企業間のデータ連携
- CO2排出量の算定に必要な外部データとのAPI連携
- グラフによるビジュアライズや外部機関への報告向けのレポーティング機能構築
- CO2排出量の削減管理やクレジットの取引・活用を行うカーボンオフセットシステム構築
■必須要件
- SPA経験
- Golang / PHP / Ruby いずれかを用いた開発経験
- SaaSの自社プロダクト開発経験
案件のご紹介を希望される方は、FLEXYに登録(案件のご紹介)よりご応募ください。
【Go/AWS】車のサブスクサービスの開発を行う企業で自社サービスのリプレイス支援(フルリモート・フルフレックス可)
テレビCM等も放送していた車のサブスクサービスの開発を担う企業で、新たに開発を進めている新サービスに携って頂きます。今回Goでのリプレイスということで今後も人気が高いであろうGo言語での経験をさらに積みたい方、やりがいあるプロジェクトに参画したい方のご応募お待ちしております。全体で約280名と大所帯ながら、アジャイルでのスピード感ある開発環境や外国籍のメンバーも多く在籍するなどベンチャーらしさも持ち合わせるエンジニア組織も魅力です。
■案件概要
- 職種:サーバサイドエンジニア
- 稼働日数:週3〜5日、ビジネスタイム以外の空き時間
- 報酬:〜80万円/月
- 勤務地:三越前
- リモート:可
■募集背景
新サービスにおけるWebアプリケーションエンジニアを募集中。すでにKothlinでサーバーサイドの開発を行なっていたが事業スケールを考える上で、Goへのリプレイスを予定しているため、Goでのサーバーサイド開発の経験があるメンバーの増強が必要とのこと。
■業務内容
- サービスにおけるGoを用いたサーバーサイド設計開発
- AWS環境で各種マイクロサービスのコンテナ設計、実装
- Aurora MySQL等を使ったDB設計、実装
- Go / Kotlinを用いたAPI設計、開発
※上記は例となりますので、適性や優先順位によってタスクに取り組んで頂くイメージです。
■必須要件
- バックエンド開発領域において、Go を用いたAPI開発経験(2年以上)
- マイクロサービスアーキテクチャを採用したプロダクトの開発経験
- AWS環境でのプロダクト開発・運用経験(コンテナ/ECS/SQS など)
■歓迎要件
- 開発言語のリプレイス経験がある(Go,Kotlin以外でもOK)
- 複数言語を習得している(Go, Kotlin, Java/Spring Bootなど)
- スマホ向けサイトやアプリの開発経験
- スクラムなどのアジャイル開発手法の経験
案件のご紹介を希望される方は、FLEXYに登録(案件のご紹介)よりご応募ください。
【Go】メディア事業などを展開している企業でシェアサロンに関するアプリのサーバーサイド開発支援(フルリモート可)
プロダクト開発においてエンドユーザー視点を非常に大切にされている環境です。またモダンな開発環境にチャレンジされる思考もあり、今後の経験としても生きてくると思います。
■案件概要
- 職種:サーバサイドエンジニア
- 稼働日数:週3〜5日
- 報酬:〜70万円/月
- 勤務地:
- リモート:可
■業務内容
シェアサロンに関するアプリ開発におけるサーバーエンド開発業務をお願いします。現状はPHP(Laravel)を活用しておりますがGo言語を今後使用する方針、且つチーム開発のため日中のコミュニケーションを特に重要視しております。
■必須要件
- Go言語(Golang)でのWEBアプリケーション開発経験
- AWS環境での開発経験
- チーム開発経験
■歓迎要件
- PHP(Laravel)でのWEBアプリケーション開発経験
- ECサービスに関する開発経験
- AWS-ECS、ECR、RDSなどの設計経験
案件のご紹介を希望される方は、FLEXYに登録(案件のご紹介)よりご応募ください。