🐭

[Go言語] ファイル分割とローカルパッケージ

2022/08/03に公開

ファイル分割無しの場合

  • 全ての関数が同じmain.goファイル内にある
ディレクトリ構造
project
 └─ main.go
main.go
package main

import (
	"fmt"
)

func foo() {
	fmt.Println("foo")
}

func bar() {
	fmt.Println("bar")
}

func main() {
	foo()
	bar()
}

同じパッケージ(ディレクトリ)内でファイル分割

  • 関数bar()を別のファイルbar.goに移動
ディレクトリ構造
project
 ├─ main.go
 └─ bar.go
main.go
package main

import (
	"fmt"
)

func foo() {
	fmt.Println("foo")
}

func main() {
	foo()
	Bar()	// 外部ファイルの関数を使用する場合、頭文字は大文字
}
bar.go
package main

import (
	"fmt"
)

func Bar() {	// 外部ファイルで使用される場合、頭文字は大文字
	fmt.Println("bar")
}

  • build及びrunをする際はmainパッケージ内の全てのファイルを指定する必要がある
build および run 時のコマンド
go build main.go bar.go
build および run 時のコマンド(go.mod が存在する場合)
go build .

別パッケージ(ディレクトリ)でファイル分割

  • 別のファイル(パッケージ)で関数Baz()を作成しmain.goで使用する
  • モジュール管理のファイルgo.modを作成する必要がある
ディレクトリ構造
project
 ├─ main.go
 ├─ bar.go
 ├─ pkg_baz
 │   └─ baz.go
 └─ go.mod
main.go
package main

import (
	"fmt"
	"project/pkg_baz"	// baz.go までのパス
)

func foo() {
	fmt.Println("foo")
}

func main() {
	foo()
	Bar()
	pkg_baz.Baz()	// パッケージ名を頭につける
}
baz.go
package pkg_baz	// パッケージ名はディレクトリ名と同じにする

import (
	"fmt"
)

func Baz() {
	fmt.Println("baz")
}
go.mod
module project	// モジュール名はディレクトリ名と同じにする

go 1.18
  • bar.goは変更なし

  • pkg_bazパッケージにさらにファイルを追加することも可能
ディレクトリ構造
project
 ├─ main.go
 ├─ bar.go
 ├─ pkg_baz
 │   ├─ baz.go
 │   └─ qux.go
 └─ go.mod
main.go
package main

import (
	"fmt"
	"project/pkg_baz"
)

func foo() {
	fmt.Println("foo")
}

func main() {
	foo()
	Bar()
	pkg_baz.Baz()
	pkg_baz.Qux()
}
qux.go
package pkg_baz	// パッケージ名は同じ

import (
	"fmt"
)

func Qux() {
	fmt.Println("qux")
}
  • bar.gobaz.gogo.modは変更なし

  • 同様にパッケージをさらに追加することも可能
ディレクトリ構造
project
 ├─ main.go
 ├─ bar.go
 ├─ pkg_baz
 │   ├─ baz.go
 │   └─ qux.go
 ├─ pkg_quux
 │   └─ quux.go
 └─ go.mod
main.go
package main

import (
	"fmt"
	"project/pkg_baz"
	"project/pkg_quux"
)

func foo() {
	fmt.Println("foo")
}

func main() {
	foo()
	Bar()
	pkg_baz.Baz()
	pkg_baz.Qux()
	pkg_quux.Quux()
}
quux.go
package pkg_quux

import (
	"fmt"
)

func Quux() {
	fmt.Println("quux")
}
  • bar.gobaz.goqux.gogo.modは変更なし

ローカルに存在するパッケージの読み込み

  • projectのディレクトリ外に存在するパッケージを読み込む
  • パッケージの作成はこれまで通り
  • パッケージ使用側(project)のgo.modにパス指定等が必要
ディレクトリ構造
─┬─ project
 │   ├─ main.go
 │   ├─ bar.go
 │   ├─ pkg_baz
 │   │   ├─ baz.go
 │   │   └─ qux.go
 │   ├─ pkg_quux
 │   │   └─ quux.go
 │   └─ go.mod
 │
 └─ pkg_orge
     ├─ orge.go
     └─ go.mod
main.go
package main

import (
	"fmt"
	"project/pkg_baz"
	"project/pkg_quux"
	"pkg_orge"	// パッケージ名
)

func foo() {
	fmt.Println("foo")
}

func main() {
	foo()
	Bar()
	pkg_baz.Baz()
	pkg_baz.Qux()
	pkg_quux.Quux()
	pkg_orge.Orge()
}
project/go.mod
module project

go 1.18

require (
    pkg_orge v0.0.0	// パッケージ名とバージョン
)

replace (
    pkg_orge => ../pkg_orge // パッケージ名 => project から pkg_orge までのパス
)
orge.go
package pkg_orge

import (
	"fmt"
)

func Orge() {
	fmt.Println("orge")
}
pkg_orge/go.mod
module pkg_orge

go 1.18
  • bar.gobaz.goqux.goquux.goは変更なし

Discussion