1. Home
  2. Golang
  3. GuideToBecomingGoDeveloper
  4. LearnTheBasics
  5. パッケージ(Packages)- Golang learning step 1-7

パッケージ(Packages)- Golang learning step 1-7

  • 公開日
  • カテゴリ:LearnTheBasics
  • タグ:Golang,roadmap.sh,学習メモ
パッケージ(Packages)- Golang learning step 1-7

roadmap.sh > Go > Learn the Basics > Packages の学習を進めていきます。

※ 学習メモとしての記録ですが、後にこのセクションを学ぶ道しるべとなるよう、ですます調で記載しています。

contents

  1. 開発環境
  2. パッケージ(Packages)
  3. パッケージの役割
  4. パッケージの作成方法
  5. パッケージのインポート
  6. パッケージの公開
  7. 標準ライブラリのパッケージ
  8. パッケージ管理ツール(go modules)
    1. モジュールの初期化と設定
    2. 依存関係の管理
    3. 依存関係の整理・最適化(go mod tidy)
  9. モジュールの命名
    1. モジュールパスの形式
    2. 接頭辞
    3. コントロールできる名前を選ぶ
    4. 説明的なテキスト
    5. 具体的な命名例
  10. パッケージのドキュメント生成(go doc)
    1. ドキュメントの書き方
    2. 特徴
    3. godoc コマンドの使用

開発環境

  • チップ: Apple M2 Pro
  • OS: macOS Sonoma
  • go version: go1.23.2 darwin/arm64

パッケージ(Packages)

Go のパッケージは、Go におけるコードの整理と再利用のための基本的な単位です。パッケージは、関連する関数、型、変数、定数をまとめて管理し、他のコードからそれらを使いやすくする仕組みです。

パッケージの役割

Go のパッケージは、コードをモジュール化し、関数や変数のスコープを管理するために使われます。大規模なプロジェクトでは、複数のパッケージを使用することで、コードの可読性や保守性を向上させます。

  • 関数や変数を機能ごとに分けてパッケージにまとめることで、プロジェクトを論理的に分割できます。(コードの整理)
  • Go ではパッケージごとに名前空間が異なるため、同じ名前の関数や変数を別のパッケージで使うことができます。(名前の衝突を防ぐ)
  • パッケージは一度作成すると、他のプロジェクトでも簡単にインポートして再利用できます。(再利用可能)

パッケージの作成方法

パッケージは、ソースファイルの先頭に package キーワードで定義されます。たとえば、my_math パッケージを作成する場合、以下のように宣言します。

// myproject/my_math/my_math.go

package my_math

func Add(a int, b int) int {
  return a + b
}

この my_math パッケージには、Add 関数が含まれており、my_math パッケージをインポートする他のファイルから利用可能です。

パッケージのインポート

他のパッケージを使用するには、import 文を使います。標準ライブラリや外部パッケージをインポートする際も、同じ手法で行います。以下は、標準ライブラリの fmt と、ユーザー定義の my_math パッケージをインポートする例です。

// myproject/main.go
package main

import (
  "fmt"
  "myproject/my_math" // 自分のプロジェクト内のパッケージ
)

func main() {
  result := my_math.Add(3, 4)
  fmt.Println(result)
  // => 7
}

パッケージの公開

Go では、パッケージ内の関数や変数が大文字で始まる場合にのみ、他のパッケージからアクセスできます。たとえば、Add という関数は公開されますが、subtract という関数は同じパッケージ内でのみ使えます。

package my_math

// 公開される関数
func Add(a int, b int) int {
  return a + b
}

// 非公開の関数
func subtract(a int, b int) int {
  return a - b
}

標準ライブラリのパッケージ

Go には非常に多くの標準パッケージが用意されており、以下はよく使われるパッケージの一部です。

  • fmt: 標準出力や文字列フォーマットに使います。
  • strings: 文字列操作に便利な関数が含まれています。
  • io, os: ファイルの入出力処理やシステム操作を行います。
  • net/http: HTTPサーバーやクライアントを扱うためのパッケージです。
  • time: 日付や時刻を扱うための関数が含まれています。

標準ライブラリは、pkg.go.dev から検索できます。

パッケージ管理ツール(go modules)

Go のパッケージ管理は、かつて GOPATH という概念に依存していましたが、現在(Go 1.11 以降)では go modules が標準となっており、go.mod ファイルを使って、依存関係の管理が行われます。

go mod init コマンドでプロジェクトをモジュール化し、依存パッケージを管理できます。

go mod init myproject

# => go: creating new go.mod: module myproject
#    go: to add module requirements and sums:
#        go mod tidy

