Go Packages

Summary: in this tutorial, you’ll learn about Go packages to organize code and make it reusable.

Introduction to Go packages

In Go, a package is a collection of related source code files that are compiled together. Each package serves a single purpose.

Packages in Go are similar to modules or libraries in other programming languages.

Every standalone Go program has at least one package called main:

package main

import "fmt"

var message = "Hello, World!"

func say(message string) {
    fmt.Println(message)
}

func main() {
    say(message)
}Code language: Go (go)

When you launch the program, Go runtime looks for the main() function inside the main package. Therefore, a Go program requires at least a main package that includes the main() function.

Package scopes

In the above program, the main package includes a message variable, the say and main functions. These variables and functions are package scope.

In Go, identifiers such as variables and functions are either package or function scope. There is no “global” scope.

In Go, you can declare anything at package scope. But you can’t use the short declaration operator :=. For example, the following declaration results in a compilation error:

package main

import "fmt"

message := "Hello, World!" // ERROR

// ...Code language: Go (go)

Package visibility

In Go, any capitalized name is automatically exported. This means that you can use it from other packages.

For example, the Println function from the fmt package has the letter P in uppercase, so you can use it in your package.

On the other hand, any name that is not capitalized can be used only within the package.

Importing packages

A package can import other necessary packages. Like variables, unused package imports will result in an error. To import a package, you use the import statement followed by the package name:

package nameCode language: Go (go)

To import multiple packages, you place them within parentheses:

import (
  "fmt"
  "os"
)Code language: Go (go)

Go does not allow import cycles. For example, a package P cannot import a package that imports P. The following will result in an error:

Package p

package p

import "q"

// ...Code language: Go (go)

Package q:

package q

import "p"

// ...Code language: Go (go)

To fix this import cycle, you need to move dependencies to a third package or eliminate them.

Package init() function

The init() function is a special function that the Go runtime will call automatically when the package is initialized.

Typically, you use the init() function to set up the initial state for the package before any other code within the package executes.

Here are some key points of the init() function:

  • The init() function takes no argument and doesn’t return any values.
  • Each package can have multiple init() functions. Go runtime will call them in the order they appear in the package.
  • Go runtime calls the init() function before the main() function in the main package.
  • Typically, you use the init() function to initialize package-scoped variables, load the configuration files and establish a database connection.

The following example shows how to use the init() function to create a log file with the name app.log and set the log output to that file:

package main

import (
    "log"
    "os"
)

func init() {
    // Create a log file
    file, err := os.OpenFile("app.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
    if err != nil {
        log.Fatalf("Failed to open log file: %v", err)
    }

    // Set log output to the file
    log.SetOutput(file)
}
func main() {
    log.Println("This is a log message")
}Code language: Go (go)

Go package example

Step 1. Open your terminal and create a new directory to store the source code files:

mkdir myappCode language: Go (go)

Step 2. Navigate to the project directory:

cd myappCode language: Go (go)

Step 3. Initialize a Go module:

go mod init myappCode language: Go (go)

Step 4. Create a new directory for the greeting package:

mkdir greetingCode language: Go (go)

Step 5. Create a greeting.go file inside the greeting package:

package greeting

import (
    "fmt"
    "time"
)

func Greet(name string) string {
    t := time.Now().Hour()
    var message string
    switch {
    case t < 12:
        message = fmt.Sprintf("Good morning, %s", name)
    case t < 17:
        message = fmt.Sprintf("Good afternoon, %s", name)
    default:
        message = fmt.Sprintf("Good evening, %s", name)
    }
    return message
}Code language: Go (go)

The greeting package has the Greet() function that returns a greeting message to the person with the specified name.

Step 6. Call the Greet() function from the greeting package from the main() function of the main package:

package main

import (
    "fmt"
    "myapp/greeting"
)

func main() {
    message := greeting.Greet("Joe")
    fmt.Println(message)
}Code language: Go (go)

How it works.

First, import the fmt and greeting packages:

import (
    "fmt"
    "myapp/greeting"
)Code language: Go (go)

Second, call the Greet() method of the greeting package inside the main() function

func main() {
    message := greeting.Greet("Joe")
    fmt.Println(message)
}Code language: Go (go)

Summary

  • A package is a collection of related source code files compiled together.
  • Go runtime calls init() functions in the package first to set the initial state for the package.
  • Go automatically exports names that are capitalized, so you can use them in other packages.
Was this tutorial helpful?