Working with Databases in Go
# CHAPTER 24
Working with Databases in Go
1. Introduction
A backend system is essentially a bridge between a user interface and a database. Go provides a standard, unified interface for interacting with relational databases via thedatabase/sql package. Whether you are using MySQL, PostgreSQL, or SQLite, the Go code looks exactly the same; you just change the "Driver".
2. Learning Objectives
By the end of this chapter, you will be able to:- Download and import a database Driver.
- Connect to a MySQL database safely.
- Execute basic CRUD operations (Insert, Update, Delete).
- Query data and map rows into Go Structs.
- Prevent SQL Injection.
3. Installing the Driver
Thedatabase/sql package provides the commands, but it relies on external, community-built Drivers to translate those commands to specific databases.
To connect to MySQL, run this in your terminal:
4. Connecting to the Database
To connect, we need a Data Source Name (DSN) string containing the username, password, host, and database name.5. Executing Queries (Insert / Update / Delete)
For operations that modify data (and don't return rows), we usedb.Exec().
CRITICAL RULE: Prevent SQL Injection!
Never concatenate user input directly into an SQL string ("INSERT INTO users VALUES (" + name + ")"). Hackers will destroy your database.
Instead, use ? placeholders. Go will safely sanitize the data.
6. Reading Data (db.Query)
To fetch data (SELECT), we use db.Query(). It returns "Rows" which we iterate over, scanning the columns into a Go Struct.
7. Reading a Single Row (db.QueryRow)
If you are searching for an exact user by ID, use db.QueryRow().
8. Common Mistakes
-
Forgetting
defer rows.Close(): When you query multiple rows, the database connection is held hostage until you finish iterating. If an error occurs inside your loop and the function returns early without closing the rows, your database will run out of connection limits and crash.
-
Forgetting the Underscore Import: If you forget
"github.com/go-sql-driver/mysql", the program will panic withsql: unknown driver "mysql".
9. Best Practices
-
Connection Pooling:
sql.Open()creates a Connection Pool, not a single connection. You should only callsql.OpenONCE when your server starts, and pass that*sql.DBpointer to all your API handlers. Do not open and close the database on every single web request!
10. Exercises
- 1. Set up a local MySQL instance (or use SQLite).
-
2.
Connect to it using
sql.Open.
-
3.
Create a table using
db.Exec("CREATE TABLE IF NOT EXISTS test (id INT AUTOINCREMENT PRIMARY KEY, msg VARCHAR(50))").
11. MCQs with Answers & Explanations
Which standard library package handles database interactions in Go?
Why do we import the MySQL driver with a blank identifier (underscore _)?
sql.Open() actively test the connection to the database server?
a) Yes b) No, it just sets up the configuration. You must call db.Ping() to actually test the connection.
Answer: b) No, you must call db.Ping().
Which method is used for SQL commands that DO NOT return rows (like INSERT or UPDATE)?
How do you prevent SQL Injection in Go?
Which method is used for SQL commands that return multiple rows (like SELECT)?
What critical keyword must be used after db.Query() to prevent severe database connection leaks?
Which method scans a specific row's column data into Go variables?
sql.Open inside every single HTTP Handler function?
a) Yes b) No, you should call it once at startup and share the *sql.DB connection pool across the application.
Answer: b) No, share the connection pool.
How do you specifically check if a user wasn't found using db.QueryRow?
12. Interview Preparation
Interview Questions:-
1.
Explain how Connection Pooling works natively in Go's
database/sqlpackage.
-
2.
What is the difference between
db.Queryanddb.Exec?
- 3. How does Go mitigate SQL injection attacks?
13. Summary
Go's approach to databases is highly abstract and safe. By utilizing a shared*sql.DB connection pool, Go web servers can handle thousands of simultaneous database queries with low overhead. Remember to always use parameterized queries (?) for security, and rigorously close your rows to preserve memory!
14. Next Chapter Recommendation
We have built REST JSON APIs, but Go can also render full HTML pages directly. In Chapter 25: Web Development with Go, we will explore Go's built-inhtml/template package to build server-side rendered websites.