Search
Close this search box.

Packages in Go allow you to encapsulate related logic into reusable component, create leaner project structure and improve maintainability. For the sake of this example we will recognize two types of packages, first one is the main package that serves as entry point to your application, second type are custom packages that you create to organize your code into components or blocks.

The main package

Package main serves as the entry point to your Go program. This package is required for all Go applications and cannot be omitted. The most common place would be to place it in the root of your project, in a folder called main.go.

The main package must always contain function main() which is the first function that is executed and will call any additional logic in your Go application.
Keep in mind that the main function never takes any arguments and doesn’t return a value.

package main

import "fmt"

func main() {
    fmt.Println("Hello, world!")
}

If you are using GoLand, your main function will have green ▶️ button next to it, identifying the entry point for your application.

Beyond the basics: main

You can use environment variables and command line arguments by using os.Getenv and os.Args to access respective values within the main function. Further, you can also use the main function to handle errors gracefully using panic, recover, and defer keywords.

In case you are using an init function, all init functions will execute before main is called, be mindful of this when designing your applications.

Read more about init functions: https://go.dev/doc/effective_go#init

Custom packages

Custom Go packages allow you to organize code in reusable blocks, that can either be shared within a project or externally as a private repository or a public package.

To start building your first package create a folder in your project with main.go file inside that folder. When naming your package, you should consider that the name of your package will become accessor to it’s functionality. This means that package “myawesomepackage” with function ConvertCSVToXML() would make the exported function ConvertCSVToXML accessible under myawesomepackage.ConvertCSVToXML() – please read carefully the section Naming packages to get tips on proper package naming; in this specific case the package “myawesomepackage” isn’t descriptive, and the name is relatively long, which long term might negatively impact the development experience for the users.

Let’s change the name of the package to “converter” and build out some functionality. For that I’m going to create folder “converter” with single main.go file. If you are using GoLand, the package name will automatically be prefilled for you based on the folder name.

package converter

import "fmt"

func init() {
    fmt.Println("Initializing converter")
}

Now that we have created our “converter” let’s create another package inside of it called “csv”. For that we are going to create sub folder to “converter” called “csv” and create another main.go file.

package csv

import "fmt"

func init() {
    fmt.Println("Initializing converter/csv")
}

At this point your folder structure should look like the below.

Now let’s declare some functionality, inside the “converter” main.go let’s add two functions textToCSV() and TextToHTML() that take text argument of type string and returns another string.

package converter

import "fmt"

func textToCSV(text string) string {
    return "csv"
}

func TextToHTML(text string) string {
    return "html"
}

func init() {
    fmt.Println("Initializing converter")
}

Let’s do the same for the csv package, but this time create only one function that will be named TextToCSV().

package csv

import "fmt"

func TextToCSV(text string) string {
    return "csv"
}

func init() {
    fmt.Println("Initializing converter")
}

Now that our custom packages have functionality, let’s go to main and try to call them!

package main

import (
	"GoFeedBasics/converter"
	"GoFeedBasics/converter/csv"
)

func main() {
    // textToCSV will be invalid in context of converter
    converter.textToCSV("Hello, world!")
    // TextToHTML imports successfully
    converter.TextToHTML("Hello, world!")

    // TextToCSV imports successfully
    csv.TextToCSV("Hello, world!")
}

What you’ll notice here is that while we are able to use functionality from both packages that the textToCSV function on converter isn’t available. This is because in Go you must capitalize the first letter of a function that you want to export, that is make usable outside of it’s source package.

Another thing to notice here is when we imported functionality from both packages, our csv package shows import from converter/csv following the path where the package is defined, yet being accessible by the package name, that is “csv”.

One last thing to pay attention to here is that there is another csv package that comes from encoding library prepackaged with Go, while the names of both packages are csv, when importing either of the packages you can give them an alias by prefixing the import by the desired accessor name that will replace “csv”.

package main

import (
	converterCSV "GoFeedBasics/converter/csv"
	"encoding/csv"
)

func main() {
	converterCSV.TextToCSV("Hello, world!")
	csv.NewWriter(nil)
}

See how we imported both csv packages but we called our custom package converterCSV instead to avoid overlap between functionality (that would cause your application to not compile).

Beyond the basics: Naming packages

When naming your packages it’s important to keep the names lower case, single word, short and concise. Don’t use any underscores, or mixedCaps.

Avoid repetition by giving your functions context specific names considering the import scenario and leverage the structure to create clarity (✅ bufio.Reader vs ❌ bufio.BufReader)

Deep dive into package naming: https://go.dev/doc/effective_go#package-names

TLDR;

Use Go packages to build reusable components. Stick to short and concise naming, favor clarity over length. Be mindful of import scenarios.

Get some practice in by building an API wrapper, date formatter or any other package you can imagine that will make your life easier in the future, continue reading future posts to learn about sharing your packages with community & and become better at Go lang.

Share the Post: