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: portscan.go
    path of file: ./repos/ServerScan/ServerScan Air/package/portscan
    
    the code of the file until where you have to start completion: package portscan

import (
	"fmt"
	"net"
	"sort"
	"strconv"
	"strings"
	"sync"
	"time"
)

func parsePort(ports string) []int {
	var scanPorts []int
	slices := strings.Split(ports, ",")
	for _, port := range slices {
		port = strings.Trim(port, " ")
		upper := port
		if strings.Contains(port, "-") {
			ranges := strings.Split(port, "-")
			if len(ranges) < 2 {
				continue
			}
			sort.Strings(ranges)
			port = ranges[0]
			upper = ranges[1]
		}
		start, _ := strconv.Atoi(port)
		end, _ := strconv.Atoi(upper)
		for i := start; i <= end; i++ {
			scanPorts = append(scanPorts, i)
		}
	}
	return scanPorts
}

func ProbeHosts(host string, ports <-chan int, respondingHosts chan<- string, done chan<- bool, model string) {
	adjustedTimeout := 500 * time.Millisecond
	for port := range ports{
		start := time.Now()
		con, err := net.DialTimeout("tcp4", fmt.Sprintf("%s:%d", host, port), 500 * time.Millisecond)
		duration := time.Now().Sub(start)
		if err == nil {
			con.Close()
			address := host + ":" + strconv.Itoa(port)
			if model == "tcp" {
				fmt.Printf("(TCP) Target %s is open\n",address)
			}else {
				fmt.Println(address)
			}
			respondingHosts <- address
		}
		if duration < adjustedTimeout {
			difference := adjustedTimeout - duration
			adjustedTimeout = adjustedTimeout - (difference / 2)
		}
	}
	done <- true
}

func ScanAllports(address string, probePorts []int, threads int, timeout time.Duration, model string) ([]string, error) {
	ports := make(chan int, 20)
	results := make(chan string, 1
    
func TCPportScan(hostslist []string,ports string,model string)  ([]string,[]string){
	var AliveAddress []string
	var aliveHosts []string
	probePorts := parsePort(ports)
	lm := 20
	if (len(hostslist)>5 && len(hostslist)<=50) {
		lm = 40
	}else if(len(hostslist)>50 && len(hostslist)<=100){
		lm = 50
	}else if(len(hostslist)>100 && len(hostslist)<=150){
		lm = 60
	}else if(len(hostslist)>150 && len(hostslist)<=200){
		lm = 70
	}else if(len(hostslist)>200){
		lm = 75
	}

	thread := 5
	if (len(probePorts)>500 && len(probePorts)<=4000) {
		thread = len(probePorts)/100
	}else if (len(probePorts)>4000 && len(probePorts)<=6000) {
		thread = len(probePorts)/200
	}else if (len(probePorts)>6000 && len(probePorts)<=10000) {
		thread = len(probePorts)/350
	}else if (len(probePorts)>10000 && len(probePorts)<50000){
		thread = len(probePorts)/400
	}else if (len(probePorts)>=50000 && len(probePorts)<=65535){
		thread = len(probePorts)/500
	}

	var wg sync.WaitGroup
	mutex := &sync.Mutex{}
	limiter := make(chan struct{}, lm)
	aliveHost := make(chan string, lm/2)
	go func() {
		for s := range aliveHost {
			fmt.Println(s)
		}
	}()
	for _,host :=range hostslist{
		wg.Add(1)
		limiter <- struct{}{}
		go func(host string) {
			defer wg.Done()
			if aliveAdd, err := ScanAllports(host, probePorts,thread, 5*time.Second,model);err == nil && len(aliveAdd)>0{
				mutex.Lock()
				aliveHosts = append(aliveHosts,host)
				for _,addr :=range aliveAdd{
					AliveAddress = append(AliveAddress,addr)
				}
				mutex.Unlock()
			}
			<-limiter
		}(host)
	}
	wg.Wait()
	close(aliveHost)
	return aliveHosts,AliveAddress
}