func NewSetBalancer(libAddrs []*net.TCPAddr, clients Pool, rng *rand.Rand) (SetBalancer, error) {
	if len(libAddrs) == 0 {
		return nil, ErrEmptyLibrarianAddresses
	}
	available := make([]string, len(libAddrs))
	for i, libAddr := range libAddrs {
		available[i] = libAddr.String()
	}
	return &setRandBalancer{
		rng:       rng,
		clients:   clients,
		available: available,
		set:       make(map[string]struct{}),
	}, nil
}
NewSetBalancer creates a new SetBalancer that selects the next client from the remaining clients
in the available set.
package client
import (
	"errors"
	"math/rand"
	"net"
	"sync"
	"github.com/drausin/libri/libri/librarian/api"
)
var (
	ErrEmptyLibrarianAddresses = errors.New("empty librarian addresses")
	ErrClientMissingFromSet = errors.New("client missing from set")
	ErrNoNewClients = errors.New("no new LibrarianClients are available")
)
type Balancer interface {
	Next() (api.LibrarianClient, error)
	CloseAll() error
}
type GetterBalancer interface {
	Next() (api.Getter, error)
}
type PutterBalancer interface {
	Next() (api.Putter, error)
}
type SetBalancer interface {
	AddNext() (api.LibrarianClient, string, error)
	Remove(address string) error
}
type uniformRandBalancer struct {
	rng     *rand.Rand
	mu      sync.Mutex
	addrs   []*net.TCPAddr
	clients Pool
}
func NewUniformBalancer(libAddrs []*net.TCPAddr, clients Pool, rng *rand.Rand) (Balancer, error) {
	if len(libAddrs) == 0 {
		return nil, ErrEmptyLibrarianAddresses
	}
	return &uniformRandBalancer{
		rng:     rng,
		clients: clients,
		addrs:   libAddrs,
	}, nil
}
func (b *uniformRandBalancer) Next() (api.LibrarianClient, error) {
	b.mu.Lock()
	defer b.mu.Unlock()
	i := b.rng.Int31n(int32(len(b.addrs)))
	return b.clients.Get(b.addrs[i].String())
}
func (b *uniformRandBalancer) CloseAll() error {
	return b.clients.CloseAll()
}
type uniformGetterBalancer struct {
	inner Balancer
}
func NewUniformGetterBalancer(inner Balancer) GetterBalancer {
	return &uniformGetterBalancer{inner}
}
func (b *uniformGetterBalancer) Next() (api.Getter, error) {
	next, err := b.inner.Next()
	if err != nil {
		return nil, err
	}
	return next.(api.Getter), nil
}
type uniformPutterBalancer struct {
	inner Balancer
}
func NewUniformPutterBalancer(inner Balancer) PutterBalancer {
	return &uniformPutterBalancer{inner}
}
func (b *uniformPutterBalancer) Next() (api.Putter, error) {
	next, err := b.inner.Next()
	if err != nil {
		return nil, err
	}
	return next.(api.Putter), nil
}
type setRandBalancer struct {
	rng       *rand.Rand
	mu        sync.Mutex
	available []string
	set       map[string]struct{}
	clients   Pool
}