I'm adding db access to my go program, it looks like this:
package db_access
import (
"database/sql"
"fmt"
"my_database"
)
type TheType struct {
Name string
}
func LoadTheTypeFromDb(db *sql.DB, id uint) (*TheType, error) {
query := fmt.Sprintf(
"SELECT %s FROM %s WHERE %s = ?",
my_database.NAME,
my_database.TABLE,
my_database.ID,
)
var theType TheType
err := db.QueryRow(query, id).Scan(&theType.Name)
switch {
case err == sql.ErrNoRows:
n := my_database.NewNotFoundError(err)
return nil, &n
case err != nil:
return nil, err
default:
return &theType, nil
}
}
And some part of the my_database
package:
package my_database
import (
"database/sql"
_ "github.com/go-sql-driver/mysql"
)
func GetDatabaseInstance(connectionString string) (*sql.DB, error) {
db, err := sql.Open("mysql", connectionString)
if err != nil {
c := newConnectionError(err)
return nil, &c
}
err = db.Ping()
if err != nil {
c := newConnectionError(err)
return nil, &c
}
return db, nil
}
And the custom errors:
package my_database
import (
"fmt"
"reflect"
)
type ConnectionError struct {
errorMessage string
}
func newConnectionError(err error) ConnectionError {
return ConnectionError{fmt.Sprintf("Connection error %s %s", reflect.TypeOf(err), err)}
}
func (e *ConnectionError) Error() string {
return e.errorMessage
}
type QueryError struct {
errorMessage string
}
func newQueryError(err error) QueryError {
return QueryError{fmt.Sprintf("Query error %s %s", reflect.TypeOf(err), err)}
}
func (e *QueryError) Error() string {
return e.errorMessage
}
type NotFoundError struct {
errorMessage string
}
func NewNotFoundError(err error) NotFoundError {
return NotFoundError{fmt.Sprintf("Not found - %s", err)}
}
func (e *NotFoundError) Error() string {
return e.errorMessage
}
- I add a custom
NotFound
error, because when the row is not found, I don't want to leaksql.ErrNoRows
outside, is that ok? I don't like that the constructor forNotFound
error is public, unlike all other custom errors, furthermore, I think I would need to add that switch statement to everyLoad*
method … also not so good. - The custom error code is very repetitive, is there a way to clean that up?
- Any other comments are much appreciated.