のんびりSEの議事録

プログラミング系のポストからアプリに関してのポストなどをしていきます。まれにアニメ・マンガなど

Goのmodulesを使用したlocal packageのimport

久しぶりにGoを触ったらライブラリの依存関係の管理方法が公式で追加されていたので、その備忘録です

Go Modulesとは

Go 1.11以降に組み込まれた、ライブラリの依存関係の解決を行うGoの標準機能

試行環境

Go Modulesを使用したパッケージのimport

  • aws-sdk-goを利用したS3 Bucketの一覧を出力する
package main

import (
    "fmt"

    "github.com/aws/aws-sdk-go/aws"
    "github.com/aws/aws-sdk-go/aws/awserr"
    "github.com/aws/aws-sdk-go/aws/session"
    "github.com/aws/aws-sdk-go/service/s3"
)

func main() {
    svc := s3.New(session.New(&aws.Config{Region: aws.String("ap-northeast-1")}))
    input := &s3.ListBucketsInput{}

    result, err := svc.ListBuckets(input)
    if err != nil {
        if aerr, ok := err.(awserr.Error); ok {
            switch aerr.Code() {
            default:
                fmt.Println(aerr.Error())
            }
        } else {
            fmt.Println(err.Error())
        }
        return
    }

    fmt.Println(result)
}
$ go mod init example.com/s3
$ go build
$ cat go. mod
module example.com/s3

go 1.15

require github.com/aws/aws-sdk-go v1.37.20

解説

  • go mod init [module]コマンドでgo.modファイルを作成する。
  • go.modファイルが含まれるディレクトリ配下でgo buildコマンドでビルドすることで、ファイル内でimportしたパッケージがgo.modファイルのrequireとして追記される
  • github上で公開されているパッケージに関しては、import文でgithub.com/${owner}/${repos}と記載することで依存パッケージとしてビルドに含まれる

非公開パッケージ(local等)をimportするには

greetingsという非公開モジュールを作成する

ディレクトリ作成

$ mkdir greetings
$ cd greetings

go.modファイル作成

$ go mod example.com/greetings
$ cat go.mod
module example.com/greetings

go 1.15

スクリプト作成(greetings.go)

package greetings

import "fmt"

func Hello(name string) string {
    message := fmt.Sprintf("Hi, %v. Welcome!", name)
    return message
}

greetingsモジュールを利用する側のモジュールを作成

$ cd ..
$ mkdir hello
$ cd hello
  • hello.go
package main

import (
    "fmt"

    "example.com/greetings"
)

func main() {
    message := greetings.Hello("Gladys")
    fmt.Println(message)
}
$ go mod init hello

非公開のモジュールを使用できるようにgo.modファイルを編集

  • hello/go.mod
module hello

go 1.15

# replace module名 => ディレクトリへのPath
replace example.com/greetings => ../greetings

ビルドし非公開モジュールが読み込まれていることを確認

$ go build
go: found example.com/greetings in example.com/greetings v0.0.0-00010101000000-000000000000
$ ./hello
Hi, Gladys. Welcome!
$ cat go.build
module hello

go 1.15

replace example.com/greetings => ../greetings

require example.com/greetings v0.0.0-00010101000000-000000000000
  • buildが成功すると、go.modファイルにrequire モジュール名 バージョンが追記される

ネストが深いモジュールへのアクセス

ディレクトリ作成

$ mkdir -p foo/bar
$ cd foo/bar
$ go mod example.com/foo/bar
  • foo/bar/bar.go
package bar

import "fmt"

func Bar() {
    fmt.Println("foo/bar")
}

読み込み元のgo.modとimportを編集

  • hello/hello.go
package main

import (
    "fmt"

    "example.com/foo/bar"
    "example.com/greetings"
)

func main() {
    message := greetings.Hello("Gladys")
    fmt.Println(message)
    bar.Bar()
}
  • hello/go.mod
module hello

go 1.15

replace example.com/greetings => ../greetings

replace example.com/foo/bar => ../foo/bar

ビルドし非公開モジュールが読み込まれていることを確認

$ go build
go: found example.com/foo/bar in example.com/foo/bar v0.0.0-00010101000000-000000000000
$ ./hello
Hi, Gladys. Welcome!
foo/bar

参考

golang.org

qiita.com