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

时间:2016-02-06 17:09:06

标签: go

我对Golang很陌生,并尝试制作一个简单的REST api应用程序。

最初,一切都很好,因为我在main包下的同一目录中包含了所有代码。

但是,现在我处于一个需要开始将代码重构为子目录和包的阶段。不幸的是,我无法成功编译应用程序。

我的GOPATH设置为:~/.workspace 当前的应用位于:~/.workspace/src/gitlab.com/myapp/api-auth

这就是我目前的代码组织:

enter image description here

这是我的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

1 个答案:

答案 0 :(得分:13)

  

The Go Programming Language Specification

     

Qualified identifiers

     

限定标识符是使用包名限定的标识符   字首。包名称和标识符都不能为空。

QualifiedIdent = PackageName "." identifier .
     

合格标识符访问不同包中的标识符,   必须导入。必须导出和声明标识符   在该软件包的软件包块中。

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

Import declarations

     

导入声明声明包含声明的源文件取决于导入包的功能(§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"的使用。