Organizing a multiple-file Go project with private support files - go

Following this answer I have created the following project structure:
.
├── bin
├── pkg
└── src
└── github.com
└── GITHUB_USERNAME
└── PROJECTNAME
├── lib
│   └── model.go
│   └── ... .go
├── LICENSE
├── README.md
└── PROJECTNAME.go
PROJECTNAME.go has the package main
model.go has the package PROJECTNAME
In the PROJECTNAME.go I am importing the follwing:
import(
'github.com/GITHUB_USERNAME/PROJECTNAME/lib/model'
)
but when I run go build I get the follwing error:
cannot find package "github.com/GITHUB_USERNAME/PROJECTNAME/lib/model" in any of:
/usr/lib/go/src/pkg/github.com/GITHUB_USERNAME/PROJECTNAME/lib/model (from $GOROOT)
/home/USERNAME/go/src/github.com/GITHUB_USERNAME/PROJECTNAME/lib/model (from $GOPATH)
How must the packages names be to import correctly? Are there any other strategies?

Package import paths are defined by directory names, not file names.
The correct import path is "github.com/GITHUB_USERNAME/PROJECTNAME/lib" and all of the go files in that folder must have the same package clause at the top.
The identifier after the package clause is what identifier will be imported into the package that imports it. So if it's package foo, you can access the Bar identifier by foo.Bar in the importing code.
By convention, authors typically use the last part of the import path as the package name, so in this case, you should have package lib at the top of all of the Go files under the lib folder.

Two things here:
You missed "project" during the import. Use github.com/GITHUB_USERNAME/PROJECTNAME/lib/model
Minor: Naming the package github.com/GITHUB_USERNAME/PROJECTNAME/lib/model "PROJECTNAME" seems strange. How about lib or model?

Your import statement from your main package should read
import(
"github.com/GITHUB_USERNAME/PROJECTNAME/lib/PROJECTNAME"
)
You said your model.go uses PROJECTNAME as the package. So you don't actually name a file in your import path. The last component should be the package name. That means you can have a number of go files in the lib directory all with PROJECTNAME as the package.

Related

Python import VIsual Studio Code

I'm trying to import a class from a file, but I can't find the right syntax in Visual Studio Code :i
My structure:
└── src
├── common
│ ├── database.py
│
└── models
├── admin
├──admin.py
In admin.py, I need to import a class called Database, which is located in database.py. My solution would be:
from src.common.database import Database
But then I get this error:
ModuleNotFoundError: No module named 'src'
As mentioned by #Dave in https://stackoverflow.com/a/7506029/2053706, you can use relative references to other files on import.
What you're looking for is:
from ...src.common.database import Database
Each "dot" is one path back, except the first "dot" which is "this folder".
Hope that makes sense.

Structuring a multi-executable Go project

