You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: speedtest.go
    path of file: ./repos/mylg/speedtest
    
    the code of the file until where you have to start completion: // Package speedtest interfaces for testing internet bandwidth through HTTP by speedtest.net
package speedtest

import (
	"encoding/xml"
	"fmt"
	"io"
	"io/ioutil"
	"math"
	"net/http"
	"sort"
	"strings"
	"sync"
	"time"
)

type byDistance []Server
type ST struct {
	cfg     Settings
	servers []Server
}
type Client struct {
	IP  string  `xml:"ip,attr"`
	Lat float64 `xml:"lat,attr"`
	Lon float64 `xml:"lon,attr"`
	ISP string  `xml:"isp,attr"`
}
type Server struct {
	Name     string  `xml:"name,attr"`
	Id       string  `xml:"id,attr"`
	Sponsor  string  `xml:"sponsor,attr"`
	Country  string  `xml:"country,attr"`
	URL      string  `xml:"url,attr"`
	URL2     string  `xml:"url2,attr"`
	Lat      float64 `xml:"lat,attr"`
	Lon      float64 `xml:"lon,attr"`
	Distance float64
}

type Hosts struct {
	Server []Server `xml:"servers>server"`
}

type Settings struct {
	Download struct {
		TestLength    float64 `xml:"testlength,attr"`
		ThreadsPerURL int     `xml:"threadsperurl,attr"`
	} `xml:"download"`
	Upload struct {
		Ratio         int     `xml:"ratio,attr"`
		MaxChunkCount int     `xml:"maxchunkcount,attr"`
		Threads       int     `xml:"threads,attr"`
		TestLength    float64 `xml:"testlength,attr"`
	} `xml:"upload"`
	ServerCfg struct {
		IgnoreIds string `xml:"ignoreids,attr"`
	} `xml:"server-config"`
	Client struct {
		Client
	} `xml:"client"`
}

func Run() error {
	st := ST{}
	fmt.Printf("Powered by Ookla â€” http://www.speedtest.net/terms\n")
	fmt.Printf("Downloading the speedtest.net configuration")
	if err := st.getConfig(); err != nil {
		return err
	}
	fmt.Printf(" \u2713\nYour IP: %s, Service Provider: %s\n", st.cfg.Client.IP, st.cfg.Client.ISP)
	fmt.Printf("Retrieving speedtest.net servers list")
	if err := st.getServers(); err != nil {
		return err
	}
	fmt.Printf(" \u2713\nSelecting best server based on Geo and Latency")
	server, latency := st.bestServer()
	if server.Distance == 0 {
		return fmt.Errorf("could not find a server")
	}
	fmt.Printf(
    
func (st *ST) upload(server Server) string {
	var (
		sizes       []int
		totalUpload int
		sizeUpl     = []int{32768, 65536, 131072, 262144, 524288, 1048576, 7340032}
		count       = st.cfg.Upload.MaxChunkCount * 2 / len(sizeUpl[st.cfg.Upload.Ratio-1:])
		jobCh       = make(chan int, len(sizeUpl)*count)
		resCh       = make(chan int, len(sizeUpl)*count)
		done        = make(chan struct{})
		base        = server.URL[:strings.LastIndex(server.URL, "/")]
	)

	for _, size := range sizeUpl[st.cfg.Upload.Ratio-1:] {
		for i := 0; i < count; i++ {
			sizes = append(sizes, size)
		}
	}
	// TODO: needs optimization
	fmt.Printf("Testing upload ")
	for t := 0; t < st.cfg.Upload.MaxChunkCount; t++ {
		go func() {
			defer func() {
				recover()
			}()
			tr := &http.Transport{
				DisableKeepAlives:  false,
				DisableCompression: true,
			}
			client := &http.Client{
				Transport: tr,
			}
			req, err := http.NewRequest("POST", base+"/upload.php", nil)
			if err != nil {
				return
			}
			req.Header.Set("User-Agent", "Mozilla/5.0")
			testLength := 1024 * 16
			chunkData := strings.Repeat("0123456789ABCDEFGHIJKLMNOPQRSTUV", testLength/32)
		DONE:
			for {
				size := <-jobCh
				chunkNums := size / testLength
				ts := time.Now()
				c := 0
			LOOP:
				for time.Since(ts).Seconds() < st.cfg.Upload.TestLength {
					buf := strings.NewReader(chunkData)
					req.Body = ioutil.NopCloser(buf)
					resp, err := client.Do(req)
					if err != nil || resp.StatusCode != 200 {
						println(err.Error())
						continue
					}

					io.Copy(ioutil.Discard, resp.Body)
					resp.Body.Close()

					resCh <- testLength
					chunkNums--
					if chunkNums > 0 {
						c++
					} else {
						break LOOP
					}
					select {
					case <-done:
						break DONE
					default:
						continue
					}
				}
				fmt.Printf(".")
			}
		}()
	}

	ts := time.Now()
	for _, size := range sizes {
		jobCh <- size
	}

	go func() {
		for {
			chunk, ok := <-resCh
			if !ok {
				break
			}
			totalUpload += chunk
		}
	}()

	<-time.After(time.Duration(st.cfg.Upload.TestLength) * time.Second)
	close(done)
	close(resCh)

	fmt.Printf("\n")
	return fmtUnit(float64(totalUpload) / time.Since(ts).Seconds())
}