Go

Golangで自分自身で定義したパッケージをインポートする方法あれこれ

More than 3 years have passed since last update.

Go初心者の自分が躓いたのでメモ
Go速習会という記事を参考に自分自身で実行していた所躓いた.

本題

たとえば,goのnegroniというWAFでwebアプリケーションを作成しようとしていたとする.

ツリー構造は以下の通り.

.
├── models
│   └── user.go
├── public
│   └── index.html
└── server.go

各ファイルは以下の通り

server.go

package main

import (
        "fmt"
        "github.com/codegangsta/negroni"
        "github.com/[username]/[appname]/models" // 自分のパッケージ
        "net/http"
)

func main() {
        mux := http.NewServeMux()
        mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
                user := models.NewUser("Tanaka Tarou", 10)
                fmt.Fprintln(w, user)
        })
        n := negroni.Classic()
        n.UseHandler(mux)
        n.Run(":8080")
}
models/user.go
package models

import "strconv"

// User defines an user
type User struct {
        ID   int
        Name string
        Age  int
}

// NewUser creates user instance
func NewUser(name string, age int) *User {
        return &User{
                Name: name,
                Age:  age,
        }
}

func (u *User) String() string {
        return u.Name + "(" + strconv.Itoa(u.Age) + ")"
}

server.goというファイルがメインになっており,
モデルとして定義したmodels/user.goの NewUser関数をmain関数で利用する時,

server.go
import (
        "fmt"
        "github.com/codegangsta/negroni"
        "github.com/[username]/[appname]/models" // 自分のパッケージ
        "net/http"
)

このようにして,自分自身のモデルを定義しなければならない.

特に意識せずに,このまま実行すると…

$ go run server.go 
server.go:6:2: cannot find package "github.com/[username]/[appname]/models" in any of:
    /usr/local/opt/go/libexec/src/github.com/[username]/[appname]/models (from $GOROOT)
    /Users/[username]/src/github.com/[username]/[appname]/models (from $GOPATH)

このようにしてエラーが起きる.

その1(推奨)

@1l0さんより推奨していただいた方法です.

$GOPATH/src/github.com/[username]/[appname]
この中で最初から作業をしてしまう.

つまり,今回の場合では,
/Users/[username]/src/github.com/[username]/[appname]
という場所を作り,はじめからそのdir配下で作業をすれば良い事になる.

github.com
└── [username]
    └── [appname]
        ├── models
        │   └── user.go
        ├── public
        │   └── index.html
        └── server.go

これで最初から$ go get などせずに済む.

その2

githubにpushする.

$ git init
$ git add .
$ git commit -m "update model"
$ git remote add origin [githubのリポジトリ]
$ git push origin master

次に,githubへのpushが完了した事を確認してから,

$ go get github.com/[username]/[appname]/models

を実行し,再び$ go run server.goをすると上手くいく.

その3(非推奨)

相対パスでpackageを指定する方法.
Go言語でローカルパッケージをインポートという方法があるらしい.

しかし,一般的にはオススメされている方法では無いそうです.

以下は,@1l0さんのコメントより引用です.

相対パスは以下の理由でお勧めしません。

  • 毎度pkg化することになるのでコンパイルが遅い
  • 他人が普通にgo getできない