如何使用自定义包

206

我正在尝试在Go中创建和使用自定义包。这可能是非常显然的事情,但我找不到太多关于它的信息。基本上,我有这两个文件在同一个文件夹中:

mylib.go

package mylib

type SomeType struct {

}

main.go

package main

import (
    "mylib"
)

func main() {

}

当我尝试运行 go run main.go 时,出现以下错误:
main.go:4:2: import "mylib": cannot find package

我已经尝试运行go build mylib.go,但似乎没有任何反应(没有生成文件,也没有错误消息)。所以你有什么想法如何做到这一点吗?

我没有设置GOPATH变量,只有GOROOT。 - laurent
1
先在 mylib 目录下运行 go install,然后再试一遍。 - Joe
1
请参考此帖子 - kostix
@Joe,仍然无法通过在内部运行“go install”来工作。 - hunter_tech
9个回答

189

首先,请确保阅读并理解 "如何编写Go代码" 文档。

实际答案取决于您的“自定义包”的性质。

如果它旨在普遍使用,请考虑采用所谓的 "Github代码布局"。 基本上,您可以将库作为一个单独的 go get-table 项目。

如果您的库是供内部使用的,则可以按照以下步骤进行:

  1. 将包含库文件的目录放置在项目目录下。
  2. 在项目的其他部分中,使用相对于包含该项目的工作区根目录的路径引用库。

为了演示:

src/
  myproject/
    mylib/
      mylib.go
      ...
    main.go

现在,在最高级别的 main.go 中,您可以 import "myproject/mylib" ,它会正常工作。

1
如果我在src/下创建一个新项目(myproject2),我该如何导入mylib? - Kiril
3
@Kiril,您的意思是,在“myproject2”的代码中如何导入“mylib”? 那么答案就是“使用import“ myproject / mylib”--想法是Go在从GOPATH环境变量中提取的每个目录下搜索导入的路径(它们称为“工作区”),但这种搜索(幸运的是)不是递归的,因此这些路径实际上是在各自的工作区上“锚定”的。 - kostix
4
另一篇必读文章:"包名" - kostix
1
@LeiYang,“要导入的包”是一个或多个Go源文件的目录。至于“如何将包构建为.lib文件,然后导入lib文件”,答案取决于您真正想要问什么。如果您担心编译速度,那么不用担心:Go工具链会按照每个包的基础缓存所有构建结果。如果您想问是否可能编译并分发仅限二进制的编译包,则答案是 - kostix
1
@LeiYang,但是请注意,如果你仍然迫切需要类似的东西,在某些平台上,Go支持插件。 - kostix
显示剩余4条评论

78

对于这种文件夹结构:

main.go
mylib/
  mylib.go

最简单的方法是使用这个:

import (
    "./mylib"
)

5
在Go的最新版本中,原先的代码已经无法使用,因为包将找不到。正确的引用方式应该是 foo/mylib(假设包含 main.go 的文件夹为 foo)。 - nemo
6
@nemo,使用最新版本的go,我总是使用"./mylib"并且它有效。 - laurent
3
使用 go 1.2,我同意 @this.lau_ 的观点。 - canadadry
8
请注意,这将导致go install无法正常工作。如果您正在构建一个独立的项目,并希望其他人下载并在其上运行go build,那么这是可以的。然而,如果您想要完整的go install支持,则建议采用上述提到的“Github代码布局”(即使在Bitbucket或类似平台上)。 - photoionized
我建议不要使用这种方式。它会破坏 godef。 godef 不理解“.”导入。 - King Jk

9

我是一名有经验的程序员,但对Go编程领域比较陌生!我承认我在理解Go时遇到了一些困难......

在尝试将我的go文件组织到子文件夹中时,我面临着同样的问题。

我是这样做的:

GO_Directory(指定为$GOPATH的目录)

GO_Directory //the one assigned to $GOPATH
__MyProject
_____ main.go
_____ Entites
_____ Fiboo // in my case, fiboo is a database name
_________ Client.go // in my case, Client is a table name

