func (c *Credentials) GetWithContext(ctx Context) (Value, error) {
	if curCreds := c.creds.Load(); !c.isExpired(curCreds) {
		return curCreds.(Value), nil
	}
	resCh := c.sf.DoChan("", func() (interface{}, error) {
		return c.singleRetrieve(&suppressedContext{ctx})
	})
	select {
	case res := <-resCh:
		return res.Val.(Value), res.Err
	case <-ctx.Done():
		return Value{}, awserr.New("RequestCanceled",
			"request context canceled", ctx.Err())
	}
}
GetWithContext returns the credentials value, or error if the credentials
Value failed to be retrieved. Will return early if the passed in context is
canceled.

Will return the cached credentials Value if it has not expired. If the
credentials Value has expired the Provider's Retrieve() will be called
to refresh the credentials.

If Credentials.Expire() was called the credentials Value will be force
expired, and the next call to Get() will cause them to be refreshed.

Passed in Context is equivalent to aws.Context, and context.Context.
package credentials
import (
	"fmt"
	"sync/atomic"
	"time"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/internal/sync/singleflight"
)
var AnonymousCredentials = NewStaticCredentials("", "", "")
type Value struct {
	AccessKeyID string
	SecretAccessKey string
	SessionToken string
	ProviderName string
}
func (v Value) HasKeys() bool {
	return len(v.AccessKeyID) != 0 && len(v.SecretAccessKey) != 0
}
type Provider interface {
	Retrieve() (Value, error)
	IsExpired() bool
}
type ProviderWithContext interface {
	Provider
	RetrieveWithContext(Context) (Value, error)
}
type Expirer interface {
	ExpiresAt() time.Time
}
type ErrorProvider struct {
	Err error
	ProviderName string
}
func (p ErrorProvider) Retrieve() (Value, error) {
	return Value{ProviderName: p.ProviderName}, p.Err
}
func (p ErrorProvider) IsExpired() bool {
	return false
}
type Expiry struct {
	expiration time.Time
	CurrentTime func() time.Time
}
func (e *Expiry) SetExpiration(expiration time.Time, window time.Duration) {
	e.expiration = expiration
	if window > 0 {
		e.expiration = e.expiration.Add(-window)
	}
}
func (e *Expiry) IsExpired() bool {
	curTime := e.CurrentTime
	if curTime == nil {
		curTime = time.Now
	}
	return e.expiration.Before(curTime())
}
func (e *Expiry) ExpiresAt() time.Time {
	return e.expiration
}
type Credentials struct {
	creds atomic.Value
	sf    singleflight.Group
	provider Provider
}
func NewCredentials(provider Provider) *Credentials {
	c := &Credentials{
		provider: provider,
	}
	c.creds.Store(Value{})
	return c
}