gitee.com/liuxuezhan/go-micro-v1.18.0@v1.0.0/util/net/net.go (about)

     1  package net
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"net"
     7  	"strconv"
     8  	"strings"
     9  )
    10  
    11  // HostPort format addr and port suitable for dial
    12  func HostPort(addr string, port interface{}) string {
    13  	host := addr
    14  	if strings.Count(addr, ":") > 0 {
    15  		host = fmt.Sprintf("[%s]", addr)
    16  	}
    17  	// when port is blank or 0, host is a queue name
    18  	if v, ok := port.(string); ok && v == "" {
    19  		return host
    20  	} else if v, ok := port.(int); ok && v == 0 && net.ParseIP(host) == nil {
    21  		return host
    22  	}
    23  
    24  	return fmt.Sprintf("%s:%v", host, port)
    25  }
    26  
    27  // Listen takes addr:portmin-portmax and binds to the first available port
    28  // Example: Listen("localhost:5000-6000", fn)
    29  func Listen(addr string, fn func(string) (net.Listener, error)) (net.Listener, error) {
    30  
    31  	if strings.Count(addr, ":") == 1 && strings.Count(addr, "-") == 0 {
    32  		return fn(addr)
    33  	}
    34  
    35  	// host:port || host:min-max
    36  	host, ports, err := net.SplitHostPort(addr)
    37  	if err != nil {
    38  		return nil, err
    39  	}
    40  
    41  	// try to extract port range
    42  	prange := strings.Split(ports, "-")
    43  
    44  	// single port
    45  	if len(prange) < 2 {
    46  		return fn(addr)
    47  	}
    48  
    49  	// we have a port range
    50  
    51  	// extract min port
    52  	min, err := strconv.Atoi(prange[0])
    53  	if err != nil {
    54  		return nil, errors.New("unable to extract port range")
    55  	}
    56  
    57  	// extract max port
    58  	max, err := strconv.Atoi(prange[1])
    59  	if err != nil {
    60  		return nil, errors.New("unable to extract port range")
    61  	}
    62  
    63  	// range the ports
    64  	for port := min; port <= max; port++ {
    65  		// try bind to host:port
    66  		ln, err := fn(HostPort(host, port))
    67  		if err == nil {
    68  			return ln, nil
    69  		}
    70  
    71  		// hit max port
    72  		if port == max {
    73  			return nil, err
    74  		}
    75  	}
    76  
    77  	// why are we here?
    78  	return nil, fmt.Errorf("unable to bind to %s", addr)
    79  }