func (db *PGStore) load(session *sessions.Session) error {
	var s PGSession
	err := db.selectOne(&s, session.ID)
	if err != nil {
		return err
	}
	return securecookie.DecodeMulti(session.Name(), string(s.Data), &session.Values, db.Codecs...)
}
load fetches a session by ID from the database and decodes its content
into session.Values.
package pgstore
import (
	"database/sql"
	"encoding/base32"
	"net/http"
	"strings"
	"time"
	"github.com/pkg/errors"
	"github.com/gorilla/securecookie"
	"github.com/gorilla/sessions"
	_ "github.com/lib/pq"
)
type PGStore struct {
	Codecs  []securecookie.Codec
	Options *sessions.Options
	Path    string
	DbPool  *sql.DB
}
type PGSession struct {
	ID         int64
	Key        string
	Data       string
	CreatedOn  time.Time
	ModifiedOn time.Time
	ExpiresOn  time.Time
}
func NewPGStore(dbURL string, keyPairs ...[]byte) (*PGStore, error) {
	db, err := sql.Open("postgres", dbURL)
	if err != nil {
		return nil, err
	}
	return NewPGStoreFromPool(db, keyPairs...)
}
func NewPGStoreFromPool(db *sql.DB, keyPairs ...[]byte) (*PGStore, error) {
	dbStore := &PGStore{
		Codecs: securecookie.CodecsFromPairs(keyPairs...),
		Options: &sessions.Options{
			Path:   "/",
			MaxAge: 86400 * 30,
		},
		DbPool: db,
	}
	err := dbStore.createSessionsTable()
	if err != nil {
		return nil, err
	}
	return dbStore, nil
}
func (db *PGStore) Close() {
	db.DbPool.Close()
}
func (db *PGStore) Get(r *http.Request, name string) (*sessions.Session, error) {
	return sessions.GetRegistry(r).Get(db, name)
}
func (db *PGStore) New(r *http.Request, name string) (*sessions.Session, error) {
	session := sessions.NewSession(db, name)
	if session == nil {
		return nil, nil
	}
	opts := *db.Options
	session.Options = &(opts)
	session.IsNew = true
	var err error
	if c, errCookie := r.Cookie(name); errCookie == nil {
		err = securecookie.DecodeMulti(name, c.Value, &session.ID, db.Codecs...)
		if err == nil {
			err = db.load(session)
			if err == nil {
				session.IsNew = false
			} else if errors.Cause(err) == sql.ErrNoRows {
				err = nil
			}
		}
	}
	db.MaxAge(db.Options.MaxAge)
	return session, err
}
func (db *PGStore) Save(r *http.Request, w http.ResponseWriter, session *sessions.Session) error {
	if session.Options.MaxAge < 0 {
		if err := db.destroy(session); err != nil {
			return err
		}
		http.SetCookie(w, sessions.NewCookie(session.Name(), "", session.Options))
		return nil
	}
	if session.ID == "" {
		session.ID = strings.TrimRight(
			base32.StdEncoding.EncodeToString(
				securecookie.GenerateRandomKey(32),
			), "=")
	}
	if err := db.save(session); err != nil {
		return err
	}
	encoded, err := securecookie.EncodeMulti(session.Name(), session.ID, db.Codecs...)
	if err != nil {
		return err
	}
	http.SetCookie(w, sessions.NewCookie(session.Name(), encoded, session.Options))
	return nil
}
func (db *PGStore) MaxLength(l int) {
	for _, c := range db.Codecs {
		if codec, ok := c.(*securecookie.SecureCookie); ok {
			codec.MaxLength(l)
		}
	}
}
func (db *PGStore) MaxAge(age int) {
	db.Options.MaxAge = age
	for _, codec := range db.Codecs {
		if sc, ok := codec.(*securecookie.SecureCookie); ok {
			sc.MaxAge(age)
		}
	}
}