为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
慕码人8056858 2021-12-07 18:54:52
我对 Golang 还很陌生,正在尝试制作一个简单的 REST api 应用程序。最初,一切都很好,因为我将所有代码都放在main包下的同一目录中。但是,现在我处于需要开始将代码重构为子目录和包的阶段。不幸的是,我未能成功编译该应用程序。我GOPATH的设置为:~/.workspace 当前应用程序位于:~/.workspace/src/gitlab.com/myapp/api-auth这是我目前的代码组织方式:这是我的 main.gopackage mainimport (    "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 middlewaresimport "net/http"// AcceptHandler ensures proper accept headers in requestsfunc 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)}
查看完整描述

1 回答

?
米脂

TA贡献1836条经验 获得超3个赞

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


QualifiedIdent = PackageName "." identifier .

限定标识符访问必须导入的不同包中的标识符。标识符必须在该包的包块中导出和声明。


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

进口申报


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


    ImportDecl       = "import" ( ImportSpec | "(" { ImportSpec ";" } ")" ) .

    ImportSpec       = [ "." | PackageName ] ImportPath .

    ImportPath       = string_lit .

PackageName 用于限定标识符以访问导入源文件中包的导出标识符。它在文件块中声明。如果省略 PackageName,则默认为导入包的包子句中指定的标识符。如果出现显式句点 (.) 而不是名称,则在该包的包块中声明的所有包的导出标识符将在导入源文件的文件块中声明,并且必须在没有限定符的情况下访问。


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


实现限制:编译器可以将 ImportPaths 限制为仅使用属于 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 middlewaresin package main,这是真的。


错误


./main.go:42: undefined: AcceptHandler

说你没有AcceptHandler在 package 中定义main,这是真的。


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


例如,在 package 中main,使用限定标识符middlewares.AcceptHandler,这是 import 的一种用法"gitlab.com/myapp/api-auth/middlewares"。


查看完整回答
反对 回复 2021-12-07
  • 1 回答
  • 0 关注
  • 323 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信