How to use next available port in http.ListenAndServe

huangapple go评论70阅读模式
英文:

How to use next available port in http.ListenAndServe

问题

我写了一个简单的Web服务器来监听8080端口。但是我不想使用硬编码的端口号。我希望我的服务器监听任何可用的端口。并且我想知道我的Web服务器监听的端口号是多少。

以下是我的代码:

package main

import (
	"net/http"
)

func main() {		
	http.HandleFunc("/", handler)
	http.ListenAndServe(":8080", nil)
}

请注意,这段代码中的端口号是硬编码的,即":8080"。如果你想让服务器监听任何可用的端口,你可以将端口号设置为空字符串,即":0"。这样,操作系统会自动分配一个可用的端口给你的服务器,并且你可以通过http.ListenAndServe函数的返回值来获取实际监听的端口号。例如:

package main

import (
	"fmt"
	"net/http"
)

func main() {		
	http.HandleFunc("/", handler)
	server := http.ListenAndServe(":0", nil)
	fmt.Printf("Server is listening on port %s\n", server.Addr)
}

这样,你就可以通过server.Addr获取实际监听的端口号了。

英文:

I wrote a simple web server to listen on port 8080. But I don't want to use a hard coded port number. What I want is that my server listen on any available port. And I want to know that on what port number my web server is listening.

My code is given bellow:

package main

import (
	"net/http"
)

func main() {		
	http.HandleFunc("/", handler)
	http.ListenAndServe(":8080", nil)

}

答案1

得分: 118

你可以使用端口0来表示你不指定一个具体的端口,而是希望系统选择一个空闲可用的端口:

http.ListenAndServe(":0", nil)

这种方法的问题是你无法得知分配的端口是什么。因此,你需要自己创建net.Listener(使用net.Listen()函数),并将其手动传递给http.Serve()

listener, err := net.Listen("tcp", ":0")
if err != nil {
    panic(err)
}

fmt.Println("Using port:", listener.Addr().(*net.TCPAddr).Port)

panic(http.Serve(listener, nil))

示例输出:

Using port: 42039

如你所见,你可以从net.Listener中获取分配的端口,通过其net.Addr地址(通过Addr()方法获取)。net.Addr并不直接提供访问端口的方法,但由于我们使用tcp网络流创建了net.Listener,所以net.Addr的动态类型将是*net.TCPAddr(我们可以通过类型断言获取),它是一个结构体,有一个字段Port int

请注意,如果你的应用程序不需要使用端口(例如,只是为了自己显示),你不需要进行类型断言,只需打印listener.Addr()(其中包含端口):

fmt.Println("Address:", listener.Addr())

示例输出:

Address: [::]:42039

还要记得处理返回的错误(在这种情况下是http.ListenAndServe())。在我的示例中,我只是将其传递给panic(),因为http.ListenAndServe()http.Serve()在一切顺利时会阻塞(只有在出现错误时才会返回,我将其传递给panic())。

英文:

You may use port 0 to indicate you're not specifying an exact port but you want a free, available port selected by the system:

http.ListenAndServe(":0", nil)

The problem with this is that you won't be able to find out what port was assigned. So you need to create the net.Listener yourself (using the net.Listen() function), and manually pass it to http.Serve():

listener, err := net.Listen("tcp", ":0")
if err != nil {
	panic(err)
}

fmt.Println("Using port:", listener.Addr().(*net.TCPAddr).Port)

panic(http.Serve(listener, nil))

Example output:

Using port: 42039

As you can see, you can access the assigned port from the net.Listener, from its net.Addr address (acquired by its Addr() method). net.Addr does not directly give access to the port, but since we created the net.Listener using tcp network stream, the net.Addr will be of dynamic type *net.TCPAddr (which we can acquire with a type assertion), which is a struct and has a field Port int.

Note that if you don't need the port in your application (e.g. you just want to display it for yourself), you don't need the type assertion, you can just print listener.Addr() (which will contain the port at the end):

fmt.Println("Address:", listener.Addr())

Example output:

Address: [::]:42039

Also don't forget to handle returned errors (http.ListenAndServe() in this case). In my example I simply passed it to panic() because http.LitenAndServe() and http.Serve() block if everything goes well (so they only return if there's an error, which I pass to panic()).

答案2

得分: 7

我登陆到这个页面是因为我想要在一个随机端口上启动一个新的服务器进行测试。后来我了解到了httptest包,它在管理用于测试的临时HTTP服务器方面做得更好。你可以在这里找到相关信息:https://golang.org/pkg/net/http/httptest/。

英文:

I landed on this page because I wanted to start a new server on a random port for testing purposes. I later learned about the httptest package, https://golang.org/pkg/net/http/httptest/ , which does a much better job of managing temporary HTTP server for testing.

答案3

得分: 2

https://pkg.go.dev/net/http/httptest 支持在随机端口上运行 HTTP 服务器。

package main

import (
    "fmt"
    "net/http"
    "net/http/httptest"
)

func main() {       
    handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        w.WriteHeader(http.StatusNoContent)
    })

    server := httptest.NewServer(handler)
    defer server.Close()

    fmt.Println("服务器已启动", server.URL)
}

示例输出

服务器已启动 http://127.0.0.1:54926
英文:

Package https://pkg.go.dev/net/http/httptest supports HTTP server on random port.

package main

import (
    "fmt"
    "net/http"
    "net/http/httptest"
)

func main() {       
    handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        w.WriteHeader(http.StatusNoContent)
    })

    server := httptest.NewServer(handler)
    defer server.Close()

    fmt.Println("Server started", server.URL)
}

Example output

Server started http://127.0.0.1:54926

huangapple
  • 本文由 发表于 2017年4月15日 18:12:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/43424787.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定