Goプログラミング入門一覧

【Go入門】プログラムの構成とパッケージ

こんにちは。Go入門ブログの第3回です。
前回の記事では、Goのインストールと開発環境構築手順を解説し、実際にHello Worldの出力で動作確認を行いました。

【Go入門】Goのインストールと動作確認(Hello World)

Hello Worldを出力するサンプルコードがこちらです。

package main

import (
    "fmt"
)

func main() {
    fmt.Println("Hello World!")
}

今回の記事では、こちらのコードを題材にGoプログラムの基本的な構成を解説していきます。
また、このコードを複数ファイルに分割し、コンパイルして実行ファイルを生成する方法も紹介します。

Goプログラムファイルの基本構成

Goのプログラムファイルの基本的な構成は以下のようになっています。

  1. 所属するパッケージの宣言
  2. 使用するパッケージのインポート
  3. 処理の記述

Goのプログラムは、パッケージ(package)で構成されます。
Goにおけるパッケージとは名前空間を分けるための仕組みで、これによりモジュール性や再利用性などを提供しています。

Goでは、変数や関数などのプログラム要素は、すべて何らかのパッケージに所属している必要があります。

1. 所属するパッケージの宣言

先述の通り、Goではすべてのプログラム要素をパッケージに所属させなければいけません。
したがって、プログラムファイルの先頭では、このファイルに記述するコードがどのパッケージに所属するかを宣言します。

package main

ここではpackage mainという宣言で、このファイルがmainパッケージに属していることをメイジしています。

なお、1つのファイルに記述できるのは単一のパッケージについてのみであり、複数のパッケージを宣言することはできません。

2. 使用するパッケージのインポート

次に、プログラム内で使用するパッケージのインポートを宣言します。
サンプルコードの3-5行目がimport部です。

import (
    "fmt"
)

Goの標準ライブラリは、すべて固有の名前を持つパッケージとして提供されています。
ここでインポートしているfmtパッケージには、文字の入出力に関するライブラリがまとめられています。

もちろん標準ライブラリだけでなく、自分で作成したパッケージをインポートすることも可能です。
これについては後で詳しく解説します。

なお、特に使用するパッケージがない場合、import部の宣言は省略可能です。

3. 処理の記述

パッケージの宣言とインポートの宣言の後に、プログラムの本体となる処理部を記述します。

func main() {
    fmt.Println("Hello World!")
}

ここではfmtパッケージのPrintlnメソッドを使用し、”Hello World!”を出力しています。
Printlnメソッドは、引数で指定された文字列を標準出力に出力し、文字列の末尾に改行を追加します。

エントリポイント

Goでは、mainパッケージ内で定義された関数mainから処理の実行が開始されます。
この例で、パッケージ名または関数名のmainを変更するとプログラムは動作しません。

ソースコードを複数ファイルで管理する

先の例では、単一のプログラムファイルで単純なプログラムを作成しました。
しかし、実際の開発では、多くの場合ソースコードを複数のファイルに分割して管理することになります。

Goでは、パッケージを単位としてソースコードをファイルやディレクトリに分割し、プログラムを作成します。
ここでは先の例で使用したHello Worldを、複数のファイル・パッケージに分割してみましょう。

Hello Worldプログラムの構造

ここでは、Hello Worldを出力するプログラムを以下のような構成で管理したいと思います。

HelloWorld
 |- hello
 |    |- hello.go
 |    |- greet.go
 |
 |- main.go

まず、プログラムを格納するディレクトリ名をHelloWorldとします。
このディレクトリ名はそのままアプリケーションの名称にもなります。
HelloWorldの直下に、メイン処理を記述するmain.goファイルと、独自にhelloパッケージを定義するためのhelloディレクトリを作成します。

helloディレクトリの中には、helloパッケージの機能を記述するソースファイルであるhello.goとgreet.goを作成します。

なお、Goのコーディング規約では、パッケージ名とインポートパスの最後の要素を同じ名前にすることとされています。
このため、helloというパッケージを格納するディレクトリをhelloという名称にしています。
パッケージ名とディレクトリ名を異なる名称にすることもできますが、管理が煩雑になり特にメリットはないでしょう。

helloパッケージの作成

helloパッケージに属するファイルを以下の通り記述します。

package hello

func SayHello() string {
    return "Hello World!"
}
package hello

func Greet() string {
    return "How are you?"
}

いずれもhelloパッケージに所属させるため、先頭でpackage helloを宣言します。

hello.goには、文字列”Hello World”を返す関数SayHelloを定義しています。
greet.goには、文字列”How are you?”を返す関数Greetを定義しています。

注意が必要な点として、外部のパッケージから使用する関数や変数の名称は、先頭を大文字にする必要があります。
小文字ではじまる名称だと、外部からアクセスすることができません。

main.goの記述

メイン処理であるmain.goファイルの記述は以下のようになります。

package main

import (
    "fmt"

    "./hello"
)

func main() {
    fmt.Println(hello.SayHello())
    fmt.Println(hello.Greet())
}

まず、import宣言部にhelloパッケージが宣言されていることに注目してください。
相対パスで記述することで、import文が記述されているファイルから相対位置に置かれているパスを指定することができます。
なお、通常は環境変数GOPATHで指定されたパス内のパッケージが参照されます。

関数mainでは、helloパッケージで定義した関数SayHelloGreetをそれぞれ呼び出し、標準出力しています。

プログラムのビルド

前回はgo runコマンドでプログラムを実行しましたが、今回はプログラムをビルドして実行ファイルを作成してみます。

main.goファイルが配置されているディレクトリで、go buildコマンドをオプションを指定せずに実行してください。

$ go build

ビルドを実行したディレクトリ内に、実行ファイルHelloWorld(Windows環境ではHelloWorld.exe)が作成されたと思います。

オプションを指定せずにgo buildを実行した場合、以下のようにビルドが行われます。

  • カレントディレクトリの名前が実行ファイルの名称として使用される
  • カレントディレクトリ配下にある.go拡張子のファイルがすべてビルド対象となる

プログラムの実行

正常にビルドが行われたら、生成されたファイルを実行してみましょう。

$ HelloWorld
Hello World!
How are you?

上記のように、”Hello World!”と”How are you?”が改行して出力されれば成功です。

終わりに

今回は、Hello Worldを題材にGoプログラムの基本的な構成とビルド方法を解説しました。
ここまでの記事で、ファイル構成を正しく行い、処理を記述し、ビルドして実行することができるようになったはずです。

次回以降の記事では、変数の利用や型の扱い、制御文の記述といったGoの基本的な文法を解説していきます。


スポンサーリンク
スポンサーリンク
スポンサーリンク