首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在戈朗环游context.Context

在戈朗环游context.Context
EN

Code Review用户
提问于 2019-10-13 17:07:51
回答 1查看 438关注 0票数 4

目前,我正在“优雅地”处理HTTP net/http关机,它运行得非常好(我不是要求您检查服务器关机)。如下面的代码所示,在运行应用程序时,context是第一次直接在服务器包中创建的。之后我所做的就是(这是我希望您回顾的),在调用服务器并将其传递给服务器之前,我已经创建了一个context.Background()。这一做法在戈朗是否可以接受/可行?

为什么我想要预先创建一个context,而一切都已经很好了?

  • 这是因为我需要context中的几个键值对,这样我就可以在整个应用程序中使用它们。

当前在服务器

中使用上下文的实现

cmd/auth/main.go

代码语言:javascript
复制
package main

import (
    "github.com/BentCoder/auth/internal/http"
)

func main() {
    srv := http.NewServer(":8011", 10)
    srv.Start()
}

internal/http/server.go

代码语言:javascript
复制
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)
}

输出

代码语言:javascript
复制
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"

,这就是我决定做的,

代码语言:javascript
复制
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)
}

和更新服务器包(相关位)如下所示。

代码语言:javascript
复制
func shutdown(ctx context.Context, .....
    ...
    ctx, cancel := context.WithTimeout(ctx, time.Duration(tim)*time.Second)
    ...
}
EN

回答 1

Code Review用户

发布于 2019-10-20 18:13:28

实际上,您已经改进了设计,因为现在单元测试可以注入自己的上下文,从而使shutdown()变得可测试。纯金。

但你说的理由让我很谨慎。我会将一个参数(例如struct)传递给Start()NewServer()WithValue没有多少好的用途可以使您的代码更加可读性和整洁性。

此外,WithValue的文档警告说,“提供的key必须是可比较的,并且不应该是string类型或任何其他内置类型,以避免使用上下文的包之间的冲突。”所以这是你的例子的一个大问题。

票数 1
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/230655

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档