222

I've used GOPATH but for this current issue I'm facing it does not help. I want to be able to create packages that are specific to a project:

myproject/
├── binary1.go
├── binary2.go
├── package1.go
└── package2.go

I tried multiple ways but how do I get package1.go to work in the binary1.go or the binary2.go and so on?

For example; I want to be able to import "package1" and then be able to run go build binary1.go and everything works fine without the error being thrown that the package cannot be found on GOROOT or GOPATH. The reason why I need this kind of functionality is for large scale projects; I do not want to have to reference multiple other packages or keep them in one large file.

5
  • 3
    You're supposed to put the source files for each binary into its own directory.
    – fuz
    Commented Jul 9, 2013 at 6:41
  • All the .go files in a single directory are part of the same package, and you don't need to import files in the same package (i.e., the same directory). You mentioned working outside of GOPATH, which is one of the capabilities of the new Go modules system. This answer covers module structure, importing local packages, arranging packages within a module, whether or not to have multiple modules in single repository, etc.
    – thepudds
    Commented Aug 2, 2019 at 20:51
  • 15
    And this behavior is ok with everyone? That you basically can't import your local sub-packages unless you specify the entire git/repo/to/my/project path? I just don't see the reason why anyone would want this behavior. What if you move your project to another location (i.e. Docker image), you need to alter all paths again? I'm looking for answers why this is so complicated.
    – milosmns
    Commented Aug 18, 2019 at 14:55
  • 1
    @milosmns see my answer stackoverflow.com/a/60915633/175071 Commented Mar 29, 2020 at 14:32
  • Does this answer your question? Accessing local packages within a go module (go 1.11) Commented Apr 17, 2021 at 5:58

10 Answers 10

185

Go dependency management summary:

  • vgo if your go version is: x >= go 1.11
  • dep or vendor if your go version is: go 1.6 >= x < go 1.11
  • Manually if your go version is: x < go 1.6

Edit 3: Go 1.11 has a feature vgo which will replace dep.

To use vgo, see Modules documentation. TLDR below:

export GO111MODULE=on
go mod init
go mod vendor # if you have vendor/ folder, will automatically integrate
go build

This method creates a file called go.mod in your projects directory. You can then build your project with go build. If GO111MODULE=auto is set, then your project cannot be in $GOPATH.


Edit 2: The vendoring method is still valid and works without issue. vendor is largely a manual process, because of this dep and vgo were created.


Edit 1: While my old way works it's not longer the "correct" way to do it. You should be using vendor capabilities, vgo, or dep (for now) that are enabled by default in Go 1.6; see. You basically add your "external" or "dependent" packages within a vendor directory; upon compilation the compiler will use these packages first.


Found. I was able import local package with GOPATH by creating a subfolder of package1 and then importing with import "./package1" in binary1.go and binary2.go scripts like this :

binary1.go

...
import (
        "./package1"
      )
...

So my current directory structure looks like this:

myproject/
├── binary1.go
├── binary2.go
├── package1/
│   └── package1.go
└── package2.go

I should also note that relative paths (at least in go 1.5) also work; for example:

import "../packageX"
9
  • 4
    That works ok until you have two subfolders with one referring to another. For example, if package2 was also a subfolder and it needed package1, the system breaks.
    – Carl
    Commented Apr 4, 2014 at 1:52
  • 7
    import "../package1"
    – Felix Rabe
    Commented Oct 14, 2014 at 11:57
  • 13
    Relative import paths are a bad idea.
    – Dave C
    Commented Apr 1, 2015 at 15:59
  • 1
    if #golang provides 'namespace', I can agree with you that 'relative import path' or 'sub-packages' are a bad ideas'. Commented Sep 9, 2015 at 11:15
  • 1
    Function name should begin with Capitilized keyword
    – kokemomuke
    Commented Sep 8, 2016 at 14:11
75

There's no such thing as "local package". The organization of packages on a disk is orthogonal to any parent/child relations of packages. The only real hierarchy formed by packages is the dependency tree, which in the general case does not reflect the directory tree.

Just use

import "myproject/packageN"

and don't fight the build system for no good reason. Saving a dozen of characters per import in any non trivial program is not a good reason, because, for example, projects with relative import paths are not go-gettable.

