I have created a package named go-orm in golang and its structure is follows.
go-orm
--| mine.go
--| src
-----| src.go
-----| db
--------| DBConnection.go
When I ran the command "go install" in go-orm directory, it created only
go-orm.a but not src.a and db.a (sub directories or packages). When I checked
"go install" with mgo package it created .a files for it's sub directory "bson".
I need the same functionality for my package. What change is needed in my
package to make this possible.
Edit 1
my package is in GOPATH/src/ directory. All my sub packages(src and db) exist.
Package build
Go Path
The Go path is a list of directory trees containing Go source code. It
is consulted to resolve imports that cannot be found in the standard
Go tree. The default path is the value of the GOPATH environment
variable, interpreted as a path list appropriate to the operating
system (on Unix, the variable is a colon-separated string; on Windows,
a semicolon-separated string; on Plan 9, a list).
Each directory listed in the Go path must have a prescribed structure:
The src/ directory holds source code. The path below 'src' determines
the import path or executable name.
The pkg/ directory holds installed package objects. As in the Go tree,
each target operating system and architecture pair has its own
subdirectory of pkg (pkg/GOOS_GOARCH).
If DIR is a directory listed in the Go path, a package with source in
DIR/src/foo/bar can be imported as "foo/bar" and has its compiled form
installed to "DIR/pkg/GOOS_GOARCH/foo/bar.a" (or, for gccgo,
"DIR/pkg/gccgo/foo/libbar.a").
The bin/ directory holds compiled commands. Each command is named for
its source directory, but only using the final element, not the entire
path. That is, the command with source in DIR/src/foo/quux is
installed into DIR/bin/quux, not DIR/bin/foo/quux. The foo/ is
stripped so that you can add DIR/bin to your PATH to get at the
installed commands.
Here's an example directory layout:
GOPATH=/home/user/gocode
/home/user/gocode/
src/
foo/
bar/ (go code in package bar)
x.go
quux/ (go code in package main)
y.go
bin/
quux (installed command)
pkg/
linux_amd64/
foo/
bar.a (installed package object)
Use the prescribed directory structure, including the use of src as a directory name. Follow the example. Don't use src, pkg, or bin as package names.
go-orm
--| mine.go
--| src <== !? Don't use src as a package name.
-----| src.go
-----| db
--------| DBConnection.go
After long analysis I found that "import" statement in root directory go file
can do the trick. I created one extra file named create_archieve.go in root
directory(go-orm). Inside that I just inserted the following lines which created
go-orm.a, src.a and db.a.
create_archieve.go
package nosql_orm
import _"go-orm/src/db"
Related
I can not find a way to factor out some code from main.go into a local package when using Go modules (go version >= 1.11) outside of $GOPATH.
I am not importing any external dependencies that need to be included into go.mod, I am just trying to organize locally the source code of this Go module.
The file main.go:
package main
// this import does not work
import "./stuff"
func main() {
stuff.PrintBaz()
}
The file ./stuff/bar.go (pretending to be a local package):
package stuff
import "log"
type Bar struct {
Baz int
}
func PrintBaz() {
baz := Bar{42}
log.Printf("Bar struct: %v", baz)
}
The file go.mod (command go mod init foo):
module foo
go 1.12
When executing go run main.go:
If I import "./stuff", then I see build command-line-arguments: cannot find module for path _/home/<PATH_TO>/fooprj/stuff.
If I import "stuff", then I see build command-line-arguments: cannot load stuff: cannot find module providing package stuff.
If I import stuff "./stuff" with a package alias, then I see again: build command-line-arguments: cannot find module for path _/home/<PATH_TO>/fooprj/stuff.
I can not find a way to make local packages work with go modules.
What's wrong with the code above?
How can I import local packages into other Go code inside a project defined with Go modules (file go.mod)?
Module structure
The most common and easiest approach is:
Use a single go.mod per repository, and
Place the single go.mod file in the repository root, and
Use the repository name as the module path declared in the module line in the go.mod
(If you are using a custom import path such as me.io/mymod rather than using a VCS host based import path, then you would use the custom import path instead of the repository name in your go.mod).
For example, if your repo is github.com/my/repo, then you would place a single go.mod in the repo root, with the first line reading module github.com/my/repo. That can be created by cd'ing to the repo root and running go mod init github.com/my/repo. When working with the repo locally, the repo directory can be located wherever is convenient on your filesystem. (If you do not have a repo, see below).
Following this helps you stay on the happy path with modules, and it avoids multiple subtleties.
Russ Cox commented in #26664:
For all but power users, you probably want to adopt the usual convention that one repo = one module. It's important for long-term evolution of code storage options that a repo can contain multiple modules, but it's almost certainly not something you want to do by default.
There is much more about multi-module repositories in the "Multi-module Repositories" FAQ section on the modules wiki. Those 6 or so FAQs in that section should be read in their entirety by anyone considering veering off the recommendation above.
Arranging packages within a module
Once you have set up your go.mod, you can arrange your packages in directories however you see fit in directories underneath the directory containing the go.mod, as well as in the directory with the go.mod. Three good articles about how to arrange your code in packages:
https://rakyll.org/style-packages/
https://medium.com/#benbjohnson/standard-package-layout-7cdbc8391fc1#.ds38va3pp
https://www.goinggo.net/2017/02/design-philosophy-on-packaging.html
Those articles are classics that pre-date the introduction of modules, but the philosophies in them still apply to how to arrange your packages within a module.
Importing other packages in the same module
When importing another package with modules, you always use the full path including the module path. This is true even when importing another package in the same module. For example, if a module declared its identity in its go.mod as module github.com/my/repo, and you had this organization:
repo/
├── go.mod <<<<< Note go.mod is located in repo root
├── pkg1
│ └── pkg1.go
└── pkg2
└── pkg2.go
Then pkg1 would import its peer package as import "github.com/my/repo/pkg2". Note that you cannot use relative import paths like import "../pkg2" or import "./subpkg". (This is part of what OP hit above with import "./stuff").
Modules vs. repositories vs. packages vs. import paths
A Go module is a collection of related Go packages that are versioned together as a single unit. Modules record precise dependency requirements and create reproducible builds.
Summarizing the relationship between repositories, modules, and packages:
A repository contains one or more Go modules (most often exactly one module in the repository root).
Each module contains one or more Go packages.
Each package consists of one or more Go source files that all reside in a single directory.
Each Go source code file:
declares its own package with a package foo statement, which must be consistent for all Go files in a single package directory.
automatically has access to other Go source code in the same package, without explicitly importing its own package.
imports code from another package via an import path supplied in an import statement such as import "github.com/my/repo/pkg1". The import path always starts with the module path of that package, regardless of whether that package is in the same module or a different module.
A single module can be used to build multiple executable binaries, but the func main() {...} entry point for each binary must be in its own package main, with each package main in a distinct directory.
Local-only modules
You can create, build and run modules without ever publishing them or placing them on a VCS server.
A module is defined by a tree of Go source files with a go.mod file in the tree's root directory, so you can pick a directory on your local filesystem to serve as the root of your module and place your go.mod there. Everything described above still applies, except there does not need to be a repo.
For example:
some-directory/
├── go.mod <<<< go.mod at module root declaring 'module example.com/foo'
├── pkg1
│ └── pkg1.go
└── pkg2
└── pkg2.go
If the module path in the first line of that go.mod reads module example.com/foo, then pkg1 would import its peer package as import "example.com/foo/pkg2".
Of course, you can start with a local-only module without a repo, then later start tracking it in a local repo or publish it to a VCS server.
Even for local-only modules, it is a good idea to give the module a globally unique name, such as go mod init my.org/foo, or go mod init github.com/some/repo as if it will be published someday, even if that repo does not yet exist. (If you are in a hurry, it is possible to use a shorter module name without a dot or leading hostname component, such as go mod init temp or go mod init m, but it won’t be fetchable by the go command, and you run the risk of colliding with a current or future standard library package or otherwise seeing confusing error messages later).
If you have multiple local modules, you can point them at each other via replace directives or via the Go 1.18+ workspace feature, though those are more complex workflows than placing everything for a given project in a single module.
Next steps
If you are new to Go modules, it is worthwhile to go through the official "Create a Go Module" tutorial from the Go project. This will likely save you time overall.
If you are stuck right now with an error message related to modules or import paths, there's a very good chance the error will make much more sense after completing the tutorial.
First you have to choose a name for your project and write it to go.mod file. This name belongs to root directory of the project. Each new package you create must be located inside its own subdirectory and its name should match directory name.
go.mod:
module myprojectname
or (preferred way, see #thepudd's answer for details)
module github.com/myname/myproject
Then import your project's packages like:
import myprojectname/stuff
or
import github.com/myname/myproject/stuff
Files of package stuff should be located inside project's stuff directory. You name these files as you like.
Also it's possible to create deeper project structure. For instance, you decided to separate source code files from other ones (like app configs, docker files, static files, etc...). Let's move stuff directory inside pkg, every go file inside pkg/stuff still have stuff package name. To import stuff package just write:
import myprojectname/pkg/stuff
Nothing stops you from creating more levels in the hierarchy like github.com/myuser/myproject/pkg/db/provider/postgresql, where:
github.com/myuser/myproject - project name.
postgresql - package name.
pkg/db/provider/postgresql - path to the package relative to project's root.
You can read more about go modules here: https://github.com/golang/go/wiki/Modules
Check out this repository to get useful information about various patterns used in project organizing: https://github.com/golang-standards/project-layout If you go inside pkg directory you will find out which open source projects use pkg directory in their structure.
I am doing some light hacking on the rclone project, and I'm somewhat new to go. I have cloned the repository in my home directory, /home/poundifdef/rclone.
When I look at the file, rclone.go, in the top-level directory, I see the following import statement:
package main
import (
_ "github.com/ncw/rclone/backend/all"
"github.com/ncw/rclone/cmd"
_ "github.com/ncw/rclone/cmd/all"
)
My question is this: nowhere in this code, as far as I can tell, do we specify that the github.com/ncs/rclone/* packages are supposed to refer to the local versions of these directories. Nowhere in my filesystem have I used a directory called github.com/ncw. And yet, running go run rclone.go is able to execute this code.
Where is the path github.com/ncw/rclone being mapped to my local directory, given these packages, as named, do not exist?
github.com/ncw/rclone is a module, because it has a file named go.mod at the repository root. Since you have $GOPATH unset, the experimental module feature is enabled.
Where modules are placed in your filesystem is irrelevant. when constructing import paths, all directory names in the module are appended to the module name. The module name is defined in the first line of go.mod, here "github.com/ncw/rclone". So the package in ./cmd has the import path github.com/ncw/rclone/cmd.
Commands such as go build, go install, go test, etc. download all other required packages automatically to $HOME/go/pkg/mod, unless the -mod=vendor flag is specified, in which case the sources in vendor are used.
Golang has an internal mechanism to resolve import path.
This mechanism relies on the existence of several variables on your computer, GOROOT, GOPATH and for old releases GO15VENDOREXPERIMENT.
When the compiler meet a package path, it performs a look up with those paths
GOROOT/src/[import path]
GOPATH/src/[import path]
cwd/vendor/[import path]
The longest path wins and is selected for further processing.
GOROOT is the path to the stdlib.
GOPATH is the path to your local workspace.
For all the details https://go.googlesource.com/proposal/+/master/design/25719-go15vendor.md
This all depends on the setup of your computer, so carefully check go env output.
I'm using struct from subpackage and it works. But on find usage of this structure IDEA doesn't see usages. The same situation on rename for the structure - IDEA renames the original structure and doesn't rename it in all places of usage.
How can I fix it, because I don't want to put all go files only in one package.
go project directory like this.
projectname:
bin/
src/
structs/
custom_types.go
main.go
pkg/
Use go build command will auto create bin/pkg directory.
src directory contains all go source files.
I have a directory structure like this:
Animal/
dog/
chiwawa.go
rabbit.go
Both chiwawa.go and rabbit.go are packaged named: "package animal" at the top of the file. However when I try to use a variable var Food = apple from chiwawa.go in rabbit.go, I get error - undefined: Food.
I don't have any problems when I place chiwawa.go directly under Animal without the dog directory.
Is this intentional in Go? Can I work around this while retaining the package names and directory structure?
How to Write Go Code
Workspaces
The go tool is designed to work with open source code maintained in
public repositories. Although you don't need to publish your code, the
model for how the environment is set up works the same whether you do
or not.
Go code must be kept inside a workspace. A workspace is a directory
hierarchy with three directories at its root:
src contains Go source files organized into packages (one package per directory),
pkg contains package objects, and
bin contains executable commands.
The go tool builds source packages and installs the resulting binaries
to the pkg and bin directories.
The src subdirectory typically contains multiple version control
repositories (such as for Git or Mercurial) that track the development
of one or more source packages.
To give you an idea of how a workspace looks in practice, here's an
example:
bin/
hello # command executable
outyet # command executable
pkg/
linux_amd64/
github.com/golang/example/
stringutil.a # package object
src/
github.com/golang/example/
.git/ # Git repository metadata
hello/
hello.go # command source
outyet/
main.go # command source
main_test.go # test source
stringutil/
reverse.go # package source
reverse_test.go # test source
This workspace contains one repository (example) comprising two
commands (hello and outyet) and one library (stringutil).
A typical workspace would contain many source repositories containing
many packages and commands. Most Go programmers keep all their Go
source code and dependencies in a single workspace.
For the Go tools, all the Go source files for a Go package should be in the same directory.
It is intentional. Packages in Go are imported using a directory path. So, "animal" and "animal/dog" are two different packages even if you give them the same package name.
To demonstrate this, I wrote the following example set of files:
~/go/src/test/
├── animal
│ ├── animal.go
│ └── dog
│ └── dog.go
└── test.go
animal/animal.go
package animal
type Species string
animal/dog/dog.go
package animal
// In package "animal" importing a package "animal"
import "test/animal"
type Dog struct {
Species animal.Species
Breed string
}
test.go
package main
import (
"fmt"
"test/animal/dog"
)
func main() {
d := animal.Dog{}
fmt.Printf("%#v", d)
}
Notice that dog.go imports the "test/animal" package and references it as "animal".
Furthermore notice that test.go imports "test/animal/dog" to get access to the "Dog" struct type. If it imports, "test/animal", the error (undefined: animal.Dog) is generated.
I just started with Go, and i love it! I have tried to make the structure of my project a bit more manageable, instead of having everything in my main.go
So now i have a structure like this.
src/
-> main.go
-> routes.go
-> handlers/
--> user_handlers.go
But when i try to build this with the following command
go build -v -o ./bin/my_bin ./src/...
I get this error
cannot use -o with multiple packages
But if i make it a flat structure like this
src/
-> main.go
-> routes.go
-> user_handlers.go
It works just fine, all my files got "package main" in the top of them.
What am i doing wrong?
The package name must match the directory name. Moving a source file to a new directory requires that you also change the package name.
foo/foo.go // package foo
foo/bar/bar.go // package bar
foo/bar/qux.go // package bar
The PATH is not relevant in terms of the package name.
Package foo: /some/path/some/where/foo
This allows multiple "foo" packages to be created and imported provided your import specifies the desired location of "foo"
P.S. The convention for package names is lowercase, no punctuation (e.g., no _'s)
It tells you what you did wrong, you can't separate a single package over multiple folders.
You need to set and properly use $GOPATH and properly import your routes/ folder in routes.go.
A simple example of it is:
// routes.go
// the . means you can call imported functions without prefixing them with the package name
import . "full-path-to-routes/-relative-to-$GOPATH"
From https://golang.org/doc/code.html:
The GOPATH environment variable specifies the location of your workspace. It is likely the only environment variable you'll need to set when developing Go code.
To get started, create a workspace directory and set GOPATH accordingly. Your workspace can be located wherever you like, but we'll use $HOME/go in this document. Note that this must not be the same path as your Go installation.
I highly recommend reading Effective Go.