说我像这样启动服务器:
onOpen
如何判断选择了哪个端口? srv := http.Server{
Addr: ":0",
Handler: http.FileServer(http.Dir(".")),
}
go srv.ListenAndServe()
log.Printf("Listening on ???")
旨在通过操作系统选择随机短暂端口,但我需要知道选择了哪一个。
注意:我希望不创建我自己的侦听器并使用:0
,因为srv.Listen(ln)
具有良好的默认值(但未导出)我想要使用的听众。
答案 0 :(得分:2)
我不想创建自己的侦听器并使用srv.Listen(ln),因为srv.ListenAndServe()有一个我想要使用的好的默认(但未导出)侦听器。
为什么不呢? ListenAndServe()非常容易实现。您可以自己read the source code:
func (srv *Server) ListenAndServe() error {
addr := srv.Addr
if addr == "" {
addr = ":http"
}
ln, err := net.Listen("tcp", addr)
if err != nil {
return err
}
return srv.Serve(tcpKeepAliveListener{ln.(*net.TCPListener)})
}
答案是你需要使用自己编写的ListenAndServe()来为你提供所需的信息。然而,它比你想象的容易得多。整个事情不超过20行(假设你想用tcpKeepAliveListener设置keep-alives。)
答案 1 :(得分:2)
从Go 1.14.1开始,net/http
不再包装TCP侦听器!
现在看documentation,是:
func (srv *Server) ListenAndServe() error {
if srv.shuttingDown() {
return ErrServerClosed
}
addr := srv.Addr
if addr == "" {
addr = ":http"
}
ln, err := net.Listen("tcp", addr)
if err != nil {
return err
}
return srv.Serve(ln)
}
这是由于source code所致,其中侦听器的“ keepalive”部分已移至标准net
程序包,并且默认情况下已打开。
所以,不用担心!只需创建自己的侦听器即可。
ln, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
return err
}
go srv.Serve(ln)
log.Printf("Listening on %s", ln.Addr().String())
答案 2 :(得分:0)
您可以在配置服务器地址之前选择空闲端口。获得自由端口的更简单方法是创建一个监听器,这样您就可以在Stephen建议之后获得相同的结果。
func GetFreePort() (int, error) {
ln, err := net.Listen("tcp", ":0")
if err != nil {
return 0, err
}
err = ln.Close()
if err != nil {
return 0, err
}
return ln.Addr().(*net.TCPAddr).Port, nil
}