はじめに
これからプログラミングを始めようと考えている人に向けて、Go言語を使いながらプログラミング言語の基本的な仕組みを学ぶ勉強会用の資料です。
Goを使いますが、Go固有の難しい機能を覚えることが目的ではありません。変数や条件分岐など、PythonやJavaScriptを学ぶときにも共通する考え方を、実際にプログラムを動かしながら理解していきます。
今回学習すること
・プログラムがどのように動作するか
・変数とデータ型
・計算と比較
・条件分岐(if)
・繰り返し(for)
・関数(func)
・総合演習(FizzBuzz)
事前準備:Goの実行環境
今回はブラウザ上の実行環境ではなく、自分のPCにインストールしたGoを利用します。環境構築は勉強会が始まる前に済ませておいてください。
Windows 11を利用している場合
Windows上にLinuxの環境を用意するWSL(Ubuntu)を利用します。まず下記の記事を上から順に進めてください。
① Linuxとは~WSLのインストール
② 【Windows 11】WSLにGo言語をインストールする方法
以降のコマンドはPowerShellではなく、WSLのUbuntuのターミナル上で実行します。
Macを利用している場合
以下の記事を参考にGoをインストールしてください。
【Mac】Go言語のインストール方法
以降のコマンドはmacOSのターミナルで実行します。
インストールできたか確認する
go version
Goのバージョンが表示されれば準備完了です。表示されない場合は、上記のインストール記事をもう一度確認してください。
プログラミング言語って??
コンピュータは、人間が普段利用する日本語や英語などの自然言語を、そのまま理解して処理しているわけではありません。コンピュータの内部では、情報を0と1の二進数で表現して処理しています。
そこで、人間がコンピュータに処理を指示するために利用するものがプログラミング言語です。
プログラミング言語は、大きく「高水準言語」と「低水準言語」に分けることができます。
- 高水準言語:PythonやGo、JavaScriptなど、人間が比較的理解しやすい形で記述できる言語
- 低水準言語:機械語やアセンブリ言語など、コンピュータのハードウェアに近い言語
今回利用するGo言語も高水準言語の一つです。
ただし、Goで書かれたプログラムを、そのままCPUが実行できるわけではありません。コンピュータが実行できる形式に変換する必要があります。
例えば「点数が60点以上なら合格と表示する」という処理は、言語によって記述の仕方は違いますが、やりたいことは同じになります。
今回はGoという言語を使って「データを保存する」「条件を判定する」「処理を繰り返す」「処理をまとめる」の4つを学びます。
コンパイルって??
まず、先ほど登場した「コンパイル」とはどういうものなのかについて説明していきましょう。
コンパイルとは、プログラミング言語で記述されたソースコードを、別の形式のコードに変換することです。
Go言語では、コンパイルすることによってCPUが実行できる機械語を含む実行ファイルを作成できます。
Goでは主に以下のコマンドを利用します。
go build
go buildはプログラムをコンパイルして、実行ファイルを作成するコマンドです。
go run .
go runは内部でコンパイルを行い、そのままプログラムを実行するコマンドです。
なお、プログラミング言語にはGoのように事前に機械語へコンパイルするもの以外にも、実行時にコードを解釈したり、仮想マシン上で実行したりするものがあります。
今回の勉強会では、主にgo runを利用してプログラムを動かしていきます。
GoでHello Worldを表示させよう!
作業用のフォルダを作成
Windowsの場合はWSLのUbuntuターミナル、Macの場合はターミナルを開いて、次のコマンドを実行してください。
mkdir go-workshop
cd go-workshop
go mod init example.com/go-workshop
mkdirはフォルダの作成、cdはフォルダへの移動です。
この辺りはUnixコマンドになるので今回割愛していきます。
go mod initはGoのプロジェクトを初期化しています。これを行うことによって、Goの外部パッケージを利用する際にバージョン管理などをここで行なってくれるという代物になっています
main.goを作成
作成したgo-workshopフォルダの中にmain.goというファイルを作り、次のコードを記述してください。VS Codeなどのエディタを利用して構いません。
package main
import "fmt"
func main() {
fmt.Println("Hello World!")
}
このコードは初心者が必ずやるであろうHelloWolrdのコードですね。
このコードの説明をしていきましょう。
まず一行目の package main はそのプロジェクトがどのパッケージに所属しているのかということを示します。基本的にmainパッケージはそのプロジェクト本体を動作させるパッケージで、他のディレクトリ階層で作成するパッケージをインポートして利用すると言った使い方になります。(同ディレクトリに別パッケージを作成することはできないので別パッケージを作成したい場合はディレクトリを作成してそこで新たなパッケージを作成するようにしましょう。)なお、1パッケージ:1ファイルではないので同ディレクトリに複数ファイルを作成して一つのパッケージとすることができます。
import "fmt" は文字を表示するための機能を読み込みます。インポートするパッケージが一行だけの場合は現在みたいな書き方でいいんですが、複数ある場合は以下のように記載します。
import(
"fmt"
"math"
)
func main()がプログラムの実行開始地点となる関数です。Goでは関数を定義するときにfunc 関数名()という形式で記述します。
Go言語では、関数や変数などの名前の最初の文字が大文字か小文字かによって、他のパッケージから利用できるかどうかが決まります。
- 大文字で始まる名前:他のパッケージからも参照できる(エクスポートされる)
- 小文字で始まる名前:基本的に同じパッケージ内でのみ参照できる
例えば、PrintMessage()という関数は他のパッケージからも利用できますが、printMessage()という関数は同じパッケージ内でのみ利用できます。
なお、main()はプログラムの実行開始地点として使われる特別な関数であり、小文字で始まります。
fmt.Printlnが画面に文字を表示します。fmtパッケージには文字の表示以外にも色々あるので確認しておきましょう。
実行してみよう
go run .
実行結果:
Hello World!
ここまで表示されたら成功です。main.goの文字を好きな言葉に書き換えて、もう一度実行してみましょう。
変数って??
変数は、プログラムの中で使う値に名前をつける仕組みです。例えば、名前や年齢を何度も表示するときに便利です。Goでは := を使うと、右側の値から型を推測して変数を宣言できます。
package main
import "fmt"
func main() {
name := "Taro"
age := 18
fmt.Println(name)
fmt.Println(age)
}
:=以外にも var <変数名> <型名> や var <変数名> = <値>といった指定方法もあります。また、変数とは異なりますが、定数と呼ばれるπなどの値を定義しておくものもあります。こちらは処理の中で変更されては困るので、constと記述することで定数として定義することができます。
データ型って??
データ型とはその値が持つデータの属性を表したものです。プログラミングでは、正しくそのデータを扱うことができるように、そのデータの属性を管理します。その一覧を以下に示します。
| データ型 | 説明 | 例 |
|---|---|---|
| int | 整数 | 10,-5 |
| float32 | 小数を含む数値(32ビット) | 3.14,2.5 |
| float64 | 小数を含む数値(64ビット) | 3.14159,0.5 |
| string | 文字列 | "Hello" |
| bool | 真偽値 | true,false |
なお、 違う型の値はそのままでは計算することができない場合があります。
計算してみよう
fmt.Println(10 + 3) // 足し算:13
fmt.Println(10 - 3) // 引き算:7
fmt.Println(10 * 3) // 掛け算:30
fmt.Println(10 / 3) // 整数同士の割り算:3
fmt.Println(10 % 3) // 余り:1
上の5行はmain関数の中に入れて実行します。Goではint同士の割り算は小数部分を切り捨てることにも注目してください。
やってみよう① 自己紹介
- name(名前)
- age(年齢)
- favorite(好きなもの)
を変数として用意し、 fmt.Println を使って自己紹介を表示してみましょう。
条件分岐って??
条件分岐は、条件によって実行する処理を変更することです。例えば、単位が取れているのかどうかの判断をさせることができます。※単位が取れるかの判断値は60点とします。
package main
import "fmt"
func main() {
score := 75
if score >= 60 {
fmt.Println("単位合格")
} else {
fmt.Println("単位不合格")
}
}
if の後ろには、trueかfalseとなる条件式を記述します。
| 比較演算子 | 説明 | 例 |
|---|---|---|
| == | 等しい | a==b |
| != | 等しくない | a!=b |
| >= | 以上 | a>=b |
| <= | 以下 | a<=b |
| > | より大きい | a>b |
| < | より小さい | a<b |
注意
=(代入)と==(比較)は違うので注意しましょう。
やってみよう② 年齢でメッセージを変更
ageという変数を作成し、18以上の場合は「成人です」、18未満の場合は「未成年です」と表示してみてください。
発展問題
90点以上は「S」、80点以上は「A」、70点以上は「B」、60点以上は「C」、それ以外は「D」と表示してみましょう。else if というものも使えます。 else if は else よりも前に記載することで比較条件を増やすことができます。
else if は以下のように使うことができます。
package main
import "fmt"
func main() {
score := 75
attendance := 10 // 出席回数
if attendance <= 7 {
fmt.Println("出席不良")
} else if score >= 60 {
fmt.Println("単位合格")
} else {
fmt.Println("単位不合格")
}
}
別の条件分岐
さきほど else if について説明してきましたが、複数の条件を見やすく記述できる場合があります。それが switch文を利用する方法です。
switch 文は、ある値や条件に応じて実行する処理を切り替えることができます。例えば、数字によって曜日を表示するプログラムを作成してみましょう。
package main
import "fmt"
func main() {
day := 3
switch day%7 {
case 1:
fmt.Println("月曜日")
case 2:
fmt.Println("火曜日")
case 3:
fmt.Println("水曜日")
case 4:
fmt.Println("木曜日")
case 5:
fmt.Println("金曜日")
case 6:
fmt.Println("土曜日")
case 7:
fmt.Println("日曜日")
default:
fmt.Println("正しい曜日を指定してください")
}
}
このプログラムを実行すると、以下のように表示されます。
水曜日
switch day では、変数 day の値によって処理を分岐させています。
case は、それぞれの値に対応する処理を記述するためのものです。今回の場合は day が3なので、case 3: の処理が実行されます。また、default は、どの case にも当てはまらなかった場合に実行される処理です。else と似た役割を持っています。
複数の条件を指定する
switch 文では、1つの case に複数の値を指定することもできます。例えば、平日と休日を判定する場合は以下のように記述できます。
package main
import "fmt"
func main() {
day := 6
switch day%7 {
case 1, 2, 3, 4, 5:
fmt.Println("平日です")
case 6, 7:
fmt.Println("休日です")
default:
fmt.Println("正しい曜日を指定してください")
}
}
このように、複数の値をカンマで区切ることで、同じ処理をまとめて記述できます。
条件式を利用したswitch文
先ほどまでは特定の値によって処理を分岐させていましたが、Go言語では switch の後ろに変数を指定せず、条件式を使った分岐も可能です。例えば、さきほど else if で作成した成績判定のプログラムを switch 文で記述してみましょう。
package main
import "fmt"
func main() {
score := 85
switch {
case score >= 90:
fmt.Println("S")
case score >= 80:
fmt.Println("A")
case score >= 70:
fmt.Println("B")
case score >= 60:
fmt.Println("C")
default:
fmt.Println("D")
}
}
このプログラムでは、上から順番に条件式を確認していき、最初に条件が成立した case の処理を実行します。
今回の場合は score が85なので、score >= 80 の条件が成立し、「A」と表示されます。なお、Goの switch 文では、通常は一致した case の処理が終わると自動的に switch 文を抜けます。そのため、C言語などとは異なり、各 case の最後に break を記述する必要はありません。
if文とswitch文の使い分け
ここまで if 文と switch 文について学習してきましたが、どちらも条件分岐を実装するためのものです。
| 構文 | 主な用途 |
|---|---|
if |
条件が少ない場合や、複雑な条件式を判定する場合 |
else if |
複数の条件を順番に判定する場合 |
switch |
特定の値や複数の条件によって処理を切り替える場合 |
必ずしも switch 文の方が優れているというわけではなく、処理の内容に応じて読みやすい方法を選択することが大切です。
やってみよう:switch文を使った成績判定
先ほどの成績判定プログラムを、switch 文を使って作成してみましょう。
判定条件は以下の通りです。
- 90点以上:S
- 80点以上:A
- 70点以上:B
- 60点以上:C
- 60点未満:D
さらに、出席回数が7回以下だった場合は、点数に関係なく「出席不良」と表示する処理を追加してみましょう。
ヒント:switch 文の中では &&(かつ)などの論理演算子を利用した条件式も記述できます。
繰り返し処理って??
同じ処理を何度も記述したい場合、1行ずつコピーするのではなく、繰り返しを利用します。Goではforを使います。
package main
import "fmt"
func main() {
for i := 1; i <= 5; i++ {
fmt.Println(i)
}
}
i := 1 は開始時の値、i <= 5 は繰り返す条件、i++ は1回ごとに1を足す処理です。このコードでは1〜5が順に表示されます。
開始時の値は現在このforループ内のみで利用するのにiという変数を定義していますが、forループ外で定義したものを利用しても構いません。
forループの他の使い方
先ほどは一般的なforループの記述方法を紹介しましたが、Go言語ではforループを複数の形式で記述することができます。
今回はその中でも基本的な3つの使い方を紹介していきます。
① 一般的なforループ
先ほど紹介したように、初期値・継続条件・更新処理を指定する方法です。
package main
import "fmt"
func main() {
for i := 1; i <= 5; i++ {
fmt.Println(i)
}
}
この場合は、iが1から5になるまで繰り返し処理を実行します。
② while文のようなforループ
Go言語には、PythonやC言語などにあるwhileという構文がありません。
その代わりに、forに条件式だけを記述することでwhile文と同じような処理を実装できます。
package main
import "fmt"
func main() {
i := 1
for i <= 5 {
fmt.Println(i)
i++
}
}
先ほどのforループと異なり、初期値の設定をforループの外側で行い、ループ内部で値を更新しています。
i <= 5という条件が成立している間は繰り返し処理を実行し、条件が成立しなくなると終了します。
③ 無限ループ
forループは、条件式を省略すると無限ループとして利用することもできます。
package main
import "fmt"
func main() {
i := 1
for {
fmt.Println(i)
i++
if i > 5 {
break
}
}
}
for {}と記述すると、基本的には処理を繰り返し続けます。
しかし、このサンプルコードではbreakという命令を利用しています。breakは現在実行しているループを終了させるための命令です。
今回はiが5を超えた段階でループを終了するため、結果として1から5までの数値が表示されます。
なお、終了条件のない無限ループを実行するとプログラムが動作し続けるため、注意しましょう。
やってみよう③ 1から10の合計
sum := 0 という変数を作成し、forで1〜10を順番に足して合計を表示してみましょう。
発展問題:1〜20の偶数だけ表示してみましょう。
関数って??
関数は、ひとまとまりの処理に名前をつけて、何度でも呼び出せるようにする仕組みです。値を渡すものを「引数」、結果として返すものを「戻り値」といいます。
package main
import "fmt"
func add(a int, b int) int {
return a + b
}
func main() {
result := add(3, 5)
fmt.Println(result)
}
add(3, 5)は3と5を引数として渡しています。returnで返された8がresultに入ります。
関数を定義する構文は以下のように定義することができます。
func <関数名>(<引数名1> <引数の型1>, ..., <引数名n> <引数の型n>) <戻り値> {
return a + b
}
やってみよう④ 長方形の面積
縦と横の長さを受け取って面積を返すrectangleAreaという関数を作成しましょう。mainから呼び出して表示できれば成功です。
最後に:FizzBuzzを作ってみよう!
今まで学習した変数・条件分岐・繰り返しを組み合わせてFizzBuzzを作成してみましょう。
1〜30の数字に対して以下のように表示します。
・3の倍数:Fizz
・5の倍数:Buzz
・3と5の両方の倍数:FizzBuzz
・それ以外:その数字
ヒント:余りを求める%とif、forを使います。3と5の両方の倍数の判定を最初に書いてみましょう。
出力結果としては以下のような形になります。
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz
...
まとめ
今回はGo言語を用いてプログラミングの基礎について学習しました。変数・データ型・計算・条件分岐・繰り返し・関数は、Go以外のプログラミング言語を勉強するときにも役立つ考え方です。書き方を暗記するより、「どんな処理をしたいのか」「そのためにどの仕組みを使うのか」を考えられるようになることが大切です。
AIが発展してきている中で人間がやるべきことがどういうことなのか、考えながら勉強していきましょう。
参考資料
Go公式サイト:https://go.dev/
A Tour of Go:https://go.dev/tour/
Go公式チュートリアル:https://go.dev/doc/tutorial/