Go - Packages



A package is like a folder that puts your program into order by classifying related functions, types, and files that makes your program neat, reusable, and modular. For instance, the fmt package provides facilities to display messages on the screen and avoids name conflicts.

All programs begin running from the main package, which is the entry point. When developing your own package, add a package declaration at the top of your Go language program to specify its purpose and keep everything organized.

Here, we have two significant kinds of packages to learn −

  • Standard Library Packages:These are pre-built for operations such as dealing with I/O, dealing with strings, dealing with concurrency, and more. For instance, fmt package deals with formatted I/O and the net/http package deals with creating HTTP servers.
  • User-defined Packages: Users can define their own packages to encapsulate and reuse their code in different projects.

Importing Packages

We can import the package by using the "import" keyword followed by the package name that you want to import (which handles formatted I/O).

If you want to import "fmt" package, you can import like this:

import "fmt" 

Package Declaration

Every Go language program begins with a package declaration. We can declare a package by using the "package" keyword followed by the package <name>.

Here is the syntax to declare a package −

package "package_name"

For example, if you want to declare a pacakage name as "main". Then the syntax will be as below−

package "main"

The main package is only required for executable programs, as it defines the entry point (the main() function). For reusable libraries, any other package name can be used as below −

package "math"
package "utils"
package "strings"
.....etc

Example

This ensures that when you run a program, the main package is executed first.

package main
import "fmt"
func main() {
    fmt.Println("Hello, Golang Packages!")
}

It will generate the following output −

Hello, Golang Packages!

Blank Import

Sometimes, you may want to import a package but not actually use it in your code. Therefore, the compiler complains about unused imports. To avoid this, you may use a null import, denoted by an underscore _ before the package name.

import _ "strings"

Example

This is helpful if you want to turn on optional features that a package offers at compile-time without actually using it in your code.

package main
import _ "fmt"
func main() {
    // fmt is not directly used, but importing may enable special features during compile-time.
}

Nested Packages

You can create nested packages by having packages held within sub-directories. Nested packages work like folders inside folders. They can be imported just like regular packages by specifying their path.

import "math/complex"

Example

Here, complex is a nested package inside the math package, and it can be used for handling complex numbers.

package main
import (
   "fmt"
   "math/cmplx"
)
func main() {
   // Define a complex number
   complexNum := complex(3, 4) // Represents 3 + 4i
   // Calculate magnitude and phase of the complex number
   magnitude := cmplx.Abs(complexNum)
   phase := cmplx.Phase(complexNum)
   // Print the results
   fmt.Println("Complex Number:", complexNum)
   fmt.Println("Magnitude:", magnitude)
   fmt.Println("Phase (radians):", phase)
}

It will generate the following output −

Complex Number 1: (3+4i)
Complex Number 2: (1+2i)
Sum: (4+6i)
Magnitude of Complex Number 1: 5

Built-in Packages

Built-in packages are pre-made tools for general tasks, which save your time and energy. They are included in the standard library and support a large variety of functionalities.

  • fmt:It is used to format and print output (e.g., fmt.Println to print text).
  • strings: Offers functions to work with strings, such as case change, splitting, or searching in text.
  • math: Includes functions for mathematical operations like square roots, powers, and trigonometry.
  • net/http: Used to create web servers and handle HTTP requests.
  • io and os: Helps with reading and writing files, working with input/output streams, and interacting with the operating system.
  • time: Used for working with dates, times, and durations.

Access Modifiers

The visibility of identifiers (functions, variables, constants, etc.) is determined by their naming convention:

An identifier with a name that begins with an uppercase letter is exported and can be accessed outside the package, and an identifier with a lowercase name is unexported and can only be accessed within the package.

Example

In this example, we illustrate invoking an exported function (callable from other packages) and an unexported function (callable within the same package) to print messages.

package main
import "fmt"
// Exported function
func HelloWorld() {
    fmt.Println("Hello, World!")
}
// Unexported function
func helloWorld() {
    fmt.Println("hello, world!")
}
func main() {
   HelloWorld()  // Calling the exported function
   helloWorld()  // Calling the unexported function
}

It will generate the following output −

Hello, World!
hello, world!

Aliasing Imports

When importing packages, you can give them an alias to simplify usage in your code

import io "fmt"
func main() {
    io.Println("Using alias for fmt package")
} 

It will generate the following output −

Using alias for fmt package

Initializing Packages

You can implement an init() function inside a package, which gets executed when the package is imported. This helps in initializing configurations or variables.

package example
import "fmt"
func init() {
    fmt.Println("Package initialized")
}

The above program generates the following output −

Package initialized

Third-Party Packages

You can use third-party packages from external sources by integrating them with the Go Modules system.

First, initialize your project:

go mod init your_project_name

Then, add a dependency:

go get github.com/example/package

Finally, import and use the package in your code:

import "github.com/example/package"

Example

Here, we use a third-party package to print the message "This text is green!" in green color on the terminal.

// Run these commands in your terminal:
// 1. Initialize your module: go mod init myproject
// 2. Install a third-party package: go get github.com/fatih/color
package main
import "github.com/fatih/color"
func main() {
    color.Green("This text is green!")
}

The above program generates the following output −

This text is green!

Package Documentation

The go doc tool can help you generate and view documentation for your package.

go doc fmt

Example

This command helps developers understand the package and its functions without referring to external documentation. It’s a handy way to explore and learn about Go packages in your terminal.

package fmt // import "fmt"
Package fmt implements formatted I/O with functions analogous to C's printf and scanf.
...
func Println(a ...interface{}) (n int, err error)
...

The terminal will display a summary of the fmt package, including an overview of its purpose, functions, and usage.

Example of User-defined Package: Folder structure

The folder structure for a user-defined package means organizing your files in separate folders, where the main program is in one folder, and the package code (functions/types) is in its own folder.

/myproject
  main.go
  greetings
     hello.go

File: greetings/hello.go

package greetings
import "fmt"
func Hello() {
    fmt.Println("Hello from greetings package!")
}

File: main.go

package main
import (
    "myproject/greetings"
)
func main() {
    greetings.Hello()
}

The above program generates the following output −

Hello from greetings package!

The Hello() function within the greetings package is invoked from the main package, and it prints out the given message to the console. This shows how to make use of a user-defined package within a Go program.

Advertisements