在文件 MyProject\Entities\Fiboo\Client.go 中

package Fiboo

type Client struct{
    ID int
    name string
}

在文件 MyProject\main.go 中

package main

import(
    Fiboo "./Entity/Fiboo" 
)

var TableClient  Fiboo.Client

func main(){
    TableClient.ID = 1
    TableClient.name = 'Hugo'

    // do your things here
}

我正在运行Ubuntu 16.04上的Go 1.9。

记住,我是Go的新手。如果我的做法存在不好的实践,请告诉我!


6

对于托管在GitHub上的项目,人们通常会做以下事情:

github.com/
  laike9m/
    myproject/
      mylib/
        mylib.go
        ...
      main.go

mylib.go

package mylib

...

main.go

import "github.com/laike9m/myproject/mylib"

...

4
我尝试了许多方法,但最好的方法是使用go.mod并放置。
module nameofProject.com

然后我从同一项目中导入,我使用的是:

import("nameofProject.com/folder")

在任何地方创建项目非常有用


2
另一个解决方案:
src/myproject添加到$GOPATH中。 然后使用import "mylib"编译即可。

这将无法适用于像 GitHub 托管的包之类的可通过 go get 获取的路径。 - Gustav

1

最终我找到了这个问题的解决方案。请注意,我的编码环境非常基本,同时我作为一个初学者,使用的都是基础知识。我想以与官方库相同的方式使用我的库。我不需要编辑GOPATH或任何其他系统变量或路径,也不需要重新构建或安装任何东西。因此,这是我从上到下的解决方案:

  1. 在我的主包中,我的代码如下:
    package main
    
    import (
      "mylib"  // This is my library!!
      "fmt"
    )
    
    
    func main() {
      ...
      mylib.myFunc(par)
      mylib.myOtherFunc(par1,par2)
      ...
    }
  1. 在包实现文件中,必须使用完全相同的包名称。我的包示例如下:
package mylib

import (
  "math"
  "strconv"
  "strings"
)

func myFunc(par int) {
  ...
}

func myOtherFunc(par1 string, par2 int) {
  ...
}
  1. 在命名和定位所有的东西时,你需要记住以下几点:
  • Create a subfolder with the package name next to the other packages. You can find them easily by searchin eg. 'bufio', 'os' or 'math' (on my machine they are under \Go\src). In my case it looks like this:

     C:
      /Go
        /src
          /bufio
          /io
          /...
          /mylib
          /...
          /strings
    
  • Move your package file into this folder. The folder name is important, this has to be the same as the package name, this is how your compiler finds it

  • You can have one ore more .go files here, they needn't to be named mylib.go, you can use any names, eg. myMath.go, myString.go, etc.

  • I repeat: the package name in all the .go files has to be your library name ('mylib' in my case)

  1. 这样,以后您就可以通过新功能扩展自己的库,它们可以在单独的.go文件中实现,唯一重要的是您必须将此文件存储在名为“mylib”的子文件夹中,并且包名称必须相同。

希望对您有所帮助,祝好!

LA


0
本质上的问题在于,将打包编译的软件包作为库二进制文件定制,然后将其作为第三方库(如"net/http"或"fmt")导入到某个新的Go项目中,而不是使用原始的Go代码。我想知道这是否在Go编程中可行。

目前你的回答不够清晰,请编辑并添加更多细节以帮助其他人理解它如何回答问题。你可以在帮助中心找到有关如何编写好答案的更多信息。 - Community
这并没有回答问题。一旦您拥有足够的声望,您将能够评论任何帖子;相反,提供不需要询问者澄清的答案。- 来自审核 - Subhashis Pandey

0

对于面临这个问题的人,你需要先初始化go模块,然后才能使用自定义包。

例如你的代码目录是:../mycode/main.go。现在你想创建diffcode自定义包并将其导入到主要程序中。你需要首先运行命令go mod init mycode(确保你在../mycode目录下)。现在你创建了包diffcode并有一些文件。为了导入这个包,你需要把module/package放入main.go。在这种情况下是mycode/diffcode


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接