SPONSORED ADS

Everything you need to know about Packages in Go

Last Updated Feb 28, 2023

Packages in Go are a way of organizing code and reusing functionality across different projects. A package in Go is a collection of related Go source files that can be compiled together into a single binary or library. All source files in the same package can see the functions, types, variables, and constants that are defined in one source file.

Packages are the most important units of logic. They usually show big, abstract ideas that are very different from each other. The meaning of directories is different in Go than in most popular programming languages. Other languages usually only use directories to namespace things. This is a workaround for dealing with the filesystem and has little to do with the structure of the problem domain itself. In Go, each directory is a package, which is a logical unit. It is easier to build high-level spatial links by just looking at the directory tree.

Since version 1.11 (released date 24 August 2018) Go introduce modules. If you are working on Go packages, then you should consider relocating your project to Go Modules.

Go Modules

Go modules are a dependency management system that help you manage the dependencies of your Go project. Go modules allow you to specify which versions of external packages your project depends on, ensuring consistent and reliable builds.

Go modules are a powerful and easy-to-use dependency management system for Go projects. They allow you to manage your project's dependencies with ease, ensure consistency across builds, and provide a way to manage private packages.

Initialize

You can initialize a new Go module in your project using the go mod init command. This command creates a new go.mod file in the root of your project that keeps track of the dependencies and versions used in your project.

Let's create a sample program nodeepshit my github

$ mkdir nodeepshit # create directory
$ cd nodeepshit 
$ go mod init github.com/clgt/nodeepshit

My github username is clgt. Feel free to change it to yours. We don't need to publish or create the repository first; we just need to give it a unique name in case we want to publish it later.

If everything go as plan, your terminal will print out something like this

go: creating new go.mod: module github.com/clgt/nodeepshit

Install dependency

You can use the go get command to add a new dependency to your project. For example go get github.com/Machiel/slugify. When you add a new dependency, Go modules will automatically update the go.mod file with the required version. Let's do it.

go get github.com/Machiel/slugify

Check content of your go.mod. It should look like bellow

module github.com/clgt/nodeepshit

go 1.19

require github.com/Machiel/slugify v1.0.1 // indirect

Go modules use semantic versioning to manage dependencies. This means that when you add a dependency to your project, Go modules will try to use the latest version that matches your specified version constraint.

Update dependency

You can use the go get -u command to update all of your dependencies to their latest compatible versions. Go modules will automatically update the go.mod file to reflect the new versions of the dependencies.

Package declaration

Each Go source file belongs to a package, and the first line of every Go source file must be a package declaration. The package name should be short and descriptive.

The main package is a special package in Go. It's the entry point for a Go program that can be executed from the command line. A Go program must have a main package and a main function to be executable.

Let's create our main package.

image

Package imports

To use functionality from other packages, you need to import them into your package. The import statement at the top of your source file specifies which packages your code is using.

package main

// Importing packages
import "fmt"

func main() {
	s := "everything should be simple"
	fmt.Println(s)
}

fmt is a standard package for Go. It came with Golang, so we don't need to install it to use it. We have already install the Machiel/slugify package, so let's use it.

image

Visibility (Exported and Unexported function/name )

In Go, the visibility of a function or variable is controlled by its name. If the name starts with a lowercase letter, it's only visible within the package. If the name starts with an uppercase letter, it's visible outside the package.

For example slugify.Slugify: slugify is the package name where Slugify is the function name, because Slugify start with uppercase letter we can call it in our main package which is surely outsite of the slugify package.

Custom Package

We have been importing a go standard package until now (fmt). We also install and import package from third parties. But we can't finish this tutorial until we make our own custom package, right.

Yeah Let's do it. We'll make a custom "config" package because every service needs some configuration.

mkdir config # create new folder
cd config
touch config.go # create a file

image

Our config package is easy to understand. It can be used to Read a json file (start with uppercase so it is exported)

Full code here

package config

import (
	"encoding/json"
	"io/ioutil"
)

type Config struct {
	Name       string
	AuthorName string
}

// Default value 
func (c *Config) Default() error {
	if c.Name == "" {
		c.Name = "Nodeepshit"
	}
	if c.AuthorName == "" {
		c.AuthorName = "multiplexer"
	}
	return nil
}

func Read(path string) (*Config, error) {
	b, err := ioutil.ReadFile(path)
	if err != nil {
		return nil, err
	}
	return parse(b, path)
}

func parse(b []byte, path string) (*Config, error) {
	c := &Config{}
	if err := json.Unmarshal(b, c); err != nil {
		return nil, err
	}
	if err := c.Default(); err != nil {
		return nil, err
	}

	return c, nil
}

Now back to our main function, we will import and use the config package. But first let's create config.json

// file: config.json
{
    "Name": "Nodeepshit"
}

Then update our main package

// file: main.go
package main

import (
	"fmt"

	"github.com/Machiel/slugify"
	"github.com/clgt/nodeepshit/config"
)

func main() {
	cfg, err := config.Read("./config.json")
	if err != nil {
		panic(err)
	}
	s := "everything should be simple " + cfg.Name
	slug := slugify.Slugify(s)
	fmt.Println(slug) // everything-should-be-simple-nodeepshit
}

If everything okay, run the program with go run main.go will result in everything-should-be-simple-nodeepshit

image

Conclusion

That’s all folks! Basically packages are a fundamental concept in Go that allow you to organize and reuse code effectively. While modules are a powerful and easy-to-use dependency management system. Together they help us create robust and maintainable Go code.

References

https://go.dev/blog/migrating-to-go-modules

Hi there. Nodeepshit is a hobby website built to provide free information. There are no chargers to use the website.

If you enjoy our tutorials and examples, please consider supporting us with a cup of beer, we'll use the funds to create additional excellent tutorials.

If you don't want or unable to make a small donation please don't worry - carry on reading and enjoying the website as we explore more tutorials. Have a wonderful day!