Part 1

Package Scope

We structure our code in packages. We also import other packages from standard library and external sources. In the last application we had only one file main.go. But we could also have more than one file in our application. All the files in the same folder level are in the same package. All variables and functions in the package scope are shared.

If you haven’t already clone this repository from Part 1

# from the root of the repository.
# if you are in any folder change directory to root
cd packaging

The folder structure of packaging folder looks like this

├── file1.go
├── file2.go
└── main.go

The content of the files are following.

// main.go
package main

import "fmt"

func main() {
	fmt.Println(data1, data2)

// file1.go
package main

var data2 = "world"

// file2.go
package main

var data2 = "world"

The files does not have much things. But it will be enough to demonstrate.

Lets try to build it again.

go run main.go

We get an error.

# command-line-arguments
./main.go:6:14: undefined: data1
./main.go:6:21: undefined: data2

Huh! I said just a moment ago that the variables in package are shared. But this is saying the variables are undefined. What could this be.

The problem is actually with our go run command. We are telling go to run the main.go file. But it is not the only file needed for our application to work. We need to let go build tool know that it needs to include the other files too. We can do one of two things

go run main.go file1.go file2.go
go run *

We will talk about how to build packages for external use in a later chapter.


We can import any standard library packages by putting them at the top of our file. If we have more than one import we can add multiple import statements or putting in an import block.

import (

There are many packages in the standard library. You can find them here . These packages come bundled with Go runtime.

But what if we want to use a package that is not part of the standard library. We will use Go modules for that.

Go modules are the way we manage dependencies in our Go application. It is comparable to package.json for node or requirements.txt for python.

You can create a new module with go mod init <modulename>. To download a module we run go get <modulepath>. This updates our go.mod file with the module. If you clone a repository with a populated go.mod file. You can download the necessary modules with go mod download.

From the root of the repository

cd importing
go mod download
go run main.go

We should see on our terminal some thing like this print.

hello world


Exporting can mean two different things. One is package level export. Exporting local packages to be used in other local packages. And the other is exporting our amazing library for the world to use. When you are building a Go application that you expect other people to import use the module path that represents the git repository. For example if your code is going to github.com/username/pkg name the module as github.com/username/pkg

In our example our code will be living in github.com/moficodes/go-crash-course/exporting so we create a new module in the exporting folder with that name. We have another folder called print with a file print.go and package print. The file structure looks like the following.

├── go.mod
├── main.go
└── print
    └── print.go

We can import this print package in the main package with

import "github.com/moficodes/go-crash-course/exporting/print"

In our main function we try to use two variables defined in print package.

// print/print.go
package print

var data = "hello"
var Number = 1

If we try to run our application from exporting folder:

go run main.go

We would see:

# command-line-arguments
./main.go:10:14: cannot refer to unexported name print.data

What just happened? We got an error about one of the two variables defined in our file as not being exported. But we did not put any special instruction to export either of those variables.

In Go anything that starts with an uppercase letter gets exported. This is different from languages like Java or JavaScript where you have to explicitly declare something being exported. This is pretty nice because the language semantics actually carry meaning.

The same uppercase rule is true for imported packages too.

Next Steps

This is Part 2 of this Go crash course series.

Part 3