func (election *Election) Start() bool {
	success := false
	election.startOnce.Do(func() {
		election.Lock()
		election.state = started
		election.Unlock()
		go election.updateVote()
		time.AfterFunc(election.Duration, func() {
			election.Stop()
		})
		success = true
	})
	return success
}
Start starts an election and will stop the election after duration. Returns
if start success. Multiple concurrent call will only return success once.
package election
import (
	"errors"
	"fmt"
	"sync"
	"time"
)
type electionState uint8
const (
	initialized electionState = 0
	started     electionState = 1
	stopped     electionState = 2
)
type Config struct {
	Duration                    time.Duration
	MinVotingInterval           time.Duration
	MaxVotingInterval           time.Duration
	ChangeVoteMinRelativeWeight float32
	ChangeVoteMinAbsoluteWeight uint32
	ConsensusMinRelativeWeight  float32
	ConsensusMinAbsoluteWeight  uint32
	GetWeight                   func(interface{}) uint32
}
type Election struct {
	*Config
	startOnce     sync.Once
	neighborVotes sync.Map
	voteReceived  chan struct{}
	txVoteChan    chan interface{}
	sync.RWMutex
	selfVote interface{}
	state    electionState
}
func NewElection(config *Config) (*Election, error) {
	if config.Duration == 0 {
		return nil, errors.New("Election duration cannot be empty")
	}
	if config.MinVotingInterval > config.MaxVotingInterval {
		return nil, fmt.Errorf("Min voting interval %v is greater than max voting interval %v", config.MinVotingInterval, config.MaxVotingInterval)
	}
	if config.GetWeight == nil {
		config.GetWeight = func(interface{}) uint32 { return 1 }
	}
	election := &Election{
		Config:       config,
		state:        initialized,
		voteReceived: make(chan struct{}, 1),
		txVoteChan:   make(chan interface{}),
	}
	return election, nil
}
func (election *Election) SetInitialVote(vote interface{}) error {
	if election.HasStarted() {
		return errors.New("Cannot set initial vote, election has started")
	}
	election.Lock()
	election.selfVote = vote
	election.Unlock()
	return nil
}