【追記】AppEngine Goで、go-app-builder: Failed parsing input: app file users.go conflicts with same file imported from GOPATH と叱られる問題
問題
AppEngineなアプリケーションをGoで開発していて、もちろんコントローラとかモデルとかは、initがあるところとは別のディレクトリ切って作ったりするんだけど、意気揚々とgoapp serve ./すると以下のように叱られる
% goapp serve ./ # 中略 ERROR 2016-05-07 16:19:44,645 go_runtime.py:179] Failed to build Go application: (Executed command: /Users/otiai10/.gcp/go_appengine/goroot/bin/go-app-builder -app_base /Users/otiai10/proj/go/src/github.com/otiai10/foo -arch 6 -dynamic -goroot /Users/otiai10/.gcp/go_appengine/goroot -nobuild_files ^^$ -unsafe -gopath /Users/otiai10/proj/go -print_extras_hash app/main.go app/controllers/citation.go) 2016/05/07 18:19:44 go-app-builder: Failed parsing input: app file users.go conflicts with same file imported from GOPATH
調査
- google app engine - How to import local Golang package in GAE - Stack Overflow
- google app engine - Go Package Conflict - Stack Overflow
- go - Good way to use and test local packages in Google App Engine apps written in golang? - Stack Overflow
- Go Runtime Environment - Go — Google Cloud Platform
- go - Golang how to import local packages without gopath? - Stack Overflow
- Google Go AppEngine imports and conflicts when serving / testing - Stack Overflow
- "This will cause two imports, one by appengine when it scans the directories, and a second by your source when it is explicitly imported."
appengineによるimportと、そこでimportされたソースコードによるimport(自分のケースだとmain.goがimportしてる)が、同じファイルをimportしようとしているっぽい。
解決
import "myproject/handler"
ベンダー込みの$GOPATH/src/github.com/otiai10/foo/controllersではなくて、app.yamlから見た相対pathを以下のように書く
import (
"net/http"
- "github.com/otiai10/foo/app/controllers"
+ "app/controllers"
)
この際、
"./app/controllers"
であってもgoappは動かない。でもapp/controllersにしなきゃならんので、govetから以下のように叱られる。
cannot find package "app/controllers" in any of: 以下いつもの
うーん... appengineなruntimeからではないビルドを除外するために、controllers/users.goの冒頭に以下を加えても同じ
+// +build appengine +
このwarningうざいんだけど、とりあえず動くからこの方向で行く
DRY
追記: 2016/05/09
goappによって2重インストールになってしまう問題は上記のように解決したけれど、cannot find packageになってしまうのはじゃっかんうざいので、以下のように、app.yamlとimportする側のmain.goがあるところ、importされるsrcがあるところを分けたことによって解決した。
foo
├── README.md
├── app
│ ├── app.yaml
│ └── main.go
└── src
├── controllers
│ ├── users.go
│ └── index.go
で、起動は
goapp serve ./app/app.yaml # または # goapp serve app # これでもちゃんと ./app/app.yaml をさがしてくれる
DRY