Golang: Packages
Tags: go
Published: 2022-04-22 17:22:52

## Introduction

In this 11th part of the series, we will be covering packages in golang. Package is a cool way to organize code in large projects. We can create a separate file which can include certain helper functions or variables from other files or scripts. There are couple of types of packages like packages from the standard library, open sourced community packages and custom packages that you can build of your own. In this particular section, we will be covering the fundamentals of packages and exploring the standard library in golang. 

## What is a Package ?

Package in simplest of terms is a collection of go scripts that can serve a purpose. Just like `fmt` has several functions like `Println`, `Printf`, `Scan`, `Scanf`, etc. most packages have functions that we can use in our own programs to solve a simple problem. We have already created many packages but none of them have been super useful so far, we just used the statement `package main` and didn't use the package anywhere. Every package has a entry point called `main` along with a entry function `main` which is triggered when we run the package. 

```
- package_name
    - script_1.go
    - script_2.go

    - sub_package_name
        - utility_1.go
    - go.mod
```

The above is a simple folder structure for a package in golang, we have the package itself as the name of the folder. Inside of the package folder, we would have the scripts or sub-packages if any. Also there is a `go.mod` file in all go source package folders which contain the meta information about the package and it's dependencies. 

Let's take a look at the [fmt](https://github.com/golang/go/tree/master/src/fmt) package source code, it has a [print.go](https://github.com/golang/go/blob/master/src/fmt/print.go) file which has all the functions associated with printing, similarly separate files for different core functionality.

We will soon into the details of packages in this series. Right now, we only care about the fundamentals of a package in golang.

## Importing Packages

We have been already importing a package since writing our hello world in go, the `fmt` package which holds some functions for formatting, printing, logging and various string input/output manipulation. 

```go
import "fmt"
```

So, we have used the simple `import "package"` statement, but there are a couple of more ways to import packages if we have multiple packages to import.

```go
import (
    "fmt"
    "math"
)
```

Using the `()` and by specifying the name of the package we can import multiple packages at once. Also there is a harder way out there, if you really like to toil hard.

```go
import "fmt"
import "math"
```

This is generally avoided as it just looks too pythonic, we are in golang. 

### Aliasing Imported packages

We can alias an package a name whatever we want for the usage in the rest of the script file. This allows a bit better semantics of longer package names into readable code. 

```go
package main

import (
	"fmt"
	r "math/rand"
)

func main() {
	fmt.Println(r.Int())
}
```

```
$ go run import.go
3454565657742387432
```

