アプリ開発の第一歩!Go言語のパッケージ管理の基本を知ろう

Go言語
この記事は約9分で読めます。
Go初学者
Go初学者

main.goファイルだけでプログラムのコードを書くと、とても読みにくいんですが…

この記事ではGo言語のパッケージ管理の基本が理解できます!
  • main.go ファイルだけでなくファイルを分割して管理する基本的な方法
  • パッケージ管理の前準備について
  • パブリックとプライベートの違いをプログラムで確認

今回はGo言語のパッケージ管理の基本をお伝えしていきます。

当ブログの入門編では main.go ファイルひとつでプログラムの動きを確認していきました。

Goの文法を学習するには main.go だけで問題ないのですが、アプリ開発ともなればプログラムの行数が多くなり確認作業も大変です。

Goでは、あなたが管理しやすいように機能ごとなどにファイルを分割してパッケージを自作することができます。

この記事では、パッケージ管理の基本的なことを理解していきましょう。

もりぴ
この記事を書いた人

XHTML1.0時代にHTML&CSSを勉強した経験あり。無趣味だった私が2020年5月からプログラミング学習を開始し現在も挫折せずに趣味で学習を楽しんでいる51歳。プログラミングの楽しさをブログを通してお伝えしていきます。

もりぴをフォローする

今回の学習するパッケージ管理の構成

今回は下記のようなパッケージ管理の構成にします。

morip@morip-PC1:~/go/src/package$ tree
.
├── go.mod
├── main.go  // プログラムのメイン
└── myapp  // フォルダ名をパッケージ名に
    ├── myfunc.go  // 関数を管理するファイル
    └── myvar.go  // 定数・変数を管理するファイル

1 directory, 4 files

パッケージ管理をする場合は GOPATH のフォルダ内に src フォルダを作成してから、その直下に管理対象のフォルダを作成していきます。

もりぴ
もりぴ

src フォルダの直下にしないとエラーの原因になります。

パッケージ管理の前準備

goのバージョン1.13から go mod でモジュール管理が推奨されていますので、go mod モジュールをインストールする必要があります。

まずは、ターミナルを開いてからパッケージ管理するフォルダまで移動します。

cd コマンドで移動したら go mod init と入力して実行しましょう。

// パッケージ管理の前準備
morip@morip-PC1:~/go/src$ cd package/
morip@morip-PC1:~/go/src/package$ go mod init
go: creating new go.mod: module ini_test
go: to add module requirements and sums:
        go mod tidy

「依存パッケージの管理のために go mod tidy コマンドを実行してください」という内容のメッセージがでますが、今の段階で go mod tidy コマンドを実行すると…

// go mod tidyの実行結果
morip@morip-PC1:~/go/src/package$ go mod tidy
morip@morip-PC1:~/go/src/package$ 
もりぴ
もりぴ

何も実行されません。

go mod tidy コマンドの実行は、プログラムファイルを実行する時に行いましょう。

go mod tidy不要な依存パッケージの削除や追加を行ってくれるコマンドです。

ちなみに今回のプログラムでは、依存パッケージを使用しないので go mod tidy コマンドを実行しなくてもプログラムは正常に動作します。

今の段階では、下記のファイル構成でOKです。

morip@morip-PC1:~/go/src/package$ tree
.
├── go.mod  // go.modが自動で作成される
├── main.go  // プログラムのメイン

go mod init しなくてもプログラムコードを書いているときはエラーにはなりませんが、環境によっては go run main.go を実行すると…

$ go run main.go
main.go:5:2: package package/myapp is not in GOROOT (/usr/lib/go-1.16/src/package/myapp)

というエラーになるかもしれません。

エラー回避のためにも go mod init は実行しておきましょう。

パッケージ管理実践編

それではパッケージ管理を実践していきます。

今回のフォルダ構成やファイル構成は、あくまでも基本を学ぶための一例です。

パッケージフォルダの作成とファイル作成

下記のような構成を作成していきましょう。

morip@morip-PC1:~/go/src/package$ tree
.
├── go.mod
├── main.go  // プログラムのメイン
└── myapp  // フォルダ名をパッケージ名に
    └── myvar.go  // 定数・変数を管理するファイル
ここまでの作業手順
  1. package フォルダの直下に myapp フォルダを作成
  2. 定数と変数を管理するファイルとして myvar.go を作成

各ファイルの内容は下記の通りです。

// myvar.go

package myapp  // パッケージ名