go mod init を実行すると、現在のディレクトリに go.mod というファイルが生成されます。このファイルは、Go モジュールのプロジェクトを管理するための設定ファイルです。go.mod には、以下のような基本情報が記載されます。

module myproject

go 1.23.2
  • module myproject: これはモジュール名を表します。myproject がモジュール名として設定されますが、通常これはリポジトリの URL やプロジェクトの名前になります(例: github.com/user/myproject)。
  • go 1.23.2: プロジェクトが使用する Go のバージョンが指定されます。go mod init を実行した環境で使用している Go のバージョンが自動的に挿入されます。

モジュールの初期化と設定

go mod init コマンドを実行することで、現在のディレクトリがモジュールとして扱われます。これにより、プロジェクト内のコードは Go Modules の仕組みを使って依存関係を管理できるようになります。

モジュール化されると、プロジェクトは従来の GOPATH から独立し、プロジェクトディレクトリのどこにでも配置できます。(Go 1.11 以降、GOPATH の制約から解放されました)

Go では、モジュールはパッケージの集合体として機能します。モジュール化により、プロジェクト内のパッケージの依存関係を適切に管理し、外部パッケージのインポートも効率的に行えるようになります。

依存関係の管理

go mod init で生成された go.mod ファイルは、プロジェクトが依存する外部パッケージ(モジュール)を記録します。たとえば、外部ライブラリをインポートして使用した場合、go ツールが自動的に依存関係を解決し、go.mod にその情報が追加されます。

次に go get コマンドなどを実行すると、そのパッケージが自動的にダウンロードされ、go.mod に依存パッケージが以下のように追加されます。

go get github.com/gin-gonic/gin
# github.com/gin-gonic/gin パッケージとその依存パッケージがダウンロードされる
module myproject

go 1.23.2

require github.com/gin-gonic/gin v1.7.4

go.mod に依存する外部パッケージとそのバージョンが require セクションに記載されます。たとえば、ここでは github.com/gin-gonic/gin というパッケージのバージョン v1.7.4 が依存として追加されています。

また、依存パッケージの具体的なバージョン情報や、ソースの取得先の情報などは go.sum という別のファイルに管理されます。

go.sum ファイルの例:

github.com/gin-gonic/gin v1.7.4 h1:checksum...
github.com/gin-gonic/gin v1.7.4/go.mod h1:checksum...
# その他依存パッケージのバージョンやチェックサムも含まれる

コードにパッケージをインポートして利用

パッケージが追加されたので、プロジェクトのコード内で github.com/gin-gonic/gin パッケージをインポートして使用できます。main.go ファイルを作成し、簡単な Gin サーバーを実装してみましょう。

package main

import "github.com/gin-gonic/gin"

func main() {
  r := gin.Default()
  r.GET("/", func(c *gin.Context) {
    c.JSON(200, gin.H{
      "message": "Hello, world!",
    })
  })
  err := r.Run() // デフォルトで :8080 ポートで実行
  if err != nil {
    return
  }
}

コードを実行して、Gin が正しくインポートされて動作するか確認します。

go run main.go

ブラウザで http://localhost:8080 にアクセスすると、以下のような JSON レスポンスが表示されます。

{
    "message": "Hello, world!"
}

これで、外部パッケージ github.com/gin-gonic/gin が依存として追加され、プロジェクト内で使用できるようになりました。

依存関係の整理・最適化(go mod tidy)

go mod tidy コマンドは、Go Modules の依存関係を整理・最適化するためのコマンドです。このコマンドを実行することで、go.mod と go.sum ファイルが最新の状態に保たれ、不要な依存関係が削除され、必要な依存関係がすべて追加されます。

具体的な役割:

  1. 不要な依存関係を削除
    • 以前にインポートされていたけれども、現在はプロジェクト内で使われていないパッケージが go.mod から削除される。
    • 例えば、ある外部ライブラリをインポートしていたが、そのライブラリのコードを削除した場合、依存関係だけが go.mod に残ることがある。このような不要な依存関係を整理できる。
  2. 必要な依存関係を追加
    • プロジェクトのソースコード内で新たに使用されたパッケージが、まだ go.mod に登録されていない場合、自動的に追加される。
    • 例えば、新しいパッケージを使用したけれども、go get コマンドを実行していない場合、このコマンドを使うことでそのパッケージの依存関係が解決される。
  3. go.sum の更新
    • go.sum ファイルには、go.mod に記載された各パッケージの正しいバージョンとそのチェックサム(整合性を保つための値)が記録されている。
    • go mod tidy を実行すると、最新の依存関係に基づいて go.sum が更新され、不要なエントリが削除され、必要なエントリが追加される。

