In aggiunta alle risposte che hai già ricevuto, considera l'utilizzo del ricevitore al numero method values e http.HandlerFunc.
Se i dati sono dati che vengono caricati prima dell'avvio del processo, si potrebbe andare con qualcosa di simile:
type Common struct {
Data map[string]*Data
}
func NewCommon() (*Common, error) {
// load data
return c, err
}
func (c *Common) Root(w http.ResponseWriter, r *http.Request) {
// handler
}
func (c *Common) Page(w http.ResponseWriter, r *http.Request) {
// handler
}
func main() {
common, err := NewCommon()
if err != nil { ... }
http.HandleFunc("/", common.Root)
http.HandleFunc("/page", common.Page)
http.ListenAndServe(...)
}
Questo funziona bene se tutti i dati Common
è di sola lettura. Se i dati Common
è di lettura/scrittura, quindi ti consigliamo di avere qualcosa di più simile:
type Common struct {
lock sync.RWMutex
data map[string]Data // Data should probably not have any reference fields
}
func (c *Common) Get(key string) (*Data, bool) {
c.lock.RLock()
defer c.lock.RUnlock()
d, ok := c.data[key]
return &d, ok
}
func (c *Common) Set(key string, d *Data) {
c.lock.Lock()
defer c.lock.Unlock()
c.data[key] = *d
}
Il resto è fondamentalmente la stessa, tranne che invece di accesso ai dati attraverso i campi del ricevitore direttamente, faresti accesso loro attraverso i getter ei setter. In un server web in cui viene letta la maggior parte dei dati, è probabile che si desideri un RWMutex, in modo che le letture possano essere eseguite simultaneamente l'una con l'altra. Un altro vantaggio del secondo approccio è che hai incapsulato i dati, quindi puoi aggiungere scritture trasparenti a e/o letture da un memcache o una groupcache o qualcosa del genere in futuro se la tua applicazione dovesse crescere.
Una cosa che mi piace molto su come definire i miei gestori come i metodi su un oggetto è che rende molto più facile per unità di testarli: si può facilmente definire un table driven test che include i valori desiderati e l'output che ci si aspetta, senza dover per andare in giro con le variabili globali.
peterSO, quale tipo di implementazione utilizzi personalmente? –
Sia l'ottimizzazione prematura che la generalizzazione prematura sono cattive. :) –
Potrei sbagliarmi, ma poiché i dati devono essere mantenuti per tutte le richieste, che sono concomitanti, qualsiasi accesso a una variabile globale che lo trattiene dovrebbe essere protetto da un mutex. – kostix