Efficient SQL Queries in Go with the database/sql Package

Ambiyansyah Risyal
3 min readJan 12, 2023

--

Photo by Fern M. Lomibao on Unsplash

In this example, we will be using the Go programming language to perform a simple SQL query on a database. We will go through each step in detail to help you understand how to write efficient and performant SQL queries in Go.

Before we get started, it’s important to note that Go has a number of different packages that can be used for interacting with databases. In this example, we will be using the database/sql package, which provides a lightweight interface for interacting with databases.

To begin, we will need to import the database/sql package and any other necessary packages:

import (
"database/sql"
_ "github.com/go-sql-driver/mysql" // MySQL driver
)

Next, we will need to establish a connection to our database. To do this, we will use the sql.Open function:

db, err := sql.Open("mysql", "user:password@/database")
if err != nil {
panic(err.Error())
}
defer db.Close()

In this example, we are using the MySQL driver and providing the necessary connection details in the form of a connection string. The sql.Open function returns a *sql.DB type, which represents a connection pool to the database. It's important to note that this function does not actually establish a connection to the database - it simply prepares the connection pool.

Once we have a connection pool, we can use the *sql.DB type's Ping method to verify that we can actually connect to the database:

err = db.Ping()
if err != nil {
panic(err.Error())
}

With the connection established, we can now execute a SQL query using the *sql.DB type's Query method. This method takes a SQL query string as its first argument, and any necessary parameters as subsequent arguments:

rows, err := db.Query("SELECT name FROM users WHERE age > ?", 20)
if err != nil {
panic(err.Error())
}
defer rows.Close()

The Query method returns a *sql.Rows type, which represents the result set of the query. We can use this type to iterate over the rows of the result set and process the data.

To iterate over the rows, we can use a for loop:

for rows.Next() {
var name string
err = rows.Scan(&name)
if err != nil {
panic(err.Error())
}
fmt.Println(name)
}

In this loop, we are using the *sql.Rows type's Next method to advance to the next row in the result set. We are then using the Scan method to scan the values from the current row into variables. In this case, we are scanning the name column into a string variable.

It’s important to note that the Scan method takes pointers as arguments, so we need to pass the address of the name variable using the & operator.

Finally, we should check for any errors that may have occurred during the iteration process:

err = rows.Err()
if err != nil {
panic(err.Error())
}

Once we have finished iterating over the rows, we should close the *sql.Rows type using the Close method. This is important because it allows the connection pool to reuse the connection, improving performance.

defer rows.Close()

It’s also a good idea to handle any errors that may have occurred during the query process. This can be done using a simple if statement:

if err != nil {
panic(err.Error())
}

Overall, the process for executing a SQL query in Go is relatively simple. By using the database/sql package and following the steps outlined above, you can easily query a database and process the results in your Go programs.

Here is the complete example code:

package main

import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"
)

func main() {
// Establish connection to database
db, err := sql.Open("mysql", "user:password@/database")
if err != nil {
panic(err.Error())
}
defer db.Close()
// Verify connection to database
err = db.Ping()
if err != nil {
panic(err.Error())
}
// Execute SQL query
rows, err := db.Query("SELECT name FROM users WHERE age > ?", 20)
if err != nil {
panic(err.Error())
}
defer rows.Close()
// Iterate over result set
for rows.Next() {
var name string
err = rows.Scan(&name)
if err != nil {
panic(err.Error())
}
fmt.Println(name)
}
// Check for errors during iteration
err = rows.Err()
if err != nil {
panic(err.Error())
}
}

I hope this example and explanation helps you understand how to write efficient and performant SQL queries in Go. Let me know if you have any questions or need further clarification

To begin, we will need to import the database/sql package and any other necessary packages:

--

--

Ambiyansyah Risyal
Ambiyansyah Risyal

Written by Ambiyansyah Risyal

Software engineer. Lover of learning and creating. Sharing thoughts and experiences on tech and software development. Always seeking new ideas and techniques.

Responses (1)