The concept of import paths have some important properties:

  • Import paths can be be globally unique.
  • In conjunction with GOPATH, import path can be translated unambiguously to a directory path.
  • Any directory path under GOPATH can be unambiguously translated to an import path.

All of the above is ruined by using relative import paths. Do not do it.

PS: There are few places in the legacy code in Go compiler tests which use relative imports. ATM, this is the only reason why relative imports are supported at all.

5
  • 2
    I recommend taking a look at this intro video for a better understanding of packages and the GOPATH. youtube.com/watch?v=XCsL89YtqCs Commented Apr 8, 2014 at 21:47
  • 8
    I think this is bad advise. If you end up using gopkg.in for versioning, for example, you're out of luck with absolute import paths for your "mini" pakages, as described above. Either you break the source repo or the versioned one becomes useless.
    – Greg
    Commented Nov 21, 2014 at 4:20
  • import "myproject/packageN". myproject is the folder name that holds my project? Commented Mar 9, 2016 at 11:07
  • 1
    That's completely wrong, how do I use it with private repositories now?
    – agilob
    Commented Jun 28, 2018 at 14:43
  • "myproject" is the package name inside your main.go file
    – Russo
    Commented Aug 8, 2020 at 2:36
54

Perhaps you're trying to modularize your package. I'm assuming that package1 and package2 are, in a way, part of the same package but for readability you're splitting those into multiple files.

If the previous case was yours, you could use the same package name into those multiples files and it will be like if there were the same file.

This is an example:

add.go

package math

func add(n1, n2 int) int {
   return n1 + n2
}

subtract.go

package math

func subtract(n1, n2 int) int {
    return n1 - n2
}

donothing.go

package math

func donothing(n1, n2 int) int {
    s := add(n1, n2)
    s = subtract(n1, n2)
    return s
}

I am not a Go expert and this is my first post in StackOveflow, so if you have some advice it will be well received.

51

Since the introduction of go.mod , I think both local and external package management becomes easier. Using go.mod, it is possible to have go project outside the GOPATH as well.

Import local package:

Create a folder demoproject and run following command to generate go.mod file

go mod init demoproject

I have a project structure like below inside the demoproject directory.

├── go.mod
└── src
    ├── main.go
    └── model
        └── model.go

For the demo purpose, insert the following code in the model.go file.

package model

type Employee struct {
    Id          int32
    FirstName   string
    LastName    string
    BadgeNumber int32
}

In main.go, I imported Employee model by referencing to "demoproject/src/model"

package main

import (
    "demoproject/src/model"
    "fmt"
)

func main() {
    fmt.Printf("Main Function")

    var employee = model.Employee{
        Id:          1,
        FirstName:   "First name",
        LastName:    "Last Name",
        BadgeNumber: 1000,
    }
    fmt.Printf(employee.FirstName)
}

Import external dependency:

Just run go get command inside the project directory.

For example:

go get -u google.golang.org/grpc

It should include module dependency in the go.mod file

module demoproject

go 1.13

require (
    golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa // indirect
    golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9 // indirect
    golang.org/x/text v0.3.2 // indirect
    google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150 // indirect
    google.golang.org/grpc v1.26.0 // indirect
)

https://blog.golang.org/using-go-modules

7
  • 1
    can't load package: package .: no Go files in... (go build in folder of go.mod)
    – Sebi2020
    Commented Apr 10, 2020 at 16:06
  • Such a banality but it took me an embarrassing amount of time to find the answer and your post was the most legible and useful. Thank you! Commented Jul 14, 2020 at 19:05
  • 1
    This should be the best answer Commented Nov 15, 2020 at 1:46
  • hands down the best answer though not best practices.
    – yantaq
    Commented Sep 18, 2021 at 16:19
  • Finally found the working answer, thank you! Commented Nov 30, 2021 at 16:29
28

I have a similar problem and the solution I am currently using uses Go 1.11 modules. I have the following structure

- projects
  - go.mod
  - go.sum
  - project1
    - main.go
  - project2
    - main.go
  - package1
    - lib.go
  - package2
    - lib.go

And I am able to import package1 and package2 from project1 and project2 by using

import (
    "projects/package1"
    "projects/package2"
)

