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.
The post Golang: How to Use Library Packages appeared first on The New Stack.