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 }