After running go mod init projects. I can use go build from project1 and project2 directories or I can do go build -o project1/exe project1/*.go from the projects directory.

The downside of this method is that all your projects end up sharing the same dependency list in go.mod. I am still looking for a solution to this problem, but it looks like it might be fundamental.

21

You can use replace

go mod init example.com/my/foo

foo/go.mod

module example.com/my/foo

go 1.14

replace example.com/my/bar => /path/to/bar

require example.com/my/bar v1.0.0

foo/main.go

package main
import "example.com/bar"

func main() {
    bar.MyFunc()
}

bar/go.mod

module github.com/my/bar

go 1.14

bar/fn.go

package github.com/my/bar

import "fmt"

func MyFunc() {
    fmt.Printf("hello")
}

Importing a local package is just like importing an external pacakge

except inside the go.mod file you replace that external package name with a local folder.

The path to the folder can be full or relative /path/to/bar or ../bar

9

To add a "local" package to your project, add a folder (for example "package_name"). And put your implementation files in that folder.

src/github.com/GithubUser/myproject/
 ├── main.go
 └───package_name
       └── whatever_name1.go
       └── whatever_name2.go

In your package main do this:

import "github.com/GithubUser/myproject/package_name"

Where package_name is the folder name and it must match the package name used in files whatever_name1.go and whatever_name2.go. In other words all files with a sub-directory should be of the same package.

You can further nest more subdirectories as long as you specify the whole path to the parent folder in the import.

2
  • 3
    This is a fine suggestion, except that during any kernel panic the stack trace that's dumped from the binary shows the github.com path for example, not always the most desirable behavior. There are flags to suppress this, but it shouldn't be necessary just to achieve simple package organization, and I've found that it does fail on occasion. Commented Jul 2, 2018 at 0:01
  • 2
    package myproject/package_name is not in GOROOT (/usr/lib/go-1.14/src/myproject/package_name)
    – Sebi2020
    Commented Apr 10, 2020 at 16:13
3

Run:

go mod init yellow

Then create a file yellow.go:

package yellow

func Mix(s string) string {
   return s + "Yellow"
}

Then create a file orange/orange.go:

package main
import "yellow"

func main() {
   s := yellow.Mix("Red")
   println(s)
}

Then build:

go build

https://golang.org/doc/code.html

2
  • This solution helped me a lot and cleared my point Thanks @steven-penny
    – jazeb007
    Commented Dec 8, 2020 at 17:36
  • Thanks for this simple example. What is the result binary called (and can i set that)? Commented Feb 3, 2021 at 12:33
0

In bash terminal

mkdir <module name>  
cd <module name>  
go mod init <module name>  
touch <module name>.go
  • Create go package in <module name>.go
cd ..  
mkdir main  
cd main  
go mod init main  
touch main.go
  • create main package that imports "<module name>"
go mod edit -replace=<module name>=<module path>
go mod tidy
  • look at each go.mod if you want to understand what's happening in go's background your folder structure will look like:
- Project  
  - <module name>  
    - <module name>.go  
    - go.mod  
  - main  
    - main.go  
    - go.mod  
go run .

OR

go build && 
./main.exe
0

Spent a whole evening trying to figure out why I am not able to access a function from my package, getting the error message above over and over again. TL;DR: You can only access functions from outside a package that start with an upper case letter.

Long answer: Project looked like this:

-awesomeProject
--- foo
------> foo.go
------> go.mod (<-- needed to be deleted)
awesome.go
go.mod
  1. Had to delete the go.mod file in the foo folder (already mentioned above). Still wondering why I could not access my function in foo -> foo.go
  2. Had to make sure that the function in foo -> foo.go started with an upper case letter (func Foo... instead of func foo ...).

Then everything worked like a charm.

Quote from Jon Bodner's book Learning Go - An Idiomatic Approach to Real-World Go Programming on this topic:

"This leads to the question: how do you export an identifier in Go? Rather than use a special keyword, Go uses capitalization to determine if a package-level identifier is visible outside of the package where it is declared. An identifier whose name starts with an uppercase letter is exported. Conversely, an identifier whose name starts with a lowercase letter or underscore can only be accessed from within the package where it is declared."

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.