Golangのpackage/importについて+簡単なtestコードを書いてみる


前回はGoのインストールと、VSCodeで環境を整えてハローワールドするところまでやった。
今回はディレクトリの構成の話と、簡単なテストコードを書いて実行するところまでやってみる。

package

Goではすべての要素は、何らかのパッケージに属していなければならない。

また、1つのファイルに記述できるのは単一のパッケージのみで、複数パッケージを宣言するとエラーとなる。

Goで書かれたプログラムは package main と宣言したファイルの中の、 mainメソッドからスタートすることになる。

また、1つのディレクトリには1種類のパッケージ定義のみ許容される。
→これはイメージを掴むために実際にやってみる。試しに以下のようなファイル構成をとってみた。

.
├── hello.go
└── hey.go

そして、片方のファイルの中でmainではないパッケージ名を宣言してみる

hey.go
package hey

func hey() {
  // nothing to do
}

すると確かに下記のような感じで怒られる

> go build
can't load package: package Hello: found packages main (hello.go) and hey (hey.go) in /Users/user/go/src/Hello

フォルダ名や宣言しているpackage名に気をつける必要があることがわかった。

import

他のパッケージの要素をそのファイルで使用するために使う。

前回ハローワールドしたときも、文字列の出力のために必要なfmtをインポートしていた。

※importしたのに使わなかったパッケージがあると、コンパイル時にエラーが出てしまう

goTest.go
package main

import "fmt"
import "notRefered" // 参照されていないパッケージ

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

goTest.go:3:8: cannot find package "notRefered" in any of:
    /usr/local/go/src/notRefered (from $GOROOT)
    /Users/user/go/src/notRefered (from $GOPATH)

しかし、これに関しては、前回紹介したVSCodeの環境であれば勝手にimport文を削除or追加してくれた。

ファイル分割してみる

こんな感じのファイル構成にしてみた

greeting
    ├── countries
    │   ├── china.go
    │   ├── germany.go
    │   └── japan.go
    └── main.go
main.go
package main

import "fmt"
import "./countries"

func main() {
    fmt.Println(countries.SayHelloInJapanese())
    fmt.Println(countries.SayHelloInChinese())
    fmt.Println(countries.SayHelloInGerman())
}

importで、package名だけ書くと、$GOPATHを見に行くので、自分で他のディレクトリに作成したパッケージをimportしたい場合は、上記のように相対パスで指定してあげる必要がある。

china.go
package countries

func SayHelloInChinese() string {
    return "Nihao!"
}
japan.go
package countries

func SayHelloInJapanese() string {
    return "Konnichiha!"
}
germany.go
package countries

func SayHelloInGerman() string {
    return "GutenTag!"
}

実行

> go run main.go
Konnichiha!
Nihao!
GutenTag!

Testコード書いてみる

Goでは*_test.go となっているファイルはテストコードとして扱ってくれる。

先程のcountriesパッケージのテストコードを作成する。

countries_test.go
package countries

import "testing"

func TestSayHelloInJapanese(test *testing.T) {
    expect := "Konnichiha!"
    actual := SayHelloInJapanese()
    if expect != actual {
        test.Errorf("%s != %s", expect, actual)
    }
}
func TestSayHelloInChinese(test *testing.T) {
    expect := "Nihao!"
    actual := SayHelloInChinese()
    if expect != actual {
        test.Errorf("%s != %s", expect, actual)
    }
}
func TestSayHelloInGerman(test *testing.T) {
    expect := "GutenTag!"
    actual := SayHelloInGerman()
    if expect != actual {
        test.Errorf("%s != %s", expect, actual)
    }
}

ディレクトリ階層はこんな感じ

├── countries
│   ├── china.go
│   ├── countries_test.go
│   ├── germany.go
│   └── japan.go
└── main.go

テストを実行してみる

> go test ./countries -v
=== RUN   TestSayHelloInJapanese
--- PASS: TestSayHelloInJapanese (0.00s)
=== RUN   TestSayHelloInChinese
--- PASS: TestSayHelloInChinese (0.00s)
=== RUN   TestSayHelloInGerman
--- PASS: TestSayHelloInGerman (0.00s)
PASS
ok      greeting/countries      0.005s

無事にテストが実行され、PASSできた