We have imported the package `math/rand`, here [rand](https://pkg.go.dev/math/rand@go1.18.1#Int) is a sub package of the main package math. Hence we have aliased the rand package as `r` and thus, we can use r to access all the functions and other types from the package. 


### Blank Package Import

We can even import the package but not use it without getting a compilation error. So, the blank identifier is used in golang to ignore the initialized or returned values from any context and avoid the compilation warning or errors.  

```go
package main

import (
	_ "fmt"
)

func main() {
}
```

```
$ go run blank_import.go
```

Here, we have imported `fmt` package with a `_` blank identifier but we didn't use it anywhere, still we don't get any error messages and it compiled the code successfully.

## Standard Library Packages

The Golang Standard Library has some good number of packages which can be used for some general tasks like formatting input/output, file handling, web requests, system commands, etc. You can check out the entire list along with the documentation on the [official website](https://pkg.go.dev/std). 

We can import these standard library packages just by parsing their name in the string quotes like we did with `fmt` as `"fmt"`. We have previously used the `rand` package from the math standard library package as a sub-package by using the statement `"math/rand"`, if we want we can import the entire `math` package as `"math"` but that's unwanted and we import only the package which we really need.

There are other packages as well like `bufio` which is used for reading and performing operations with text, `os` for working with files systems and operating system level stuff, and other packages which are specific to use cases like rendering templates, time, sorting, math operations, encoding, etc. We will dive into some of them throughout this series. 

## Installing Packages

We can now get into installing other packages which are not in the standard library. You can get the documentation along with all references for a particular package on the official Golang [package repository](https://pkg.go.dev/). We use the CLI command to grab the packages into our `GOPATH`. OK, GOPATH, we have not covered this!

### GOPATH

GOPATH is the path or the location in your system's disk where all the packages and modules are stored. You can get the default location of your GOPATH environment variable from the simple shell command.

```
$ echo $GOPATH
C:\Users\acer\go
```

It has a few folders namely, `bin`, `pkg`, and `src`. These folder server different purpose like: 

- `bin` for storing the binaries generated from `go install` command
- `pkg` for storing pre-compiled source files and objects for quicker generation of executables and compilation.
- `src` for storing all the go source files of packages and modules.

### Go Get command

Now, let's see how to install a package from the go community on GitHub.  

```
go get github.com/gorilla/mux
```

We have installed a package which is a powerful HTTP router and a URL dispatcher and it can also be used to make web applications. It's called `mux`, we won't be using it right away just to get a feel for installing and playing with packages at the moment. 

After executing the command `go get` you should see a folder to be added in the `$GOPATH\pkg\mod` as `github.com\gorilla` and inside of it we should have a mux folder with the latest version. So, the `go get` command is used to download and install a package along with its all dependencies.

### Set up a project for using a package

Now, we have got the package so we can import it from anywhere in our go environment. 

#### Create a new folder (any name)

You can test a go package from a isolated environment from the GOPATH by creating using the mod command. 
The `mod init` command is a official way to create modules in golang and it creates kind of a environment to work on a templated project and structure the project/module/package properly. 

```
go mod init
```

#### Install the packages 

We have already installed the package but that was a global install in the GOPATH, so we need to install it in this module. 

```
go get github.com/gorilla/mux
```

#### Use the package

Now, we can move into actually using the package in our source go file. We won't do any thing complicated just a simple web server. It's too easy don't worry!

```go
package main

import (
	"net/http"

	"github.com/gorilla/mux"
)

func main() {

	router := mux.NewRouter()

	router.HandleFunc("/", Server)

	http.ListenAndServe(":8000", router)
}

func Server(writer http.ResponseWriter, request *http.Request) {
	writer.Write([]byte("Hello Mux!"))
}
```

We firstly setup a router(a pair of HTTP route with some logic) from the [NewRouter](https://pkg.go.dev/github.com/gorilla/mux#NewRouter) function provided by `mux`. We'll attach a function to this newly created router by pairing a URL with a function. So, in simple terms when the mentioned URL is visited or a GET request is sent(don't get into too much details) we want a function to be invoked or called which does something. Finally we will set up a web server that listens at a port with the created router.

The final piece is the function which we will call when the URL is visited i.e. the `Server` function it can be any name. The function needs to have two arguments as it is invoked by a router, the writer and the request. The Writer is a Response writer i.e. to write the message to the server. We will simply use the [Write](https://pkg.go.dev/net/http#Header.Write) function to simply print a array of bytes. 

The type of the writer is specifically `http.ResponseWriter` as we want to write a simple HTTP response header. Also the request is a [http.Request](https://pkg.go.dev/net/http#Request) type as we simply accept a HTTP request.

So, on running the following script, we will be able to see a simple HTTP response on the localhost at port `8000` or on your provided port.

```
go run main.go
```

![GO Gorilla MUX web server](https://res.cloudinary.com/techstructive-blog/image/upload/v1650645111/blog-media/gzje6ukyystp2x27u83o.png)

That's it from this part. Reference for all the code examples and commands can be found in the [100 days of Golang](https://github.com/mr-destructive/100-days-of-golang/) GitHub repository.

## Conclusion

So, we were able to dive a bit deeper in golang packages and modules. We covered from installation to importing packages in Golang, we also touched on basics of initializing a module in Golang. Hopefully, we were able to get the basics covered when it comes to packages in Golang.

Thank you for reading. If you have any questions or feedback, please let me know in the comments or on social handles. Happy Coding :)