I am trying to build a micro-services architecture project in Go. I am currently using Go 1.11 which supports modules, so I put my root directory in an arbitrary chosen directory, outside of GOPATH.
If I am getting the micro-services architecture concepts right, although my microservices need to be independent, they can share dependencies (and I don't see another way to do stuff, is it?)
Below is my directory structure:
.
├── go.mod
├── lambda
│   └── account_create
│   └── main.go
├── readme.md
└── types
├── account.go
├── location.go
├── order.go
├── pricing.go
├── product.go
└── types.go
Now the behavior I expected was to be able to run go build lambda/account_create and get an executable with that functionality so I can supply it to the respective AWS Lambda function.
However, when I run the command, I get:
can't load package: package lambda/account_create: unknown import path "lambda/account_create": cannot find module providing package lambda/account_create
Please explain me why this does not work and give me some advice on how a project like this should look.
Thank you very much!
Edit Here is my lambda/account_create/main.go file contents:
package account_create
import (
"fmt"
"roasted.ro/pkg/types"
)
func main() {
account := types.UserAccount{Name: "Victor"}
fmt.Printf("Welcome %s", account.Name)
}
To answer the latter part of your question (as the first half is more about preference), you need to do:
go build ./lambda/account_create
Notice the ./. go build takes in a package name or a path. If you don't prepend the path with a ./, it assumes you are giving it a package name.
Edit: the package has to be main if you want an executable. According to the docs, you always have to use package main for projects that build an executable:
Executable commands must always use package main.
Edit: I'll add some opinions on layout:
Consider which parts of your project are exported to other go projects. Meaning someone could import your package and expect to gain value and not have their code break when yours changes.
That should be either in a github.com/you/pkg/somepath package or just github.com/you/somepath.
Anything else (other than main packages) should be under a /internal package.
I typically make a /cmd/myexecurable1 /cmd/myexecurable2 and so forth for each executable.

Convert type from a different directory [duplicate]

I want to break my project up to subfolders.
I want this code structure:
├── main.go
└── models
└── user.go
Where main.go is:
package main
import (
"fmt"
"./models"
)
func main(){
fmt.Println(User{"new_user"})
}
And user.go is:
package models
type User struct {
Login string
}
But User is not defined in main package and import raise warning "imported and not used".
What am I doing wrong? My project is simple (not such a example but just with few files (controllers and models)) and I want a simple structure.
Maybe I doing it in completely wrong way?
Problem project is here: https://github.com/abonec/go_import_problem
I recently achieved this by using go modules.
Golang introduced preliminary opt-in support for modules as of go v1.11.1 which is intended to completely remove the, frankly, absurd $GOPATH necessity. Not only can you now have versioned dependencies in any normal directory such as ~/development, but you can basically have something that looks like namespaces and sub-directories. You can enable this feature by invoking the go command with the following environment variable: GO111MODULE=on.
Go v1.11.3 expects to enable modules by default and is slated for August 2019.
Here is an example directory structure (that you might find typically in some other languages).
~/Dev/my-app
├── src/
│ ├── one/
│ │ ├── two/
│ │ │ └── two.go
│ │ └── one.go
│ └── zero.go
├── go.mod
└── app.go
The application is called my-app, which will be the module name for app.go. We define this once in go.mod and then each of all the other go files in subdirectories will automatically be importable as if they were namespaced.
Given the above, two.go, assuming it contains a function named Two, will be importable in app.go by using my-app/src/one/two.
Here's what you need to do to achieve this:
go.mod
module my-app
two.go
package two
func Two() string {
return "I'm totally not supposed to be using go modules for this"
}
app.go
package main
import "my-app/src/one/two"
func main() {
two.Two()
}
If you were to place another file within two/, then you would simply use two.TheNewFunc() as long as you made TheNewFunc() available within the new file.
I created a very simple GitHub repo which you can check out as a demonstration.
Your import should be an absolute one:
import "github.com/abonec/go_import_problem/models"
If you don't want to export your project to an external referential, you can do a:
import "go_import_problem/models"
(That is: "the name of your project folder accessible by GOPATH/your package")
See "How to use custom packages in golang?".
And you would use:
models.User
As mentioned in Effective Go:
The importer of a package will use the name to refer to its contents, so exported names in the package can use that fact to avoid stutter.
(Don't use the import . notation, which can simplify tests that must run outside the package they are testing, but should otherwise be avoided.)
kostix adds in the comments:
to reiterate, names of Go packages are always absolute (that is, there's no relative package names, neither with ./ nor with ../ or anything like that) but that names are "anchored" to one of the so-called workspaces listed in $GOPATH.
When Go searches for a package, it looks through workspaces and tries to find a package in each of them, in order.
The search is not recursive.
And no, there's no requirement to encode URLs in package paths -- unless you want to make your package public.
You need to qualify items in in a package by its package name
So
fmt.Println(models.User{"new_user"})
Breaking up a single project into subfolders is not the recommended way of structuring a go project, which is why there is basically no good way to do what you want.
If the project is really large, and too unwieldy to make a single package, consider splitting it into several totally distinct packages, rather than special sub-directory packages. This has the advantage of forcing you to think cleanly about your internal APIs.
The packages are referenced in code in relation to your "go/src" folder
└── go
└── src
└── myAwesomeProject
├── main.go
└── models
└── user.go
So in main.go
package main
import (
"fmt"
"myAwesomeProject/models"
)
Similarly packages can reference each other using the same convention.
You should use your imported objects by it's imported names. For example if you
import "./models"
with struct User you should use it as
models.User

How to use "internal" packages?

I try understand how to organize go code using "internal" packages. Let me show what the structure I have:
project/
internal/
foo/
foo.go # package foo
bar/
bar.go # package bar
main.go
# here is the code from main.go
package main
import (
"project/internal/foo"
"project/internal/bar"
)
project/ is outside from GOPATH tree. Whatever path I try to import from main.go nothing works, the only case working fine is import "./internal/foo|bar". I think I do something wrong or get "internal" package idea wrong in general. Could anybody make things clearer, please?
UPDATE
The example above is correct the only what I need was to place project/ folder under $GOPATH/src. So the thing is import path like the project/internal/foo|bar is workable if we only import it from project/ subtree and not from the outside.
With modules introduction in Go v1.11 and above you don't have to specify your project path in $GOPATH/src
You need to tell Go about where each module located by creating go.mod file. Please refer to go help mod documentation.
Here is an example of how to do it:
project
| go.mod
| main.go
|
\---internal
+---bar
| bar.go
| go.mod
|
\---foo
foo.go
go.mod
project/internal/bar/go.mod
module bar
go 1.14
project/internal/bar/bar.go
package bar
import "fmt"
//Bar prints "Hello from Bar"
func Bar() {
fmt.Println("Hello from Bar")
}
project/internal/foo/go.mod
module foo
go 1.14
project/internal/foo/foo.go
package foo
import "fmt"
//Foo prints "Hello from Foo"
func Foo() {
fmt.Println("Hello from Foo")
}
project/main.go
package main
import (
"internal/bar"
"internal/foo"
)
func main() {
bar.Bar()
foo.Foo()
}
Now the most important module
project/go.mod
module project
go 1.14
require internal/bar v1.0.0
replace internal/bar => ./internal/bar
require internal/foo v1.0.0
replace internal/foo => ./internal/foo
Couple things here:
You can have any name in require. You can have project/internal/bar if you wish. What Go think it is URL address for the package, so it will try to pull it from web and give you error
go: internal/bar#v1.0.0: malformed module path "internal/bar": missing dot in first path element
That is the reason why you need to have replace where you tell Go where to find it, and that is the key!
replace internal/bar => ./internal/bar
The version doesn't matter in this case. You can have v0.0.0 and it will work.
Now, when you execute your code you will have
Hello from Bar
Hello from Foo
Here is GitHub link for this code example
The packages have to be located in your $GOPATH in order to be imported. The example you gave with import "./internal/foo|bar" works because it does a local-import. internal only makes it so code that doesn't share a common root directory to your internal directory can't import the packages within internal.
If you put all this in your gopath then tried to import from a different location like OuterFolder/project2/main.go where OuterFolder contains both project and project2 then import "../../project/internal/foo" would fail. It would also fail as import "foo" or any other way your tried due to not satisfying this condition;
An import of a path containing the element “internal” is disallowed if
the importing code is outside the tree rooted at the parent of the
“internal” directory.
Now if you had the path $GOPATH/src/project then you could do import "foo" and import "bar" from within $GOPATH/src/project/main.go and the import would succeed. Things that are not contained underneath project however would not be able to import foo or bar.
below way is more scalable, especially when you plan to build multiple binaries
github.com/servi-io/api
├── cmd/
│ ├── servi/
│ │ ├── cmdupdate/
│ │ ├── cmdquery/
│ │ └── main.go
│ └── servid/
│ ├── routes/
│ │ └── handlers/
│ ├── tests/
│ └── main.go
├── internal/
│ ├── attachments/
│ ├── locations/
│ ├── orders/
│ │ ├── customers/
│ │ ├── items/
│ │ ├── tags/
│ │ └── orders.go
│ ├── registrations/
│ └── platform/
│ ├── crypto/
│ ├── mongo/
│ └── json/
The folders inside cmd/ represents the number of binaries you want to build.
for more
Also to check: When you are using your externally imported object types: make sure you are prefixing them with the namespace they're in. As a golang newbie, I didn't know I had to do that, and was wondering why is VS Code just removing my import (for not being used) when I saved. It's because I had to prefix the imported object with the namespace name:
Example:
import (
"myInternalPackageName" // works fine as long as you follow all instructions in this thread
)
//Usage in code:
myInternalPackageName.TheStructName // prefix it, or it won't work.
If you don't put the namespace prefix before the object/struct name, VS code just removes your import for being unused, and then you still have the error: "Can't find TheStructName"... That was very confusing, and I had to do a build without VS code through the command line to understand that.
The point is: I had to specify the package prefix when actually using the struct from that internal package.
If you don't want to use the qualifier prefix when using imported objects, use:
import . "thePath" // Can use contents without prefixing.
Reference: What does the '.' (dot or period) in a Go import statement do?

Break up go project into subfolders

I want to break my project up to subfolders.
I want this code structure:
├── main.go
└── models
└── user.go
Where main.go is:
package main
import (
"fmt"
"./models"
)
func main(){
fmt.Println(User{"new_user"})
}
And user.go is:
package models
type User struct {
Login string
}
But User is not defined in main package and import raise warning "imported and not used".
What am I doing wrong? My project is simple (not such a example but just with few files (controllers and models)) and I want a simple structure.
Maybe I doing it in completely wrong way?
Problem project is here: https://github.com/abonec/go_import_problem
I recently achieved this by using go modules.
Golang introduced preliminary opt-in support for modules as of go v1.11.1 which is intended to completely remove the, frankly, absurd $GOPATH necessity. Not only can you now have versioned dependencies in any normal directory such as ~/development, but you can basically have something that looks like namespaces and sub-directories. You can enable this feature by invoking the go command with the following environment variable: GO111MODULE=on.
Go v1.11.3 expects to enable modules by default and is slated for August 2019.
Here is an example directory structure (that you might find typically in some other languages).
~/Dev/my-app
├── src/
│ ├── one/
│ │ ├── two/
│ │ │ └── two.go
│ │ └── one.go
│ └── zero.go
├── go.mod
└── app.go
The application is called my-app, which will be the module name for app.go. We define this once in go.mod and then each of all the other go files in subdirectories will automatically be importable as if they were namespaced.
Given the above, two.go, assuming it contains a function named Two, will be importable in app.go by using my-app/src/one/two.
Here's what you need to do to achieve this:
go.mod
module my-app
two.go
package two
func Two() string {
return "I'm totally not supposed to be using go modules for this"
}
app.go
package main
import "my-app/src/one/two"
func main() {
two.Two()
}
If you were to place another file within two/, then you would simply use two.TheNewFunc() as long as you made TheNewFunc() available within the new file.
I created a very simple GitHub repo which you can check out as a demonstration.
Your import should be an absolute one:
import "github.com/abonec/go_import_problem/models"
If you don't want to export your project to an external referential, you can do a:
import "go_import_problem/models"
(That is: "the name of your project folder accessible by GOPATH/your package")
See "How to use custom packages in golang?".
And you would use:
models.User
As mentioned in Effective Go:
The importer of a package will use the name to refer to its contents, so exported names in the package can use that fact to avoid stutter.
(Don't use the import . notation, which can simplify tests that must run outside the package they are testing, but should otherwise be avoided.)
kostix adds in the comments:
to reiterate, names of Go packages are always absolute (that is, there's no relative package names, neither with ./ nor with ../ or anything like that) but that names are "anchored" to one of the so-called workspaces listed in $GOPATH.
When Go searches for a package, it looks through workspaces and tries to find a package in each of them, in order.
The search is not recursive.
And no, there's no requirement to encode URLs in package paths -- unless you want to make your package public.
You need to qualify items in in a package by its package name
So
fmt.Println(models.User{"new_user"})
Breaking up a single project into subfolders is not the recommended way of structuring a go project, which is why there is basically no good way to do what you want.
If the project is really large, and too unwieldy to make a single package, consider splitting it into several totally distinct packages, rather than special sub-directory packages. This has the advantage of forcing you to think cleanly about your internal APIs.
The packages are referenced in code in relation to your "go/src" folder
└── go
└── src
└── myAwesomeProject
├── main.go
└── models
└── user.go
So in main.go
package main
import (
"fmt"
"myAwesomeProject/models"
)
Similarly packages can reference each other using the same convention.
You should use your imported objects by it's imported names. For example if you
import "./models"
with struct User you should use it as
models.User

Resources