func (j *Jar) setCookies(u *url.URL, cookies []*http.Cookie, now time.Time) {
	if len(cookies) == 0 {
		return
	}
	if u.Scheme != "http" && u.Scheme != "https" {
		return
	}
	host, err := canonicalHost(u.Host)
	if err != nil {
		return
	}
	key := jarKey(host, j.psList)
	defPath := defaultPath(u.Path)
	j.mu.Lock()
	defer j.mu.Unlock()
	submap := j.entries[key]
	notify := false
	modified := false
	for _, cookie := range cookies {
		e, remove, err := j.newEntry(cookie, now, defPath, host)
		if err != nil {
			continue
		}
		id := e.ID()
		if remove {
			if submap != nil {
				if _, ok := submap[id]; ok {
					delete(submap, id)
					modified = true
					if (j.notifyOn & DeleteCookie) != 0 {
						notify = true
					}
				}
			}
			continue
		}
		if submap == nil {
			submap = make(map[string]Entry)
		}
		if old, ok := submap[id]; ok {
			e.Creation = old.Creation
			e.seqNum = old.seqNum
		} else {
			e.Creation = now
			e.seqNum = j.nextSeqNum
			j.nextSeqNum++
		}
		e.LastAccess = now
		submap[id] = e
		modified = true
		if (j.notifyOn & SetCookie) != 0 {
			notify = true
		}
	}
	if modified {
		if len(submap) == 0 {
			delete(j.entries, key)
		} else {
			j.entries[key] = submap
		}
	}
	if j.notify != nil && notify {
		j.notify <- key
	}
}
setCookies is like SetCookies but takes the current time as parameter.
package cookiejar
import (
	"errors"
	"fmt"
	"net"
	"net/http"
	"net/http/cookiejar"
	"net/url"
	"sort"
	"strings"
	"sync"
	"time"
)
type Notification uint32
const (
	ReadAccess   Notification = 1 << iota  
	Expiration                             
	DeleteCookie                           
	SetCookie                              
)
type Options struct {
	PublicSuffixList cookiejar.PublicSuffixList
	Notify chan<- string
	NotifyOn Notification
}
type Jar struct {
	psList   cookiejar.PublicSuffixList
	notify   chan<- string
	notifyOn Notification
	mu sync.Mutex
	entries map[string]map[string]Entry
	nextSeqNum uint64
}
func New(o *Options) (*Jar, error) {
	jar := &Jar{
		entries: make(map[string]map[string]Entry),
	}
	if o != nil {
		jar.psList = o.PublicSuffixList
		jar.notify = o.Notify
		jar.notifyOn = o.NotifyOn
	}
	return jar, nil
}
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
	seqNum uint64
}
func (e *Entry) ID() string {
	return fmt.Sprintf("%s;%s;%s", e.Domain, e.Path, e.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 byPathLength []Entry
func (s byPathLength) Len() int { return len(s) }
func (s byPathLength) Less(i, j int) bool {
	if len(s[i].Path) != len(s[j].Path) {
		return len(s[i].Path) > len(s[j].Path)
	}
	if !s[i].Creation.Equal(s[j].Creation) {
		return s[i].Creation.Before(s[j].Creation)
	}
	return s[i].seqNum < s[j].seqNum
}
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 j == nil {
		return cookies
	}
	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 = "/"
	}
	notify := false
	modified := false
	var selected []Entry
	for id, e := range submap {
		if e.Persistent && !e.Expires.After(now) {
			delete(submap, id)
			modified = true
			if (j.notifyOn & Expiration) != 0 {
				notify = true
			}
			continue
		}
		if !e.shouldSend(https, host, path) {
			continue
		}
		e.LastAccess = now
		submap[id] = e
		selected = append(selected, e)
		modified = true
		if (j.notifyOn & ReadAccess) != 0 {
			notify = true
		}
	}
	if modified {
		if len(submap) == 0 {
			delete(j.entries, key)
		} else {
			j.entries[key] = submap
		}
	}
	sort.Sort(byPathLength(selected))
	for _, e := range selected {
		cookies = append(cookies, &http.Cookie{Name: e.Name, Value: e.Value})
	}
	if j.notify != nil && notify {
		j.notify <- key
	}
	return cookies
}
func (j *Jar) SetCookies(u *url.URL, cookies []*http.Cookie) {
	j.setCookies(u, cookies, time.Now())
}