我对Golang很陌生,并尝试制作一个简单的REST api应用程序。
最初,一切都很好,因为我在main
包下的同一目录中包含了所有代码。
但是,现在我处于一个需要开始将代码重构为子目录和包的阶段。不幸的是,我无法成功编译应用程序。
我的GOPATH
设置为:~/.workspace
当前的应用位于:~/.workspace/src/gitlab.com/myapp/api-auth
这就是我目前的代码组织:
这是我的main.go
package main
import (
"net/http"
"os"
"strings"
"github.com/gorilla/context"
"github.com/justinas/alice"
"gopkg.in/mgo.v2"
"gitlab.com/myapp/api-auth/middlewares"
)
func main() {
privateKey := []byte(strings.Replace(os.Getenv("JWT_KEY"), "\\n", "\n", -1))
conn, err := mgo.Dial(os.Getenv("MONGO_CONN"))
if err != nil {
panic(err)
}
defer conn.Close()
conn.SetMode(mgo.Monotonic, true)
ctx := appContext{
conn.DB(os.Getenv("MONGO_DB")),
privateKey,
}
err = ctx.db.C("users").EnsureIndex(mgo.Index{
Key: []string{"username"},
Unique: true,
Background: true,
Sparse: false,
})
if err != nil {
panic(err)
}
commonHandlers := alice.New(LoggingHandler, context.ClearHandler, RecoveryHandler, AcceptHandler, ContentTypeHandler)
router := NewRouter()
router.Post("/users", commonHandlers.Append(BodyParserHandler(UserResource{})).ThenFunc(ctx.userCreationHandler))
router.Post("/sessions", commonHandlers.Append(BodyParserHandler(UserResource{})).ThenFunc(ctx.sessionCreationHandler))
http.ListenAndServe(":8080", router)
}
type appContext struct {
db *mgo.Database
privateKey []byte
}
这是中间件accept.go
之一(其余的中间件类似地构建)
package middlewares
import "net/http"
// AcceptHandler ensures proper accept headers in requests
func AcceptHandler(next http.Handler) http.Handler {
fn := func(w http.ResponseWriter, r *http.Request) {
if r.Header.Get("Accept") != "application/vnd.api+json" {
writeError(w, errNotAcceptable)
return
}
next.ServeHTTP(w, r)
}
return http.HandlerFunc(fn)
}
这是我从应用的根目录运行go build
时出现的错误。
# gitlab.com/utiliti.es/api-auth
./main.go:11: imported and not used: "gitlab.com/myapp/api-auth/middlewares"
./main.go:42: undefined: LoggingHandler
./main.go:42: undefined: RecoveryHandler
./main.go:42: undefined: AcceptHandler
./main.go:42: undefined: ContentTypeHandler
./main.go:45: undefined: BodyParserHandler
./main.go:46: undefined: BodyParserHandler
答案 0 :(得分:13)
The Go Programming Language Specification
限定标识符是使用包名限定的标识符 字首。包名称和标识符都不能为空。
QualifiedIdent = PackageName "." identifier .
合格标识符访问不同包中的标识符, 必须导入。必须导出和声明标识符 在该软件包的软件包块中。
math.Sin // denotes the Sin function in package math
导入声明声明包含声明的源文件取决于导入包的功能(§Program 初始化和执行)并允许访问导出 该包的标识符。导入命名标识符 (PackageName)用于访问和指定的ImportPath 要导入的包裹。
ImportDecl = "import" ( ImportSpec | "(" { ImportSpec ";" } ")" ) . ImportSpec = [ "." | PackageName ] ImportPath . ImportPath = string_lit .
PackageName用于限定标识符,以访问导入源文件中包的导出标识符。 它在文件块中声明。如果省略PackageName,则为 默认为在package子句中指定的标识符 进口包装。如果出现显式句点(。)而不是名称, 在该包中声明的所有包的导出标识符 包块将在导入源文件的文件中声明 阻止,必须在没有限定符的情况下访问。
ImportPath的解释依赖于实现,但它通常是已编译的完整文件名的子字符串 包,可能是相对于已安装软件包的存储库。
实现限制:编译器可以仅使用属于Unicode的L,M的字符将ImportPaths限制为非空字符串, N,P和S一般类别(没有空格的图形字符) 也可以排除字符!“#$%&'()*,:;< =>?[] ^`{|}和 Unicode替换字符U + FFFD。
假设我们编译了一个包含package子句包math的包,它导出函数Sin,并安装了编译的 包含在由“lib / math”标识的文件中。该表说明了 如何在各种文件导入包之后访问Sin 进口申报类型。
Import declaration Local name of Sin import "lib/math" math.Sin import m "lib/math" m.Sin import . "lib/math" Sin
导入声明声明导入和导入的包之间的依赖关系。导入包是非法的 本身,直接或间接,或直接导入包 没有引用任何导出的标识符。要导入 打包仅用于其副作用(初始化),使用空白 标识符作为显式包名称:
import _ "lib/math"
错误
./main.go:11: imported and not used: "gitlab.com/myapp/api-auth/middlewares"
表示您在包middlewares
中没有使用包main
,这是真的。
错误
./main.go:42: undefined: AcceptHandler
表示您尚未在包AcceptHandler
中定义main
,这是真的。
“限定标识符是使用包名称前缀限定的标识符。限定标识符访问必须导入的不同包中的标识符。”
例如,在包main
中,使用限定标识middlewares.AcceptHandler
,这是导入"gitlab.com/myapp/api-auth/middlewares"
的使用。