Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I develop a go package in multiple source directories?

Tags:

go

I am developing a go package, which is a little bit complex and thus I want to organize the source code into multiple directories.

However, I don't want the users of the package to have to use too long imports. Anyways, the internal structure of the package isn't their concern.

Thus, my package structure looks so:

subDir1
  subSubDir1
  subSubDir2
subDir2
  subSubDir3

...and so on. All of them have their exported calls.

I would like to avoid that my users have to import

import (
  "mypackage/subDir1"
  "mypackage/subDir1/subSubDir2"
)

...and so on.

I only want, if they want to use an exported function from my package, they should have access all of them by simply importing mypackage.

I tried that I declare package mypackage in all of the .go files. Thus, I had source files in different directories, but with the same package declaration.

In this case, the problem what I've confronted was that I simply couldn't import multiple directories from the same package. It said:

./src1.go:6:15: error: redefinition of ‘mypackage’
   "mypackage/mysubdir1"
               ^
./src1.go:4:10: note: previous definition of ‘mypackage’ was here
   "mypackage"
          ^
./src1.go:5:15: error: redefinition of ‘mypackage’
   "mypackage/mysubdir2"
               ^
./src1.go:4:10: note: previous definition of ‘mypackage’ was here
   "mypackage"
          ^

Is it somehow possible?

like image 250
peterh Avatar asked Aug 26 '17 20:08

peterh


People also ask

Can you have multiple Go paths?

Yes. The Go path is used to resolve import statements. It is implemented by and documented in the go/build package.

How do I make multiple packages in Golang?

Check your GOPATH in environment variables and set it to the directory which contains all Go files. Create a new folder with the name of the package you wish to create. In the folder created in step 2, create your go file that holds the Go package code you wish to create.

How can you tell Go to import a package from a different location?

Go first searches for package directory inside GOROOT/src directory and if it doesn't find the package, then it looks for GOPATH/src . Since, fmt package is part of Go's standard library which is located in GOROOT/src , it is imported from there.

How do packages work in Go?

Go programs are organized into packages. A package is a collection of source files in the same directory that are compiled together. Functions, types, variables, and constants defined in one source file are visible to all other source files within the same package. A repository contains one or more modules.


1 Answers

You should not do this in any case, as the language spec allows a compiler implementation to reject such constructs. Quoting from Spec: Package clause:

A set of files sharing the same PackageName form the implementation of a package. An implementation may require that all source files for a package inhabit the same directory.

Instead "structure" your file names to mimic the folder structure; e.g. instead of files of

foo/foo1.go
foo/bar/bar1.go
foo/bar/bar2.go

You could simply use:

foo/foo1.go
foo/bar-bar1.go
foo/bar-bar2.go

Also if your package is so big that you would need multiple folders to even "host" the files of the package implementation, you should really consider not implementing it as a single package, but break it into multiple packages.

Also note that Go 1.5 introduced internal packages. If you create a special internal subfolder inside your package folder, you may create any number of subpackages inside that (even using multiple levels). Your package will be able to import and use them (or to be more precise all packages rooted at your package folder), but no one else outside will be able to do so, it would be a compile time error.

E.g. you may create a foo package, have a foo/foo.go file, and foo/internal/bar package. foo will be able to import foo/internal/bar, but e.g. boo won't. Also foo/baz will also be able to import and use foo/internal/bar because it's rooted at foo/.

So you may use internal packages to break down your big package into smaller ones, effectively grouping your source files into multiple folders. Only thing you have to pay attention to is to put everything your package wants to export into the package and not into the internal packages (as those are not importable / visible from the "outside").

like image 180
icza Avatar answered Nov 15 '22 07:11

icza