【问题标题】:Changing a value of a variable which is inside an if statement that referencing a flag更改引用标志的 if 语句中的变量的值
【发布时间】:2018-08-26 01:19:38
【问题描述】:

我有以下 Go 程序,它是一个静态文件服务器。我在控制台中收到以下错误:

..\static\main.go:45:5: cannot use handlers.CombinedLoggingHandler(os.Stdout, r) (type http.Handler) as type *mux.Router in assignment: need type assertion
..\static\main.go:52:5: cannot use handlers.CompressHandler(l) (type http.Handler) as type *mux.Router in assignment: need type assertion

如何在 Gorilla Mux 路由器和 CombinedLoggingHandler 或 CompressHandler 中使用标志?

package main

import (
    "flag"
    "fmt"
    "log"
    "net/http"
    "os"
    "time"

    "github.com/gorilla/handlers"
    "github.com/gorilla/mux"

    controllers "<this_is_a_local_repo>"
    common "<this_is_a_local_repo>"
)

var (
    host     = flag.String("host", "127.0.0.1", "TCP host to listen to")
    port     = flag.String("port", "8081", "TCP port to listen to")
    logging  = flag.Bool("logging", false, "Whether to enable HTTP response logging")
    compress = flag.Bool("compress", true, "Whether to enable transparent response compression")
    dir      = flag.String("dir", common.Abs("public"), "Directory to serve static files from")
)

func main() {
    flag.Parse()

    r := mux.NewRouter().StrictSlash(true)
    r.PathPrefix("/static/").Handler(http.StripPrefix("/static/", http.FileServer(http.Dir(*dir))))
    r.PathPrefix("/").HandlerFunc(controllers.IndexHandler(*dir + "/index.html")) // catch-all route for 404

    l := r
    if *logging {
        l = handlers.CombinedLoggingHandler(os.Stdout, r)
    }

    h := l
    if *compress {
        h = handlers.CompressHandler(l) // gzip all responses
    }

    srv := &http.Server{
        Handler: h,
        Addr:    fmt.Sprintf("%s:%s", *host, *port),
        ReadTimeout:  5 * time.Second,
        WriteTimeout: 10 * time.Second,
        IdleTimeout:  15 * time.Second,
    }
    log.Fatal(srv.ListenAndServe())
}

【问题讨论】:

  • var h http.Handler = r,如果 ... 那么 h = handlers.CombinedLoggingHandler(os.Stdout, h),如果 ... 那么 h = handlers.CompressHandler(h)。不用l := r和h := l,做h = middleware(h)就可以了。
  • 您正在为CombinedLoggingHandler 和CompressHandler 分配一个*路由器。它们都需要处理程序类型,但这里不是这种情况
  • @Himanshu 你的意思是 return 对吗?因为只要他们将http.Handler 作为参数,代码就可以了,因为*mux.Router 实现了该接口。问题是他们也 return 一个http.Handler 但赋值左侧的值的类型是*mux.Router 而不是http.Handler...问题是什么类型这两个函数return,而不是它们需要的参数。
  • 根据第一条评论,他应该修复它play.golang.org/p/zD5Ran7t3Kj
  • @mkopriva http.Handler 是一个使用servemux 作为接收者的函数。您已经声明了该类型的变量。汉德是一种类型?我从未见过声明函数类型的变量。请详细说明。我正处于学习阶段

标签: go mux gorilla


【解决方案1】:

您似乎正在尝试将中间件添加到您的 gorilla/mux 路由器。

您可以使用Router.Use() 添加中间件。

Router.Use() 采用mux.MiddlewareFunc,它只是一个带有签名func (http.Handler) http.Handler 的函数。您将遇到的大多数中间件都与此签名匹配,或者可以很容易地进行包装,如下例所示。

从我自己的一些内部代码中窃取:

func myLoggingHandler(next http.Handler) http.Handler {
    return handlers.CombinedLoggingHandler(os.Stdout, next)
}

func main() {
    r := mux.NewRouter()

    if logging {
        r.Use(myLoggingHandler)
    }
    if compress {
        r.Use(handlers.CompressHandler)
    }

    http.Handle("/", r)

    log.Fatal(http.ListenAndServe("[::]:8009", nil))

}

【讨论】:

  • 我接受这个作为答案,因为它为我的问题提供了更简单的解决方案,但我认为 mkopriva 的解决方案更通用(对于 fasthttp)。我还注意到flag.Bool 接受每个控制台参数为真,甚至false,因为缺少类型转换。所以我使用flag.String 和if logging == "true" {}。
  • 我的错误,布尔标志的格式应该是-foo=bar,对不起。 golang.org/pkg/flag
猜你喜欢
  • 2017-09-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-11
  • 1970-01-01
  • 2023-02-06
  • 2021-08-13
  • 1970-01-01
相关资源
最近更新 更多