go / freeport

I use ephemeral port binding to find an available port for tests and development servers.

The pattern

func FreePort() (int, error) {
	listener, err := net.Listen("tcp", ":0")
	if err != nil {
		return 0, err
	}
	defer listener.Close()
	return listener.Addr().(*net.TCPAddr).Port, nil
}

Binding to port 0 asks the OS for any available ephemeral port. The listener is immediately closed, freeing the port for use.

Usage

Start a test server on a free port:

func TestServer(t *testing.T) {
    port, err := FreePort()
    if err != nil {
        t.Fatal(err)
    }

    addr := fmt.Sprintf("localhost:%d", port)
    server := &http.Server{Addr: addr, Handler: handler}

    go server.ListenAndServe()
    defer server.Close()

    // Test against http://localhost:{port}
    resp, _ := http.Get("http://" + addr + "/health")
    // ...
}

When to use

When not to use

← All articles