如何正确地从Golang的子目录导入包?

如何正确地从Golang的子目录导入包?,go,Go,我是Golang的新手,我正在尝试让一个简单的RESTAPI应用程序工作 起初,一切都很好,因为我在main包下的同一目录中有所有代码 但是,现在我正处于一个需要开始将代码重构到子目录和包的阶段。不幸的是,我无法成功编译该应用程序 我的GOPATH设置为:~/.workspace 当前应用程序位于:~/.workspace/src/gitlab.com/myapp/api auth 这就是我当前的代码组织: 这是我的main.go package main import ( "net

我是Golang的新手,我正在尝试让一个简单的RESTAPI应用程序工作

起初,一切都很好,因为我在
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
(其余中间件的构造类似)

这是我从我的应用程序根目录运行
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

限定标识符是使用包名称限定的标识符 前缀包名称和标识符都不能为空

QualifiedIdent = PackageName "." identifier .
限定标识符访问不同包中的标识符, 必须进口。必须导出并声明标识符 在该包的包块中

math.Sin  // denotes the Sin function in package math

导入声明声明包含声明的源文件取决于导入包的功能(§程序) 初始化和执行),并允许访问导出的 该包的标识符。导入将命名一个标识符 (PackageName)用于访问和指定 要导入的包

    ImportDecl       = "import" ( ImportSpec | "(" { ImportSpec ";" } ")" ) .
    ImportSpec       = [ "." | PackageName ] ImportPath .
    ImportPath       = string_lit .
PackageName用于限定标识符中,以访问导入源文件中包的导出标识符。 它在文件块中声明。如果省略了PackageName,则 默认为在的package子句中指定的标识符 进口包装。如果出现显式句点(.)而不是名称, 在该包的 包块将在导入源文件的文件中声明 块,并且必须在不使用限定符的情况下访问

ImportPath的解释取决于实现,但它通常是已编译文件的完整文件名的子字符串 包,并且可能与已安装包的存储库相关

实现限制:编译器可以仅使用属于Unicode的L,M, N、 P和S一般类别(不带空格的图形字符) 也可以排除字符!“#$%&'()*,:;?[]^`{|}和 Unicode替换字符U+FFFD

假设我们编译了一个包含package子句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"
说明您在package
main
中没有使用package
Middleware
,这是正确的

错误

./main.go:42: undefined: AcceptHandler
说明您没有在包
main
中定义
AcceptHandler
,这是真的

“限定标识符是使用包名称前缀限定的标识符。限定标识符访问必须导入的不同包中的标识符。”


例如,在包
main
中,使用限定标识符
middleware.AcceptHandler
,这是导入
“gitlab.com/myapp/api auth/middleware”

的用法,您可以引用符号(函数、变量、类型)通过名称与该包名称之间的间距与其他包进行比较-例如,
middleware.AcceptHandler
。这就是为什么它们似乎未定义,而middleware“未使用”的原因。对该语言的新手来说,这是非常有帮助的、深入的解释。
./main.go:42: undefined: AcceptHandler