「A Tour of Go をやる!」シリーズの第2回目。
引き続き「A Tour of Go」を使ってGo言語のお勉強です。
前回は「A Tour of Go」の使い方が主な学習内容でしたが、サクッと終わったので今回からは新章「Basics」に突入。
新章「Basics」

今回から新章の「Basics」に入ります。
ここでは、Goの基礎部分を学ぶようですね。
今回は「Packages」がお題
該当ページはこちら。
タイトルの通りで「Packages(パッケージ)」がお題。
Package とは?
ん~、様々な機能(ファンクション)を用途別にまとめたもの、、、という感じでしょうか。ここで言う機能は「Println(文字列を出力)」や「Intn(ランダムな数値を選択)」といったファンクションを指します。
例えば、「Println」は “書式(fmt)” として分類され、「fmt」というパッケージに属します。
同様に、「Intn」は “計算(math)” で、「math」というパッケージ。
また、「Replace(文字列の置換)」などは “文字列(string)” として分類され、「strings」というパッケージ になります。
こんな感じで、沢山あるファンクションをパッケージとして整理し、探しやすく、使いやすくしているわけです。
Package 種類
(多分…)よく使うであろうパッケージを並べてみます。
パッケージ | 主な用途 |
---|---|
fmt | 書式化されたデータの入出力。 |
math | 数学上でよく使われる定数の定義や様々な計算。 |
time | 日付や時刻の書式化や計算など。 |
strings | 文字列の操作。 |
もちろん、上記以外にも多数のパッケージがあります。
サンプルプログラムを見る
サンプルプログラムから、具体的な package (パッケージ)の使い方を見てみます。
サンプルプログラム
それぞれ何をやっているのかが分かるように、各行にコメントを入れてみました。
// パッケージ宣言部分( main() を起点として動かすため)
package main
// パッケージのインポート宣言(パッケージを使う場合に必要)
import (
"fmt"
"math/rand"
)
// プログラムの起点
func main() {
fmt.Println("My favorite number is", rand.Intn(10))
}
サンプルプログラムを少し修正する
今あるサンプルプログラムを実行しても “My favorite number is 1” しか表示されず、最後の数字が変化しません。(正しくは 0~10 の間でランダム)

この原因についてはページの説明に記載があり、掻い摘むと「rand.Intn には シード値 が必要」と書かれています。
rand.Intn が求める乱数はこのシード値を基に算出されます。つまり、シード値が未設定のため暗黙的に固定の値となってしまい、乱数の範囲を定めても同じ値を返却してしまうようです。
Note: ここで実行するプログラムは常に同じ環境で実行されます ので、擬似乱数を返す rand.Intn はいつも同じ数を返します。
(数を強制的に変える場合は、乱数生成でシードを与える必要があります。rand.Seedを見てみてください。 playground 上での時間は一定なので他のものをシードとして使う必要があります。)
https://go-tour-jp.appspot.com/basics/1
これを解決するには、実行するたび変化する値をシード値として設定すればいいだけ。
下記はシード値を設定する処理を加えたサンプルプログラムになりますが、ここではシード値に「実行時の時刻」を与えるようにしています。
package main
import (
"fmt"
"math/rand"
"time" // 追加:rand.Seedで使うため追加
)
func main() {
// 追加:Seed値の設定(これが無いと同じ数字が返る)
rand.Seed(time.Now().UnixNano())
// 文字列の出力、 数字の部分は 0~10 の間でランダム
fmt.Println("My favorite number is", rand.Intn(10))
}
修正は加えましたが、もう一つ問題があって、、、
上の埋め込み Go環境 だと、これでも結果に同じ数字が表示されるんです。
これもページの説明に書いてありますが、「The Go Playground」(上の埋め込みGo環境のこと)では、実行時の状態が一定なため同じ数字が返されるとのことです。
具体的には、毎回変化してくれる値として「時刻」をシード値としましたが、「The Go Playground」で実行すると時刻が変化しないため、同じ数字が返される結果となるわけです。
下記は現在時刻を表示するプログラムですが、何時実行しても同じ値が返却されます。
package main
import (
"fmt"
"time"
)
func main() {
// 時刻(UTCから経過した秒数)を表示してみる
fmt.Println("time.Now().UnixNano() = ", time.Now().UnixNano())
}
といった諸々の理由があるため、自分のPC上で実行してみました。

ようやく数値部分がランダムに表示されていることを確認できましたね。
今回はこれでお終いですが、具体的な packages 定義の書き方をメモしておきます。
main に関する宣言方法
プログラムの起点(エントリポイント)となる main の宣言はこんな感じ。
プログラムソースの先頭部分で
package main
主処理を囲うように
func main() {
(主処理)
}
他のパッケージを使う(読み込む)場合
標準パッケージやその他のパッケージを使う場合、インポート宣言をします。
// fmt をインポートする場合
import "fmt"
// 複数のパッケージをまとめてインポートする場合
import (
"fmt"
"math"
)
今回のまとめ
今回はパッケージのお話でしたが、、、
サンプルプログラムはな~んかズレた内容でしたね…_(┐「ε:)_
それに、このお題をこなした程度では、まだまだプログラムを書けるレベルじゃありません。さらにGoを理解するためにも次回へ進みます。٩(`・ω・´)و
手探りな記事ですので、間違い勘違いあればコメント頂けると有り難いです。
コメント