Guide · Open source
How to use sqlx: queries, structs and named parameters in Go
Updated · written with AI from the project's own documentation and checked against our catalogue data
sqlx is an open-source Go library that adds convenience features on top of the standard database/sql package. This guide is for Go developers who already use database/sql and want less boilerplate when reading rows. By the end you will know how to install sqlx, map query results to structs, use named parameters and run batch inserts.
Quick start
- 1Install sqlx. Run go get github.com/jmoiron/sqlx in your Go module, and import a database driver such as github.com/lib/pq for Postgres.
- 2Open a connection. Call sqlx.Connect with your driver name and connection string. It pings the database so you find connection errors early.
- 3Define a struct. Create a Go struct for your table, using db tags when a field name does not match its column name.
- 4Load results. Use db.Get for a single row and db.Select for a slice of rows.
- 5Use named parameters. Write queries with :name placeholders and pass a map or struct as the argument to NamedExec or NamedQuery.
- 6Batch insert. Pass a slice of structs or maps to NamedExec to insert multiple rows in one call.
Install sqlx and a database driver
Install the library with go get. sqlx is a Go package, so you need a working Go environment first. The README says the project supports the two most recent Go versions and does not state an exact minimum version.
sqlx does not include a database driver. You also need a driver package for your database. The README example uses github.com/lib/pq for Postgres, imported with a blank identifier so it registers itself.
go get github.com/jmoiron/sqlxConnect to the database
Use sqlx.Connect to open a connection. It takes the driver name and a connection string, and it pings the database to check that the connection works. If you want the semantics of sql.Open without the ping, the README says to use sqlx.Open instead.
The sqlx database types keep the same interfaces as the standard library types, so you can adopt sqlx gradually in an existing codebase.
db, err := sqlx.Connect("postgres", "user=foo dbname=bar sslmode=disable")Map rows into structs with Get and Select
Get loads a single row into a struct, similar to QueryRow. Select loads many rows into a slice of structs. Struct fields map to column names, and you can use the db tag when a field name does not match its column.
If a column can be NULL and you select with SELECT *, the README says the struct field must use a sql.Null* type such as sql.NullString.
- Get: one result into a single struct
- Select: many results into a slice
- Use the db struct tag when a field name differs from the column name
- Use sql.NullString (or another sql.Null* type) for nullable columns
people := []Person{}
db.Select(&people, "SELECT * FROM person ORDER BY first_name ASC")
jason := Person{}
err = db.Get(&jason, "SELECT * FROM person WHERE first_name=$1", "Jason")Use named parameters
Named queries let you write :name placeholders instead of positional arguments. The names can be taken from a map or from a struct, and sqlx uses the driver name you passed to Open or Connect to choose the right bind variable style.
The README notes that struct bind names follow the same rules as the name-to-column mapping, so struct fields are lowercased and the db tag is respected.
_, err = db.NamedExec(`INSERT INTO person (first_name,last_name,email) VALUES (:first,:last,:email)`, map[string]interface{}{"first": "Bin", "last": "Smuth", "email": "bensmith@allblacks.nz"})
rows, err = db.NamedQuery(`SELECT * FROM person WHERE first_name=:first_name`, jason)Run batch inserts from slices
You can pass a slice of structs or a slice of maps to NamedExec to insert several rows in one call. The README lists batch insertion from []map[string]interface{} as a feature added in version 1.3.0.
Iterate over rows with Queryx and StructScan when you want to reuse a single struct for each row, instead of loading everything into a slice first.
- Batch insert with a []Person slice of structs
- Batch insert with a []map[string]interface{} slice
- Loop with Queryx and rows.StructScan to reuse one struct
_, err = db.NamedExec(`INSERT INTO person (first_name, last_name, email)
VALUES (:first_name, :last_name, :email)`, personStructs)Avoid ambiguous column names
The README warns that row headers can be ambiguous, for example when two columns have the same name. In that case struct or map mapping can be unclear. Give each column a distinct name with AS, scan rows manually with rows.Scan, or use SliceScan to get a slice of results.
- Alias columns with AS so every name is distinct
- Use rows.Scan to scan values manually
- Use SliceScan to get a slice of results
What people use it for
- Reading rows from a table straight into a slice of Go structs with Select
- Loading one record by key with Get, similar to QueryRow in database/sql
- Inserting many records from a slice of structs or maps using NamedExec
- Writing queries with readable named parameters such as :first_name instead of $1, $2
Frequently asked questions
How do I install sqlx?
Run go get github.com/jmoiron/sqlx. You also need a database driver package for your database, such as github.com/lib/pq for Postgres, as shown in the README example.
Is sqlx free to use?
sqlx is released under the MIT licence, according to the README and the project's licence badge. That licence allows use in commercial projects, but check the LICENSE file in the repository for the full terms.
What do I need to run sqlx?
You need Go and a database driver for your database. The README says the project supports the two most recent Go versions and does not state an exact minimum version.
Is sqlx an ORM?
No. The README describes sqlx as a set of extensions to database/sql for query and mapping work. It does not describe models, migrations or relationship handling, so if you need those, look at a full ORM.
What are the alternatives to sqlx?
Comparable projects named in the analysis include the standard database/sql package, GORM, sqlc and ent. database/sql is the base that sqlx extends, so it works without any extra dependency.
Why are my struct fields not filling in correctly?
The README warns that row headers can be ambiguous, such as when two columns share a name in a join. Use AS to give each column a distinct name, or scan the values manually with rows.Scan or SliceScan.
New agent skills, repos and AI tools — every week
The best new skills and open-source projects, the fastest-growing repos, and one free prompt. Five minutes to read. Unsubscribe anytime.
Our verdict
sqlx suits Go developers who already use database/sql and want less boilerplate for reading rows, named parameters and batch inserts. If you want a full ORM with models, migrations and relationships, or your project is not in Go, pick a different tool such as GORM or ent.
Install options & downloads