TNS
VOXPOP
As a JavaScript developer, what non-React tools do you use most often?
Angular
0%
Astro
0%
Svelte
0%
Vue.js
0%
Other
0%
I only use React
0%
I don't use JavaScript
0%
NEW! Try Stackie AI
Go

Golang: How to Use Library Packages

The Go programming language has a sophisticated set of support libraries for developers. Here's how to use them.
Apr 23rd, 2024 5:00pm by
Featued image for: Golang: How to Use Library Packages
Feature image via Pixabay.

Most programming languages come with built-in libraries. With these libraries, you can use pre-built code that serves a specific purpose. By doing so, you not only have to write less code but you can be certain the code you import from those libraries always does exactly what you expect it to.

Without libraries, your code would not only be considerably longer, it would be far more complicated.

For example, you have the Go standard library, which adds a number of important packages for essential functionality. You’ll find fmt (for formatted I/O), errors (implements function for error manipulation), crypto (for collecting common cryptographic constants), and more. You can view the entire Standard Library here.

But if you were limited to the Standard Library, you wouldn’t be able to get much done. You’d be limited to either using what was available or having to write your own code for the functionality you need.

That’s why you need to know how to import library packages with Go.

A Golang Circular Problem with Importing Packages

Before we get into this, I want to address something I’ve run into on a few occasions. That something is the deprecated go get command, which you’ll find in tutorials, instructions, and even textbooks everywhere. The go get command was deprecated when modules were introduced. When that happened, the go get command was being used to both update dependencies in a go.mod file as well as install commands, which was confusing.

But, if you view certain packages on GitHub (such as the MySQL driver), you’ll still find the instructions list as go get as the procedure, such as go get -u github.com/go-sql-driver/mysql, which doesn’t work. And if you attempt to use the replacement go install, you get an error such as:

Try ‘go install github.com/go-sql-driver/mysql@latest‘ to install the latest version

Let’s try that suggestion. Run:

go install github.com/go-sql-driver/mysql@latest

Guess what? That errors out as well, with:

package github.com/go-sql-driver/mysql is not a main package

It’s a circular problem.

This started because I wanted to write a tutorial on connecting Go with a MariaDB database. What should have been simple turned into a recursive nightmare, simply because I couldn’t get the MySQL driver to install for Go. So, I created the database and then attempted to import the driver with no luck.

Then I attempted to load the driver from within the code, which looked something like this:

package main

import (
    "database/sql"
    "fmt"
    "log"
    "os"

    "github.com/go-sql-driver/mysql"
)

After completing the entire code block (which connects to my database, I then run the command:

go mod init github.com/go-sql-driver/mysql

That’s followed by:

go mod tidy

Now I have a go.mod file which includes:

module github.com/go-sql-driver/mysql

go 1.22.1

Everything should work just fine. It doesn’t. Just so you can get an idea of what the full code looks like (which was inspired by the official Golang documentation here), take a gander:

package main

import (
    "database/sql"
    "fmt"
    "log"
    "os"
)

var db *sql.DB

func main() {
    // Capture connection properties.
    cfg := mysql.Config{
        User:   os.Getenv("ubooks"),
        Passwd: os.Getenv("PASSWORD"),
        Net:    "tcp",
        Addr:   "192.168.1.166:3306",
        DBName: "books",
    }

    // Get a database handle.
    var err error
    db, err = sql.Open("mysql", cfg.FormatDSN())
    if err != nil {
        log.Fatal(err)
    }

    pingErr := db.Ping()
    if pingErr != nil {
        log.Fatal(pingErr)
    }
    fmt.Println("Connected!")
}

Now, when I run the app, I get the following error:

./main.go:17:12: undefined: mysql

Remember, this is from the official documentation. After doing considerable research, I discovered the tutorial in the documentation fails without AllowNativePasswords: true.

Guess what? It fails even with the above statement. The problem is obvious, we have to define mysql before we can call it with mysql. I then found another method, which failed on me.

Clearly, this is a complex issue.

Needless to say, I had to give up on this one for the time being. I will come back to it, once I’ve figured out the problem.

So, for the time being, we’ll avoid importing third-party packages (we’ll deal with that later, once I’ve figured out the MySQL issue – because using databases in applications is actually pretty important.

A Golang Library for Random Numbers

Let’s say you want a piece of Go code that prints out 10 random numbers between 1 and 1000. For that, you have to import the match package, which includes the rand function.

If you’ve been following along, you already know you have to add the package main at the top of your code to act as an entry point and that the package should be compiled as an executable program and not a shared library.

After that, we can then import our package and specify the function we want to use:

import "math/rand"

We’ll now create a function that will print out 10 random numbers between 0-1000, using a basic for loop. That looks like this:

func main() {
for i := 0; i < 10; i++ {
println(rand.Intn(1000))
}
}

The entire code block looks like this:

package main

import "math/rand"

func main() {
for i := 0; i < 10; i++ {
println(rand.Intn(1000))
}
}

When you run the above, the output might look something like this:

452
853
822
346
461
729
672
513
158
481

The problem with that is it’s not very random. To make the randomness even more reliable, we need to seed it with something. There’s a package for that, called time, which includes everything we need to seed a random number with time, specifically, the current time.

For this, we need to change our function, to define now like so:

now := time.Now()

There’s also a function, called UnixNano() that yields t as a Unix time which is the number of seconds passed from January 1, 1970. We implement that like so:

rand.Seed(now.UnixNano())

Our entire function now looks like this:

func main() {
now := time.Now()
rand.Seed(now.UnixNano())
println("Random numbers seeded with Unix Time: ", now.UnixNano())
for i := 0; i < 5; i++ {

Our entire app looks like this:

package main

import (
       "math/rand"
       "time"
)

func main() {
        now := time.Now()
        rand.Seed(now.UnixNano())
println("Random numbers seeded with Unix Time: ", now.UnixNano())
        for i := 0; i < 5; i++ {
                 println(rand.Intn(10))

            }
}

When we run the above, we get something like this for output:

Random numbers seeded with Unix Time:  1713204758111329492
3
5
4
5
1
9
1
7
3
1

Now those are truly random numbers.

And that, my Golang newbies, is how we use library packages in Go.

Group Created with Sketch.
TNS DAILY NEWSLETTER Receive a free roundup of the most recent TNS articles in your inbox each day.