Non c'è niente di sbagliato nell'usare un modello Singleton anche qui.
Vorrei usare qualcosa di simile:
var db *sql.DB = nil
func GetDB() (*sql.DB, error) {
if db == nil {
conn := fmt.Sprintf("host=%s user=%s password=%s dbname=%s sslmode=require",
DB_HOST, DB_USER, DB_PASSWORD, DB_NAME)
log.Println("Creating a new connection: %v", conn)
d, err := sql.Open("postgres", conn)
if err != nil {
return nil, err
}
db = d
}
return db, nil
}
Con questa funzione esportata è possibile ricevere una connessione da tutti gli altri pacchetti.
Aggiornamento della risposta in base ai commenti (@all grazie per l'informazione) !:
Il DB restituito è sicuro per l'uso simultaneo da parte di più goroutines e mantiene il proprio pool di connessioni inattive . Pertanto, la funzione Open dovrebbe essere chiamata solo una volta. Raramente è necessario chiudere un DB. ¹
È raro chiudere un DB, poiché l'handle DB è pensato per essere di lunga durata e condiviso tra molte goroutine. ²
direi che non c'è ragione costringe a chiamare da vicino la connessione al database. Non ho trovato altre dichiarazioni. Nonostante ciò userei unnella funzione main
- solo per la completezza del codice.
Un'altra cosa che vorrei sottolineare è che la connessione deve essere verificata da un db.Ping()
altrimenti la connessione potrebbe essere stabilita ma il database potrebbe non esistere.
Con questa nuova informazione non mi preoccuperei di utilizzare alcuni mutex per garantire che il database sia stato stabilito. Vorrei creare un nuovo DBInit()
ed eseguirlo all'interno della funzione init()
del pacchetto principale.
Supporto Ricevo pool di connessioni in alcune funzioni chiamando sql.Open - come dovrei archiviarlo nella mia applicazione. –
Qual è l'approccio comune qui? Non sto chiedendo in che modo persiste i dati, ma un modo in cui memorizzi il riferimento al pool di connessioni nell'applicazione. –
Perché il pool di connessione di creazione per ogni selezione non è la soluzione corretta –