func (j *Jar) RemoveAllHost(host string) {
	host, err := canonicalHost(host)
	if err != nil {
		return
	}
	key := jarKey(host, j.psList)
	j.mu.Lock()
	defer j.mu.Unlock()
	expired := time.Now().Add(-1 * time.Second)
	submap := j.entries[key]
	for id, e := range submap {
		if e.CanonicalHost == host {
			e.Value = ""
			e.Expires = expired
			submap[id] = e
		}
	}
}
RemoveAllHost removes any cookies from the jar that were set for the given host.
package cookiejar
import (
	"errors"
	"fmt"
	"net"
	"net/http"
	"net/url"
	"os"
	"path/filepath"
	"runtime"
	"sort"
	"strings"
	"sync"
	"time"
	"golang.org/x/net/publicsuffix"
	"gopkg.in/errgo.v1"
)
type PublicSuffixList interface {
	PublicSuffix(domain string) string
	String() string
}
type Options struct {
	PublicSuffixList PublicSuffixList
	Filename string
	NoPersist bool
}
type Jar struct {
	filename string
	psList PublicSuffixList
	mu sync.Mutex
	entries map[string]map[string]entry
}
var noOptions Options
func New(o *Options) (*Jar, error) {
	return newAtTime(o, time.Now())
}
func newAtTime(o *Options, now time.Time) (*Jar, error) {
	jar := &Jar{
		entries: make(map[string]map[string]entry),
	}
	if o == nil {
		o = &noOptions
	}
	if jar.psList = o.PublicSuffixList; jar.psList == nil {
		jar.psList = publicsuffix.List
	}
	if !o.NoPersist {
		if jar.filename = o.Filename; jar.filename == "" {
			jar.filename = DefaultCookieFile()
		}
		if err := jar.load(); err != nil {
			return nil, errgo.Notef(err, "cannot load cookies")
		}
	}
	jar.deleteExpired(now)
	return jar, nil
}
func homeDir() string {
	if runtime.GOOS == "windows" {
		return filepath.Join(os.Getenv("HOMEDRIVE"), os.Getenv("HOMEPATH"))
	}
	return os.Getenv("HOME")
}
type entry struct {
	Name       string
	Value      string
	Domain     string
	Path       string
	Secure     bool
	HttpOnly   bool
	Persistent bool
	HostOnly   bool
	Expires    time.Time
	Creation   time.Time
	LastAccess time.Time
	Updated time.Time
	CanonicalHost string
}
func (e *entry) id() string {
	return id(e.Domain, e.Path, e.Name)
}
func id(domain, path, name string) string {
	return fmt.Sprintf("%s;%s;%s", domain, path, name)
}
func (e *entry) shouldSend(https bool, host, path string) bool {
	return e.domainMatch(host) && e.pathMatch(path) && (https || !e.Secure)
}
func (e *entry) domainMatch(host string) bool {
	if e.Domain == host {
		return true
	}
	return !e.HostOnly && hasDotSuffix(host, e.Domain)
}
func (e *entry) pathMatch(requestPath string) bool {
	if requestPath == e.Path {
		return true
	}
	if strings.HasPrefix(requestPath, e.Path) {
		if e.Path[len(e.Path)-1] == '/' {
			return true  
		} else if requestPath[len(e.Path)] == '/' {
			return true  
		}
	}
	return false
}
func hasDotSuffix(s, suffix string) bool {
	return len(s) > len(suffix) && s[len(s)-len(suffix)-1] == '.' && s[len(s)-len(suffix):] == suffix
}
type byCanonicalHost struct {
	byPathLength
}
func (s byCanonicalHost) Less(i, j int) bool {
	e0, e1 := &s.byPathLength[i], &s.byPathLength[j]
	if e0.CanonicalHost != e1.CanonicalHost {
		return e0.CanonicalHost < e1.CanonicalHost
	}
	return s.byPathLength.Less(i, j)
}
type byPathLength []entry
func (s byPathLength) Len() int { return len(s) }
func (s byPathLength) Less(i, j int) bool {
	e0, e1 := &s[i], &s[j]
	if len(e0.Path) != len(e1.Path) {
		return len(e0.Path) > len(e1.Path)
	}
	if !e0.Creation.Equal(e1.Creation) {
		return e0.Creation.Before(e1.Creation)
	}
	if e0.Name != e1.Name {
		return e0.Name < e1.Name
	}
	return e0.Value < e1.Value
}
func (s byPathLength) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (j *Jar) Cookies(u *url.URL) (cookies []*http.Cookie) {
	return j.cookies(u, time.Now())
}
func (j *Jar) cookies(u *url.URL, now time.Time) (cookies []*http.Cookie) {
	if u.Scheme != "http" && u.Scheme != "https" {
		return cookies
	}
	host, err := canonicalHost(u.Host)
	if err != nil {
		return cookies
	}
	key := jarKey(host, j.psList)
	j.mu.Lock()
	defer j.mu.Unlock()
	submap := j.entries[key]
	if submap == nil {
		return cookies
	}
	https := u.Scheme == "https"
	path := u.Path
	if path == "" {
		path = "/"
	}
	var selected []entry
	for id, e := range submap {
		if !e.Expires.After(now) {
			if e.Value != "" {
				e.Value = ""
				submap[id] = e
			}
			continue
		}
		if !e.shouldSend(https, host, path) {
			continue
		}
		e.LastAccess = now
		submap[id] = e
		selected = append(selected, e)
	}
	sort.Sort(byPathLength(selected))
	for _, e := range selected {
		cookies = append(cookies, &http.Cookie{Name: e.Name, Value: e.Value})
	}
	return cookies
}
func (j *Jar) AllCookies() (cookies []*http.Cookie) {
	return j.allCookies(time.Now())
}
func (j *Jar) allCookies(now time.Time) []*http.Cookie {
	var selected []entry
	j.mu.Lock()
	defer j.mu.Unlock()
	for _, submap := range j.entries {
		for _, e := range submap {
			if !e.Expires.After(now) {
				continue
			}
			selected = append(selected, e)
		}
	}
	sort.Sort(byCanonicalHost{byPathLength(selected)})
	cookies := make([]*http.Cookie, len(selected))
	for i, e := range selected {
		cookies[i] = &http.Cookie{
			Name:     e.Name,
			Value:    e.Value,
			Path:     e.Path,
			Domain:   e.Domain,
			Expires:  e.Expires,
			Secure:   e.Secure,
			HttpOnly: e.HttpOnly,
		}
	}
	return cookies
}
func (j *Jar) RemoveCookie(c *http.Cookie) {
	j.mu.Lock()
	defer j.mu.Unlock()
	id := id(c.Domain, c.Path, c.Name)
	key := jarKey(c.Domain, j.psList)
	if e, ok := j.entries[key][id]; ok {
		e.Value = ""
		e.Expires = time.Now().Add(-1 * time.Second)
		j.entries[key][id] = e
	}
}
func (j *Jar) merge(entries []entry) {
	for _, e := range entries {
		if e.CanonicalHost == "" {
			continue
		}
		key := jarKey(e.CanonicalHost, j.psList)
		id := e.id()
		submap := j.entries[key]
		if submap == nil {
			j.entries[key] = map[string]entry{
				id: e,
			}
			continue
		}
		oldEntry, ok := submap[id]
		if !ok || e.Updated.After(oldEntry.Updated) {
			submap[id] = e
		}
	}
}
var expiryRemovalDuration = 24 * time.Hour
func (j *Jar) deleteExpired(now time.Time) {
	for tld, submap := range j.entries {
		for id, e := range submap {
			if !e.Expires.After(now) && !e.Updated.Add(expiryRemovalDuration).After(now) {
				delete(submap, id)
			}
		}
		if len(submap) == 0 {
			delete(j.entries, tld)
		}
	}
}