モジュールの命名

モジュールパスの形式

モジュールパスは、モジュール(プロジェクトやライブラリ)の一意な名前です。 通常は次の形式をとります。

<接頭辞>/<説明的なテキスト>

接頭辞

接頭辞は、モジュールがどこから来たか(起源)を示す部分です。これにより、Goツールがそのモジュールのソースコードをどこで見つけられるかが分かります。

例えば、GitHub のリポジトリからモジュールを提供する場合、次のような形式にします。

github.com/<プロジェクト名>/

公開するモジュールの場合、リポジトリの場所が他の人にも分かるように接頭辞を設定します。

コントロールできる名前を選ぶ

自分だけが使う非公開モジュールやリポジトリ名を使わない場合には、他人と名前がかぶらない接頭辞を選びます。例えば、widgets や utilities のような一般的な名前は避け、他の人が使わないことを確認できる名前にする必要があります。

説明的なテキスト

接頭辞の後に続く部分は、プロジェクトの名前や機能を表す「説明的なテキスト」です。このテキストはモジュールが何をするものかを示します。

具体的な命名例

公開されているモジュールの例

もし GitHub にプロジェクトを公開しているなら、次のようにモジュールパスを設定します

github.com/example/myproject

公開についての詳細は「モジュールの開発と公開」を参照。

非公開で他の人と名前が衝突しないようにする場合

自分のプロジェクト用の特定の接頭辞を作り、次のように設定します。

myorg.com/internal/mytool

パッケージのドキュメント生成(go doc)

go doc は、Go のコードから自動的にドキュメントを生成するためのツールと規約のことです。これはGoの重要な機能の一つで、コードの可読性と保守性を高めるのに役立ちます。

ドキュメントの書き方

関数、型、パッケージの直前にコメントを書くことで、そのコメントがドキュメントとして扱われます。

パッケージレベルのコメントは、パッケージ宣言の直前に書きます。

関数や型のコメントは、その定義の直前に書きます。

myproject/mathutils/mathutils.go

// Package mathutils は数学的操作のためのユーティリティ関数を提供します。
package mathutils

// Add は2つの整数の和を返します。
// 2つのint型のパラメータを受け取り、その和を返します。
func Add(a, b int) int {
  return a + b
}

// Multiply は2つの整数の積を返します。
// 2つのint型のパラメータを受け取り、その積を返します。
func Multiply(a, b int) int {
  return a * b
}

特徴

  • コードと一緒にドキュメントを管理できるため、コードの変更に合わせてドキュメントも更新しやすくなる。
  • 標準的なフォーマットで書かれるため、一貫性のあるドキュメントを作成できる。
  • godoc コマンドを使用して、ターミナルで直接ドキュメントを閲覧できる

godoc コマンドの使用

  • go doc <パッケージ名>: パッケージのドキュメントを表示
  • go doc <パッケージ名>.<関数名>: 特定の関数のドキュメントを表示
% go doc mathutils

# package mathutils // import "myproject/mathutils"
# 
# Package mathutils は数学的操作のためのユーティリティ関数を提供します。
# 
# func Add(a, b int) int
# func Multiply(a, b int) int
% go doc mathutils.Add

# package mathutils // import "myproject/mathutils"
# 
# func Add(a, b int) int
#     Add は2つの整数の和を返します。 2つのint型のパラメータを受け取り、その和を返します。

まとめ

  • Go のパッケージは、コードの整理と再利用を促進する基本単位であり、関数や変数を論理的に分割して管理できる。
  • パッケージを使うことで、名前の衝突を避け、再利用性の高いコードを書くことが可能。
  • パッケージの公開・非公開は関数名や変数名の大文字・小文字によって制御される。
  • 標準ライブラリには、よく使われる機能を提供する便利なパッケージが多数用意されている。
  • Go Modules を使って依存関係を簡単に管理でき、GOPATH に依存せずにプロジェクトを整理できる。
  • go mod tidy コマンドで、依存パッケージの整理と最適化が可能。
  • go doc を使えば、自動的にドキュメントを生成し、コードの可読性や保守性を向上させることができる。
  • パッケージやモジュールは論理的かつ一貫した命名規則に従って管理され、外部との依存関係も適切に設定される。


[Next] Step 1-8: 関数(Functions)

[Prev] Step 1-6: 型キャスト(Type Casting)

Author

rito

  • Backend Engineer
  • Tokyo, Japan
  • PHP 5 技術者認定上級試験 認定者
  • 統計検定 3 級