英文:
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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论