github.com/bingoohuang/gg@v0.0.0-20240325092523-45da7dee9335/pkg/netx/freeport/freeport.go (about)

     1  package freeport
     2  
     3  import (
     4  	"fmt"
     5  	"net"
     6  )
     7  
     8  // IsFree tells whether the port is free or not
     9  func IsFree(port int) bool {
    10  	l, err := Listen(port)
    11  	if err != nil {
    12  		return false
    13  	}
    14  
    15  	_ = l.Close()
    16  	return true
    17  }
    18  
    19  // PortE asks the kernel for a free open port that is ready to use.
    20  func PortE() (int, error) {
    21  	l, e := Listen(0)
    22  	if e != nil {
    23  		return 0, e
    24  	}
    25  
    26  	_ = l.Close()
    27  	return l.Addr().(*net.TCPAddr).Port, nil
    28  }
    29  
    30  // Port Ask the kernel for a free open port that is ready to use.
    31  // this will panic if any error is encountered.
    32  func Port() int {
    33  	port, err := PortE()
    34  	if err != nil {
    35  		panic(err)
    36  	}
    37  
    38  	return port
    39  }
    40  
    41  // Ports asks the kernel for free open ports that are ready to use.
    42  func Ports(count int) ([]int, error) {
    43  	ports := make([]int, count)
    44  
    45  	for i := 0; i < count; i++ {
    46  		p, err := PortE()
    47  		if err != nil {
    48  			return nil, err
    49  		}
    50  		ports[i] = p
    51  	}
    52  
    53  	return ports, nil
    54  }
    55  
    56  // Listen listens on port.
    57  func Listen(port int) (net.Listener, error) {
    58  	return net.Listen("tcp", fmt.Sprintf(":%d", port))
    59  }
    60  
    61  // PortStart finds a free port from starting port
    62  func PortStart(starting int) int {
    63  	p := starting
    64  	for ; !IsFree(p); p++ {
    65  	}
    66  	return p
    67  }