func (d *Dispatcher) loadParams() {
	d.Args = service.Args
	if d.Args.UrlFile != "" {
		return
	} else if d.Args.Url != "" {
		d.Urls = append(d.Urls, d.Args.Url)
	} else {
		log.Fatalf("You must specify at once one url! ", d.Args.Url)
	}
	d.Timeout = d.Args.Timeout
	d.Headers = d.readHeaders()
}
load all params
package requests
import (
	"bufio"
	"fmt"
	"github.com/andboson/ab-go/service"
	"log"
	"math"
	"net/http"
	"os"
	"time"
)
var HttpClient *http.Client
var DispatcherService *Dispatcher
type Dispatcher struct {
	Args        *service.Flags
	Jobs        map[string]*Job
	Urls        []string
	PostData    []string
	ScannerPost *bufio.Reader
	ScannerUrls *bufio.Scanner
	FilePtrPost *os.File
	FilePtrUrls *os.File
	Headers     []string
	Completed   []string
	Failed      []string
	Timeout     int
	Start       time.Time
	Result      *Result
	PostLines   chan string
}
type Result struct {
	Duration   string
	Requests   int
	Failed     int
	Rps        string
	Min        string
	Max        string
	Avg        string
	LastResult string
}
func CreateDispatcher() *Dispatcher {
	makeClient()
	DispatcherService = &Dispatcher{}
	DispatcherService.Result = &Result{}
	DispatcherService.Jobs = make(map[string]*Job)
	DispatcherService.Start = time.Now()
	DispatcherService.loadParams()
	return DispatcherService
}
func makeClient() {
	useKeepAlive := service.Args.Ka
	transport := &http.Transport{
		DisableCompression: false,
		DisableKeepAlives:  !useKeepAlive,
	}
	HttpClient = &http.Client{Transport: transport}
}
func (d *Dispatcher) Run() {
	defer d.FilePtrUrls.Close()
	defer d.FilePtrPost.Close()
	for i := 0; i < d.Args.Requests; i++ {
		var jobs = make(map[string]*Job)
		for j := 0; j < d.Args.Concurrency; j++ {
			if i == d.Args.Requests {
				break
			}
			job := d.createJob()
			jobs[job.Id] = job
			i++
		}
		i--
		d.runBatch(jobs)
	}
	duration := time.Since(d.Start).Seconds()
	d.Result.Duration = fmt.Sprintf("%.3fms", duration*1000)
	d.Result.Requests = len(d.Jobs)
	d.Result.Rps = fmt.Sprintf("%.0frps", math.Ceil(float64(d.Result.Requests)/duration))
	if len(d.Jobs) < 1 {
		return
	}
	var firstJob *Job
	for _, val := range d.Jobs {
		firstJob = val
		break
	}
	min := firstJob.Duration
	max := firstJob.Duration
	var total float64
	for _, result := range d.Jobs {
		if result.Duration > max {
			max = result.Duration
		}
		if result.Duration < min {
			min = result.Duration
		}
		total = total + result.Duration
	}
	avg := total / float64(len(d.Jobs))
	d.Result.Avg = fmt.Sprintf("%.3fms", avg)
	d.Result.Max = fmt.Sprintf("%.3fms", max)
	d.Result.Min = fmt.Sprintf("%.3fms", min)
	if len(d.Completed) > 0 {
		completedLastIndex := d.Completed[len(d.Completed)-1]
		lastJob := d.Jobs[completedLastIndex]
		d.Result.LastResult = lastJob.Response.RawResponse
	}
	return
}
func (d *Dispatcher) runBatch(jobs map[string]*Job) {
	d.Completed = make([]string, 0)
	batchJobsCount := len(jobs)
	responseReciever := make(chan *Job, batchJobsCount)
	for _, job := range jobs {
		go job.Run(responseReciever)
	}
	func() {
		for {
			select {
			case response := <-responseReciever:
				d.Jobs[response.Id] = response
				if response.Response.Code != 200 {
					d.Result.Failed++
				}
				d.Completed = append(d.Completed, response.Id)
				if len(d.Completed) == batchJobsCount {
					return
				}
			}
		}
	}()
}