In questo articolo vedremo come costruire un semplice ORM (Object-Relational Mapping) in Go per interfacciarsi con un database PostgreSQL. L’obiettivo è comprendere i concetti fondamentali di un ORM: mappatura delle strutture Go alle tabelle SQL, generazione dinamica delle query e gestione dei risultati.
Requisiti
- Go 1.18 o superiore
- Database PostgreSQL
- Libreria database/sqle driverlib/pq
Connessione al database
import (
  "database/sql"
  _ "github.com/lib/pq"
  "log"
)
var db *sql.DB
func Connect() {
  var err error
  db, err = sql.Open("postgres", "user=postgres dbname=testdb sslmode=disable")
  if err != nil {
    log.Fatal(err)
  }
}
Struttura base del modello
Definiamo una struttura base da cui erediteranno gli altri modelli:
type Model interface {
  TableName() string
}
type User struct {
  ID    int
  Name  string
  Email string
}
func (u User) TableName() string {
  return "users"
}
Funzione per salvare un record
Una funzione generica per inserire un record nel database:
import (
  "fmt"
  "reflect"
  "strings"
)
func Insert(model Model) error {
  v := reflect.ValueOf(model)
  t := reflect.TypeOf(model)
  var columns []string
  var placeholders []string
  var values []interface{}
  for i := 0; i < t.NumField(); i++ {
    field := t.Field(i)
    columns = append(columns, strings.ToLower(field.Name))
    placeholders = append(placeholders, fmt.Sprintf("$%d", i+1))
    values = append(values, v.Field(i).Interface())
  }
  query := fmt.Sprintf("INSERT INTO %s (%s) VALUES (%s)",
    model.TableName(),
    strings.Join(columns, ", "),
    strings.Join(placeholders, ", "),
  )
  _, err := db.Exec(query, values...)
  return err
}
Esempio d'uso
func main() {
  Connect()
  user := User{
    Name:  "Mario Rossi",
    Email: "mario@example.com",
  }
  err := Insert(user)
  if err != nil {
    log.Fatal(err)
  }
}
Creazione della tabella PostgreSQL
Nel database PostgreSQL, assicurati di avere la tabella appropriata:
CREATE TABLE users (
  id SERIAL PRIMARY KEY,
  name TEXT,
  email TEXT
);
Conclusione
Abbiamo visto come realizzare una versione semplificata di un ORM in Go. Questo approccio può essere esteso per includere funzionalità come aggiornamenti, cancellazioni, query con filtri, validazioni e gestione delle relazioni tra entità. Tuttavia, per progetti reali, è consigliato utilizzare ORM maturi come GORM o SQLBoiler.