目前,我正在“优雅地”处理HTTP net/http关机,它运行得非常好(我不是要求您检查服务器关机)。如下面的代码所示,在运行应用程序时,context是第一次直接在服务器包中创建的。之后我所做的就是(这是我希望您回顾的),在调用服务器并将其传递给服务器之前,我已经创建了一个context.Background()。这一做法在戈朗是否可以接受/可行?
为什么我想要预先创建一个context,而一切都已经很好了?
context中的几个键值对,这样我就可以在整个应用程序中使用它们。中使用上下文的实现
package main
import (
"github.com/BentCoder/auth/internal/http"
)
func main() {
srv := http.NewServer(":8011", 10)
srv.Start()
}package http
import (
"context"
"log"
"net/http"
"os"
"os/signal"
"syscall"
"time"
)
type Server struct {
http *http.Server
timeout int64
}
func NewServer(adr string, tim int64) Server {
return Server{
http: &http.Server{
Addr: adr,
},
timeout: tim,
}
}
func (srv *Server) Start() {
log.Infof("starting HTTP server")
idle := make(chan struct{})
go shutdown(srv.http, idle, srv.timeout)
if err := srv.http.ListenAndServe(); err != http.ErrServerClosed {
log.Fatalf("failed to start/close HTTP server [%v]", err)
}
<-idle
log.Info("shutdown HTTP server")
}
func shutdown(srv *http.Server, idle chan<- struct{}, tim int64) {
sig := make(chan os.Signal, 1)
signal.Notify(sig, os.Interrupt, syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP)
<-sig
log.Infof("shutting down HTTP server in '%d' sec", tim)
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(tim)*time.Second)
defer cancel()
if err := srv.Shutdown(ctx); err != nil {
log.Fatalf("failed to shutdown HTTP server [%v]", err)
}
close(idle)
}INFO[0000] starting HTTP server source="server.go:42"
^C
INFO[0004] shutting down HTTP server in '10' sec source="server.go:82"
INFO[0004] shutdown HTTP server source="server.go:54"package main
import (
"context"
"github.com/BentCoder/auth/internal/http"
)
func main() {
ctx := context.WithValue(context.Background(), "SomeKey", "SomeVal")
srv := http.NewServer(":8011", 10)
srv.Start(ctx)
}和更新服务器包(相关位)如下所示。
func shutdown(ctx context.Context, .....
...
ctx, cancel := context.WithTimeout(ctx, time.Duration(tim)*time.Second)
...
}发布于 2019-10-20 18:13:28
实际上,您已经改进了设计,因为现在单元测试可以注入自己的上下文,从而使shutdown()变得可测试。纯金。
但你说的理由让我很谨慎。我会将一个参数(例如struct)传递给Start()或NewServer(),WithValue没有多少好的用途可以使您的代码更加可读性和整洁性。
此外,WithValue的文档警告说,“提供的key必须是可比较的,并且不应该是string类型或任何其他内置类型,以避免使用上下文的包之间的冲突。”所以这是你的例子的一个大问题。
https://codereview.stackexchange.com/questions/230655
复制相似问题