Table of Contents
Brief overview on package and import in Golang
Package in Go
A package
is simply a directory within your Go workspace that contains one or more Go source files or other Go packages. Every Go source file belongs to a package. To include a source file in a package, use the following syntax:
package <packagename>
The package declaration mentioned above must be your Go source file's first line of code. All the functions, types, and variables defined in your Go source file become part of the declared package. You can export a member defined in your package to other packages or keep it private to the same package. Other packages can import and reuse the functions or types that your package exports. For example, almost all the code that we have seen so far in this tutorial series includes the fmt
package:
Package fmt implements formatted I/O with functions analogous to C's printf and scanf. The format 'verbs' are derived from C's but are simpler.
The benefits of using package
:
- It reduces naming conflicts. You can have the same function names in different packages. This keeps our function names short and concise.
- It organizes related code together so that it is easier to find the code you want to reuse.
- It speeds up the compilation process by only requiring the recompilation of smaller parts of the program that has actually changed. Although we use the
fmt
 package, we don’t need to recompile it every time we change our program.
Import in Golang
As the name suggests, this keyword imports the specified package from the directory of $GOPATH (if no path is mentioned) or else from the mentioned directory. Importing simply means bringing the specified package from its source location to the destination code, wiz the main program. Import in Go is very important because it helps bring the packages which are super essential to run programs.
An import declaration states that the source file containing the declaration depends on functionality of the imported package (§Program initialization and execution) and enables access to exported identifiers of that package. The import names an identifier (PackageName) to be used for access and an ImportPath that specifies the package to be imported.
ImportDecl = "import" ( ImportSpec | "(" { ImportSpec ";" } ")" ) .
ImportSpec = [ "." | PackageName ] ImportPath .
ImportPath = string_lit .
Import struct from another file or package
For those above advantages, sometimes we have to import struct from another package and file rather than copy the entire code. If we do not use importing package/file and copy the struct, when the struct is changed, you have to modify all the defined struct, which is a waste of time and may cause errors. For example, we have a project with below structure:
There are 2 package: helper
and main
. In helper package, we define some helper classes and structs. Main package contains main class to execute the logic of our program. We define 2 struct in helper package: Student
and Class
struct:
Student struct:
package helper
type Student struct {
FirstName string
LastName string
Age int
}
Class struct:
package helper
type Class struct {
Lecturer string
StudentCount int
}
If we want to use Class
or Student
struct in main.go
, you have to copy those two struct from helper package or simpler, import it.
package main
import (
"fmt"
"helper"
)
func main() {
fmt.Println("Main class")
// Use <package.Struct> name i.e. helper.Class
// to access Class struct from helper package
class1 := helper.Class{
Lecturer: "TestClass",
StudentCount: 31,
}
// Use <package.Struct> name i.e. helper.Student
// to access Student struct from helper package
student1 := helper.Student{
FirstName: "Anna",
LastName: "Cody",
Age: 20,
}
fmt.Println("Class 1: ", class1)
fmt.Println("Student 1: ", student1)
}
Output:
Main class
Class 1: {TestClass 31}
Student 1: {Anna Cody 20}
Fields that start with LOWER CASE characters are package internal and not exposed, If you want to reference the field from another package it needs to start with an UPPER CASE character.
For example: If we change the Class
struct to class
then the struct itself will not be accessible from another file. If we change the elements name, notice the lowercase, L
was changed to l
for lecturer
and S
to s
in studentCount
:
package helper
type Class struct {
lecturer string
studentCount int
}
When compile main.go
, the output will be:
.\main.go:12:3: unknown field 'lecturer' in struct literal of type helper.Class
.\main.go:13:3: unknown field 'studentCount' in struct literal of type helper.Class
Summary
In this article, I demonstrated how to use package
and import
to organize source code in Golang. They allow us to easily reuse code, such as when we want to use a struct from another package or file. When importing, be careful with the package path and remember that the data field must start with an upper case character.
References
https://pkg.go.dev/fmt
https://go.dev/ref/spec#Packages
https://go.dev/ref/spec#Import_declarations
Further Reading
Import struct from another package and file golang