SQLC DBTX interface

I’ve started using SQLC and I encountered a small problem.
Auto-generated code looks like this:

type DBTX interface {
	ExecContext(context.Context, string, ...interface{}) (sql.Result, error)
	PrepareContext(context.Context, string) (*sql.Stmt, error)
	QueryContext(context.Context, string, ...interface{}) (*sql.Rows, error)
	QueryRowContext(context.Context, string, ...interface{}) *sql.Row
}

func New(db DBTX) *Queries {
	return &Queries{db: db}
}

type Queries struct {
	db DBTX
}

We use function New(db DBTX) to get access to receiver methods, but we must pass to the function an object that implements interface DBTX. I noticed that we can just pass there database connection *sql.DB and it works even though *sql.DB doesn’t implement that interface. How does it work?

Ok, I think I understand. db package has these methods implemented, thus when I create my own interface with the same methods (same signature) it means db package also implements my interface. Is it right?

1 Like

Yes that is correct.
If your struct has functions attached with the same signature (function name, arguments and return values) it will be automatically also a DBTX.
This is how inheritenace is working in go.

A nice example that is maybe often used is io.Writer (io package - io - Go Packages).
So if your class (struct) implements the function Write(p []byte) (n int, err error) it will be automatically an io.Writer and can be passed to every call that expects an io.Writer.

Matthias

1 Like

While the rest of your reply is spot on, I do want to be pedantic and address this statement.

Go in-fact does not support inheritance; instead it supports composition via type embedding. In fact, composition and type embedding are orthogonal to interfaces.

What this is instead is an example of implicit interfaces.” #fwiw

1 Like