WHAT'S NEW
お気楽 Go 言語プログラミング入門、Puzzle DE Go!、Yet Another Golang Problems のフォントを Web フォント (Noto Sans JP, Noto Sans Mono) に変更し、印刷用の CSS を追加しました。Web ブラウザの印刷機能を使って PDF に変換することもできます。表示が崩れるときはフォント Noto Sans Mono CJK JP をインストールしてください。
お気楽 Go 言語プログラミング入門
CONTENTS
●入門編
- 2021/12/11 Go 言語の基礎知識 (1)
こんにちは Go 言語、Go 言語の数値、局所変数と大域変数、文字列、if 文、比較演算子と論理演算子、for 文による繰り返し (1)、for 文による繰り返し (2)、繰り返しの制御、FizzBuzz 問題、switch 文
- 2021/12/11 Go 言語の基礎知識 (2)
配列、多次元配列、配列の代入、定数、素数を求める、エラトステネスの篩、スライス (slice)、make と append、スライスの代入、文字列のスライス、多重代入、連想配列 (マップ, map)、for 文の range 節
- 2021/12/11 関数
関数の定義方法、局所変数と大域変数、局所変数の有効範囲、複数の返り値 (多値)、可変長引数、スライスを展開して要素を可変長引数に渡す、データの探索、二分探索、ソート、素数を求める (2)、値呼びと参照呼び
- 2021/12/11 再帰定義
再帰定義の基本、再帰定義のポイント、ユークリッドの互除法、累乗の計算、末尾再帰と繰り返し、クイックソート、クイックソートのプログラム、クイックソートの弱点、バックトラック法と再帰定義、順列の生成
- 2021/12/11 高階関数
関数を引数に取る関数、匿名関数、マッピング、フィルター、畳み込み、実行例、レキシカルスコープ、匿名関数と局所変数、クロージャ、ジェネレータ
- 2021/12/11 ポインタ
メモリの構成、C言語のポインタ、Go 言語のポインタ、配列とポインタ、ポインタを関数に渡す、多段階のポインタ、メモリの動的割り当て
- 2021/12/11 構造体
構造体の基本、構造体とポインタ、構造体と配列、構造体と関数、Go 言語のメソッド、レシーバの型、連結リスト、構造体の定義、作業用メソッド、データの取得、データの挿入、データの削除、実行例
- 2021/12/11 構造体 (2)
構造体の埋め込み、埋め込みと継承の相違点、複数の構造体の埋め込み、制限付き連結リスト、スタック、is-a 関係と has-a 関係、スタックの実装、キュー、キューの実装、Appendix: 配列によるキューの実装
- 2021/12/11 インターフェース
インターフェースの定義、ポリモーフィズム、空インターフェースと型アサーション、型 switch、Stringer インターフェース、インターフェースの埋め込み、クイックソート (2)、実行結果
- 2021/12/11 二分探索木
木構造、二分木、節の定義、データの探索、データの挿入、データの削除、最小値の探索と削除、データ削除のプログラム、巡回 (traverse)、構造体 Tree とメソッドの定義、実行例
- 2022/01/16 ファイル入出力
標準入出力、バイト単位の入出力、行単位の入出力、bufio.Scanner、Windows の改行文字、ファイルのアクセス方法、コマンドライン引数の取得、ReadFile と WriteFile、書式付き出力 Printf、Scan と Fscan、書式付き入力 Scanf、ファイルを行単位で連結する
●応用編
- 2021/12/18 並行プログラミング
並行プログラミングとは?、コア数の設定、goroutine の起動、チャネルによるデータの送受信、goroutine の終了待ち、WaitGroup、goroutine の同期、チャネルと range、ジェネレータの生成、データの交換、select、タイムアウトの処理
- 2021/12/18 並行プログラミング (2)
エラトステネスの篩、数列の生成、高階関数、素数を求める、哲学者の食事とは?、データ構造の定義、サーバーの作成、フォークの取得と返却、哲学者の動作、実行結果 (1)、デッドロックの防止、実行結果 (2)、ライブロックの解消、実行結果 (3)、デッドロックの防止 (2)、実行結果 (4)
- 2021/12/18 並列プログラミング
並列処理の効果、数値積分、数値積分の並列化、モンテカルロ法、乱数列の生成、モンテカルロ法の並列化、クイックソートの並列化、順列生成の並列化
- 2021/12/18 エラー処理
エラーの返し方、panic、defer 文、ランタイムエラーの捕捉、返り値がある関数でエラーを捕捉する、特定のエラーを捕捉する
- 2021/12/18 パッケージ
モジュールとパッケージの基本、簡単な実行例、import 文の使い方、外部パッケージのインポート、パッケージ tools の作成、パッケージのテスト
- 2021/12/25 複素数と複素関数
Go 言語の数、無限大、負のゼロ、非数、Go 言語の複素数、複素数の四則演算、指数関数、対数関数、三角関数、双曲線関数、平方根、逆三角関数、逆双曲線関数
- 2021/12/26 整数の論理演算とビット操作
ビット演算子、組み合わせの生成、組み合わせに番号を付ける方法、組み合わせを番号に変換、番号を組み合わせに変換、ちょっと便利なビット操作、ビットが 1 の個数を求める、パズル「ライツアウト」、ライツアウトの解法、高速化
- 2022/01/09 書式付き入出力関数
書式付き出力関数、Go 言語の文字、書式付き入力関数、Scanf の簡単な使用例、単語のカウント
- 2022/01/09 コマンドラインフラグの解析
コマンドの形式、フラグの解析、フラグの値を格納する変数を用意する、ファイルの連結
- 2022/01/23 パッケージ strings と regexp
文字列の検索、文字の除去、文字列の分割と結合、文字列の置換、正規表現の使い方、グループ、文字列検索ツールの作成、文字列の置換と分解、文字列置換ツールの作成、キーワードクロスリファレンスの作成
- 2022/01/29 簡単な CLI ツールの作成
cat、cut、paste、head、tail、wc、grep、gres、sort
●電卓プログラム編
- 2021/12/22 電卓プログラムの作成
プログラミング言語処理系の基本的な構造、文法の表現、式の構文、単項演算子、字句解析、構文解析、式の入力と評価、実行例
- 2021/12/22 電卓プログラムの作成 (2)
構文木の組み立て、式の評価、式の入力と評価、変数、関数、変数と関数の操作、構文解析、式の評価 (2)、実行例
- 2021/12/22 電卓プログラムの作成 (3)
文法の変更 (関数定義文の追加)、字句解析の修正、局所変数と連想リスト、変数評価の修正、ユーザ関数のデータ構造、ユーザ関数の評価、関数定義文の評価、実行例
- 2021/12/22 電卓プログラムの作成 (4)
論理演算子と比較演算子の優先順位、条件分岐、文法の修正、データ型の定義、字句解析の修正、構文解析の修正、条件分岐の処理、式の評価、再帰呼び出しの対応、実行例
- 2021/12/22 電卓プログラムの作成 (5)
begin, while, let の構文、データ型の定義、構文解析の修正、begin 式の処理、while 式の処理、let 式の処理、defineFunc の修正、式の評価、実行例
- 2021/12/22 電卓プログラムの改良
型 Value の変更、整数の追加、値の比較、文字列の追加、ベクタのアクセス方法、構文解析の修正、単項演算子と二項演算子の修正、ベクタの生成とアクセス、簡単な実行例
- 2021/12/22 電卓プログラムの改良 (2)
ベクタのサンプルプログラム、ライブラリのロード、ベクタの合計値、最大値と最小値、データの探索、二分探索、バブルソード、単純挿入ソート、クイックソート、エラトステネスの篩、素因数分解、木の操作関数
- 2021/12/22 電卓プログラムの改良 (クロージャ編その1)
関数型の定義、匿名関数の構文、call 式の追加、字句解析の修正、構文解析の修正、クロージャの生成、関数評価の修正、実行例
- 2021/12/22 電卓プログラムの改良 (クロージャ編その2)
Lisp のリスト、リストの表記法、クロージャによる連結リストの実装、リストの表示、リストの生成、リストの基本的な操作、高階関数、等値の判定、簡単な例題、リストの破壊的な修正
- 2021/12/22 電卓プログラムの改良 (連結リスト編その1)
連結リストの定義、値 (Value) を文字列に変換、連結リストの基本関数、連結リストの生成、組み込み関数の追加、簡単な実行例
- 2021/12/22 電卓プログラムの改良 (連結リスト編その2)
電卓プログラム用ライブラリの作成、数値演算、述語、リストのアクセス、リストの生成、簡単なリスト操作、簡単なリストとベクタの操作、リストとベクタの探索、マッピング、フィルター、畳み込み、連想リスト、集合、マージとソート、順列と組み合わせ、スタックとキュー、乱数の生成
- 2021/12/22 電卓プログラムの改良 (遅延評価編その1)
遅延評価とは?、delay と force の動作、構文解析の修正、プロミスの定義、プロミスの評価、たらいまわし関数、クロージャによる遅延評価
- 2021/12/22 電卓プログラムの改良 (遅延評価編その2)
遅延ストリームの構造、遅延ストリームの生成、遅延ストリームの操作関数、高階関数、遅延ストリームの操作関数 (2)、高階関数 (2)、組 (pair) を生成するストリーム、無限ストリームで組 (pair) を生成する場合、素数の生成、streamSieve の改良
- 2021/12/22 電卓プログラムの改良 (コルーチンその1)
コルーチンとは?、コルーチンの動作、コルーチンの定義、コルーチンの中断と再開、コルーチンの生成
- 2021/12/22 電卓プログラムの改良 (コルーチンその2)
コルーチンの簡単なテスト、高階関数をジェネレータに変換、順列の生成、エラトステネスの篩、簡単なマルチプロセスの作成、簡単な実行例、キューによる同期処理、哲学者の食事、実行結果 (1)、デッドロックの防止、実行結果 (2)、デッドロックの防止 (2)、実行結果 (3)
Puzzle DE Go!
- 2021/12/11 経路の探索
はじめに、グラフ、隣接行列と隣接リスト、バックトラックによる探索、幅優先探索、経路の管理、幅優先探索のプログラム、反復深化、反復深化のプログラム、Appendix: 配列によるキューの実装、プログラムの作成、実行例
- 2021/12/11 生成検定法
小町算、覆面算、魔方陣、マスターマインド、小町算の解答、覆面算の解答、対称解の排除、マスターマインドの解答、プログラムの作成、何回で当たるか
- 2021/12/11 入れ替えパズルと幅優先探索
おしどりの遊び、嫉妬深い夫の問題、蛙跳びゲーム、おしどりの遊びの解答、石の移動、同一局面のチェック、移動手順の表示、おしどりの遊びを解く、実行結果、嫉妬深い夫の問題の解答、安全確認、嫉妬深い夫の問題を解く、実行結果、蛙跳びゲームの解答、石の移動、蛙跳びゲームを解く、実行結果
- 2021/12/11 反復深化と下限値枝刈り法
ペグ・ソリティアとは?、変形三角盤、ペグの跳び先表、大域変数の定義、ペグの移動、移動手順の表示、反復深化による解法、実行結果、下限値枝刈り法、解法プログラム、実行結果 (2)、ペグのグループ分け
- 2021/12/11 N Queens Problem
8 クイーンの解法、単純な生成検定法、実行結果、無駄を省く、プログラムの改良、ビット演算による高速化、並列処理による高速化
- 2021/12/11 スライドパズル
パズルの説明 (9 パズル)、幅優先探索による解法、実行結果、双方向探索、実行結果 (2)、最長手数の求め方、プログラムの作成、実行結果 (3)
- 2021/12/11 スライドパズル (2)
反復深化による解法、9 パズルの下限値、手数の遇奇性、プログラムの作成、下限値の求め方、反復深化と下限値枝刈り法、実行結果、11 パズルの解法
Yet Another Golang Problems
- 2021/12/12 問題 1 - 10, 解答 1 - 10
整数の和、素因数分解、フィボナッチ関数、組み合わせの数、めのこ平方、多角数、平均値と標準偏差、最大値と最小値、選択ソート、バブルソート
- 2021/12/12 問題 11 - 20, 解答 11 - 20
重複要素の削除、集合演算、シェルソート、整数の印字、文字列を整数に変換、順列の生成、重複順列の生成、パスカルの三角形、組み合わせの生成、重複組み合わせの生成
- 2021/12/12 問題 21 - 30, 解答 21 - 30
素因数分解、約数の個数、約数の合計値、約数、完全数、友愛数、分割数、多倍長整数による階乗とフィボナッチ関数と累乗の計算、分数を循環小数に変換、循環小数を分数に変換、パズル「小町分数」
- 2021/12/19 問題 31 - 40, 解答 31 - 40
完全順列、モンモール数、カッコ列の生成、カッコ列の総数 (カタラン数)、分割数、整数の分割、集合の分割、ベル数、集合のグループ分け、グループ分けの個数
- 2021/12/19 問題 41 - 50, 解答 41 - 50
連結リストライブラリの作成, Cons, Car, Cdr, Atom, Listp, Consp, Null, Print, Sprint, List, Nth, Append, Reverse, Length, Take, Drop, Last, ButLast, Equal, MapCar, Filter, Foldl, Foldr, ForEach, Member, MemberIf, Find, FindIf, Position, PositionIf, Count, CountIf, Remove, RemoveIf, Substitute, SubstituteIf, Zip, UnZip, Assoc, AssocIf
- 2021/12/22 問題 51 - 60, 解答 51 - 60
連結リストライブラリの作成 (2)、Iota, MakeList, Tabulate, CountLeaf, Flatten, FlatMap, Permutation, RepeatPerm, Combination, RepeatComb, RemoveDup, IsSubset, EqSet, Union, Intersection, Difference, InsertSort, Partition, QuickSort, MergeList, MergeSort
はじめに
Go 言語は Google 社によって開発されているコンパイル形式のプログラミング言語です。2012 年 3 月にバージョン 1.0 がリリースされました。現在も活発に開発が行われており、最新 (2021 年 12 月時点) バージョンは 1.17.4 になっています。
Go 言語はシンプルな言語仕様で、コンパイル・実行速度が速いといわれています。C++ と違って Go 言語にはガベージコレクションがあり、クロージャや並列処理もサポートしています。クラスや継承といったオブジェクト指向機能はありませんが、構造体、メソッド、インターフェースを使って、オブジェクト指向プログラミングを行うことは可能です。使い方も簡単で、実行形式ファイルを作成するだけではなく、スクリプト言語のようにコンパイルしたあとすぐに実行することもできます。
ただし、Go 言語にはC言語で有名な「ポインタ」があります。プログラミング言語の学習には、どの言語にもいくつかの難関がありますが、C言語最大の難関がポインタと言われています。ポインタはコンピュータの基本 (特にメモリの概念) を正しく理解していれば、けっして難しい話ではありません。問題は、C言語のポインタが不適切な操作や演算によってプログラムを簡単に暴走させてしまうことです。その点、Go 言語のポインタはC言語のような危険な操作や演算が禁止されているので、C言語よりもずっと安全にポインタを使うことができます。
M.Hiroi は Go 言語でプログラミングするのは初めてです。Go 言語の特徴のひとつである goroutine と channel による並行プログラミングを目標に、簡単なプログラムを作りながら Go 言語を勉強していきたいと思っています。まあ、初心者が作るプログラムなので、Go 言語らしいプログラムは書けないと思います。間違いやお気づきの点がありましたらご指摘お願いいたします。たいしたことはできませんが、よろしければお付き合いくださいませ。
●ダウンロード
Go 言語は次のサイトからダウンロードできます。Windows 用のバイナリが用意されているので、とても簡単にインストールすることができます。
Unix 系 OS の場合、一番簡単な方法は OS のパッケージマネージャを使ってインストールすることです。たとえば、Ubuntu の場合は次のコマンドでインストールすることができます。
sudo apt install golang
Ubuntu 18.04 (WSL) の場合、少し古いバージョン 1.10 がインストールされます。最新バージョンをインストールしたい場合は、公式ページ Download and install の手順に従ってください。具体的には、アーカイブファイル (go1.17.4.linux-amd64.tar.gz) をダウンロードし、次のコマンドで /use/local に展開します。
sudo tar -C /usr/local -xzf go1.17.4.linux-amd64.tar.gz
あとはディレクトリ /usr/local/go/bin にパスを通すだけです。次のコマンドを実行してください。
export PATH=$PATH:/usr/local/go/bin
これでパスを通すことができます。上記のコマンドはファイル ~/.bashrc に追加しておくといいでしょう。
●簡単なベンチマーク
Go 言語はプログラムをネイティブコードにコンパイルするので、バイトコードにコンパイルする処理系よりもプログラムを高速に実行することができます。その実行速度ですが、たらいまわし関数を使って調べてみました。
リスト:たらいまわし関数 (Go 言語)
package main
import (
"fmt"
"time"
)
func tak(x, y, z int) int {
if x <= y {
return z
} else {
return tak(tak(x - 1, y, z), tak(y - 1, z, x), tak(z - 1, x, y))
}
}
func main() {
s := time.Now()
fmt.Println(tak(22, 11, 0))
e := time.Now().Sub(s)
fmt.Println(e)
}
ファイル名を tak.go とすると、シェル上で次のように入力すると実行ファイル tak を生成することができます。
$ go build tak.go
また、build のかわりに run を指定すると、プログラムをコンパイルしたあと、実行形式ファイルを作らないですぐに実行することができます。
$ go run tak.go
11
1.2142619s
それでは実行結果を示します。tak(22, 11, 0) を計算しました。使用した Go 言語のバージョンは 1.17.4 です。
表 : tak(22, 11, 0) の結果
処理系 | 秒 |
SBCL (ver 1.4.5) | 6.38 |
LuaJIT (var 2.1.0-β) | 4.02 |
SML/NJ (ver 110.98) | 2.66 |
GHC (ver 8.8.4) | 1.96 |
Julia (ver 1.6.4) | 1.95 |
SBCL (最適化) | 1.57 |
GCC -O2 (ver 7.4.0) | 1.23 |
Go 言語 (ver 1.17.4) | 1.21 |
Scala (ver 2.13.5) | 1.07 |
ocamlopt (ver 4.05.0) | 0.97 |
Java (ver 11.0.10) | 0.95 |
- 実行環境 : Ubunts 18.04 (Windows Subsystem for Linux), Intel Core i5-6200U 2.30GHz
Go 言語は SML/NJ, SBCL, Haskell よりも速い結果になりましたが、Java や OCaml にはかないませんでした。それでも、GCC と同程度の速度をたたき出しているのですから、Go 言語は大変優れたコンパイラ (処理系) だと思います。
初版 2014 年 2 月 1 日
改訂 2021 年 12 月 11 日
- The Go Programming Language (本家)
- Documentation - go.dev, (本家)
- A Tour of Go, (チュートリアル, 日本語版)
『お気楽 Go 言語プログラミング入門』の著作権は筆者「広井誠 (Makoto Hiroi)」が保持します。無断使用や無断転載は禁止いたします。『お気楽 Go 言語プログラミング入門』で作成したプログラムはフリーソフトウェアとします。ご自由にお使いください。プログラムの改造や配布もご自由にどうぞ。その際は、出典を明記してくださるようお願いいたします。
ただし、これらのプログラムは無保証であり、使用したことにより生じた損害について、作者「広井誠 (Makoto Hiroi)」は一切の責任を負いません。また、これらのプログラムを販売することで利益を得るといった商行為は禁止いたします。