const (
    Max = 100
    Min = 1
)

var Age int = 51
// main.go

package main

import (
    "fmt"
    "package/myapp"  // package myappをインポート
)

func main() {
    // 定数呼び出し
    fmt.Println(myapp.Max)
    fmt.Println(myapp.Min)

    // 変数呼び出し
    fmt.Println(myapp.Age)
}

myvar.go はパッケージ名として package myapp と宣言しています。

main.go では、myvar.go の変数と定数を利用するために "package/myapp"import で宣言しています。

もりぴ
もりぴ

では、出力結果を確認しましょう。

// 出力結果
$ go run main.go 
100
1
51

package myapp の変数と定数が無事に package main から出力されました。

他のパッケージから関数を呼び出してみよう

他のパッケージ(main package以外)で定義した関数を呼び出して実行してみます。

morip@morip-PC1:~/go/src/package$ tree
.
├── go.mod
├── main.go  // プログラムのメイン
└── myapp  // フォルダ名をパッケージ名に
    ├── myfunc.go  // 関数を管理するファイル(今回はここ)
    └── myvar.go 

1 directory, 4 files

myapp フォルダの直下に myfunc.go というファイルを作成します。

スライスの値の平均値を戻り値にしたプログラムで、下記のようにコードを記述してみました。

// myfunc.go

package myapp

func Ave(sl []int) int {
    // 合計用変数
    sum := 0
    // スライスの値を取り出す(インデックス不要)
    for _, v := range sl {
        // 合計を求める
	sum += v
    }
    // 戻り値で平均値を返す
    return int(sum / len(sl))
}
// main.go

package main

import (
    "fmt"
    "package/myapp"
)

func main() {
    // スライス作成
    sl := []int{10, 20, 30, 40, 50}

    // myapp.Ave()を呼び出して実行
    a := myapp.Ave(sl)
    fmt.Println(a)
}
// 出力結果
$ go run main.go 
30
もりぴ
もりぴ

無事に myfunc.gomyapp.Ave を実行することができました!

パブリックとプライベート

myvar.go のプログラムを利用して、パブリックプライベートについてお伝えしましす。

// myvar.go

package myapp  // パッケージ名

const (
    Max = 100
    min = 1  // minの頭文字を小文字に変更
)

var Age int = 51

Go言語ではパブリックは大文字、プライベートでは小文字で記述します。

POINT

パブリックは外部のパッケージから読み込むことができますが、プライベートは同一ファイル内からのみ読み込み可能で外部からは読み込みできません。

// 出力結果
$ go run main.go 
# command-line-arguments
./main.go:11:17: cannot refer to unexported name myapp.min

「エクスポートされていない名前を参照することはできません」というエラーになります。

ただし、下記のように関数を通して読み込むこともできます。

// myvar.go

package myapp  // パッケージ名

const (
    Max = 100
    min = 1  // minの頭文字を小文字に変更
)

// 小文字でも同一ファイル内はOK
func Exp() {
    fmt.Println(min)
}
// main.go

package main

import (
    "fmt"
    "package/myapp"
)

func main() {
    // 定数呼び出し
    fmt.Println(myapp.Max)

    // 下記はエラー
    // fmt.Println(myapp.min)

    // 関数を通して呼び出し
    myapp.Exp()
}
// 出力結果
$ go run main.go 
100
1  // 定数minを呼び出し

あまり使用されることはありませんが、パブリックとプライベートの違いを理解していただけるでしょう。

【まとめ】Go言語のパッケージ管理の基本

今回はGo言語のパッケージ管理の基本についてお伝えしてきました。

それでは、まとめにはいりましょう。

見出し
  • Go言語では自作でパッケージが作成できファイルを分割することができる
  • パッケージを管理するには GOPATH 内の src フォルダの直下にフォルダを作成する
  • goのバージョン1.13から go mod でモジュール管理が推奨
    ターミナルからパッケージ管理するフォルダまで移動して go mod init を実行
  • Go言語ではパブリックは大文字プライベートでは小文字で記述

以上です。

今回の例はあくまでも学習のため(プログラムの動きを確認するため)のパッケージ管理となります。

実際のアプリ開発では、設計段階でパッケージ構成が決定されるでしょう。

個人がGo言語でアプリ開発するにしても、main.go ファイルだけでは管理できなくなるはずです。

ぜひパッケージ管理の基本は押さえておきましょう。

comment

タイトルとURLをコピーしました