func retire(t *time.Ticker) {
	for range t.C {
		now := time.Now()
		var old []string
		mut.RLock()
		for k, v := range conn {
			if now.Sub(v.used) >= period {
				old = append(old, k)
			}
		}
		mut.RUnlock()
		mut.Lock()
		for _, c := range old {
			conn[c].s.Close()
			delete(conn, c)
		}
		mut.Unlock()
	}
}
retire retires old connections
package storage
import (
	"fmt"
	"sync"
	"time"
	"gopkg.in/mgo.v2"
)
var (
	conn   = make(map[string]*session)  
	mut    sync.RWMutex                 
	ticker *time.Ticker                 
)
type session struct {
	s    *mgo.Session
	used time.Time
}
const period time.Duration = 7 * 24 * time.Hour
type Storage struct {
	session *mgo.Session
	dbname  string
}
type Collection struct {
	*mgo.Collection
}
func (c *Collection) Close() {
	c.Collection.Database.Session.Close()
}
func open(addr, dbname string) (*Storage, error) {
	sess, err := mgo.Dial(addr)
	if err != nil {
		return nil, fmt.Errorf("mongodb: %s", err)
	}
	copy := sess.Clone()
	storage := &Storage{session: copy, dbname: dbname}
	mut.Lock()
	conn[addr] = &session{s: sess, used: time.Now()}
	mut.Unlock()
	return storage, nil
}
func Open(addr, dbname string) (storage *Storage, err error) {
	defer func() {
		if r := recover(); r != nil {
			storage, err = open(addr, dbname)
		}
	}()
	mut.RLock()
	if session, ok := conn[addr]; ok {
		mut.RUnlock()
		if err = session.s.Ping(); err == nil {
			mut.Lock()
			session.used = time.Now()
			conn[addr] = session
			mut.Unlock()
			copy := session.s.Clone()
			return &Storage{copy, dbname}, nil
		}
		return open(addr, dbname)
	}
	mut.RUnlock()
	return open(addr, dbname)
}
func (s *Storage) Close() {
	s.session.Close()
}
func (s *Storage) Collection(name string) *Collection {
	return &Collection{s.session.DB(s.dbname).C(name)}
}
func init() {
	ticker = time.NewTicker(time.Hour)
	go retire(ticker)
}