Go语言 有条件地执行多个模板

lb3vh1jj  于 2023-05-04  发布在  Go
关注(0)|答案(1)|浏览(134)

我有一个有两个视图的网页,一个是匿名用户,一个是管理员用户。我想只为管理员用户显示一个导航栏。对于这两种用户类型,其他所有内容都保持不变。
这是我目前为止所尝试的

main.go

package main

import (
    "log"
    "net/http"
    "text/template"

    "github.com/julienschmidt/httprouter"
)

func BasicAuth(h httprouter.Handle, requiredUser, requiredPassword string) httprouter.Handle {
    return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
        // Get the Basic Authentication credentials
        user, password, hasAuth := r.BasicAuth()

        if hasAuth && user == requiredUser && password == requiredPassword {
            // Delegate request to the given handle
            h(w, r, ps)
        } else {
            // Request Basic Authentication otherwise
            w.Header().Set("WWW-Authenticate", "Basic realm=Restricted")
            http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
        }
    }
}

func Anonymous(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
    t, err := template.ParseFiles("index.html")
    if err != nil {
        log.Fatalln(err)
    }
    err = t.Execute(w, map[string]string{"Name": "Anonymous"})
    if err != nil {
        log.Fatalln(err)
    }
}

func Admin(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
    t, err := template.ParseFiles("index.html", "admin.html")
    if err != nil {
        log.Fatalln(err)
    }
    err = t.Execute(w, map[string]string{"Name": "Admin"})
    if err != nil {
        log.Fatalln(err)
    }
}

func main() {
    user := "admin"
    pass := "1234"

    router := httprouter.New()
    router.GET("/", Anonymous)
    router.GET("/admin/", BasicAuth(Admin, user, pass))

    log.Fatal(http.ListenAndServe(":8080", router))
}

index.html

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>{{ .Name }}</title>
        <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css" rel="stylesheet">
        <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/js/bootstrap.bundle.min.js"></script>
        <script src="https://code.jquery.com/jquery-3.6.4.min.js"></script>
        <script>
            function counter() {
                document.getElementById("x").innerHTML = "x: " + document.querySelectorAll('.x').length;
                document.getElementById("y").innerHTML = "y: " + document.querySelectorAll('.y').length;
                document.getElementById("z").innerHTML = "z: " + document.querySelectorAll('.z').length;
            }
        </script>
    </head>
    <body onload="counter()">
        {{ template "dashboard" }}
        <nav class="navbar fixed-bottom">
            <div class="container-fluid nav-justified">
                <span id="x" class="navbar-brand nav-item"></span>
                <span id="y" class="navbar-brand nav-item"></span>
                <span id="z" class="navbar-brand nav-item"></span>
            </div>
        </nav>
    </body>
</html>

admin.html

{{ define "dashboard" }}
<nav class="navbar">
    <div class="container-fluid nav-justified">
        <span class="nav-item">
            <a class="navbar-brand" href="/a">a</a>
        </span>
        <span class="nav-item">
            <a class="navbar-brand" href="/b">b</a>
        </span>
        <span class="nav-item">
            <a class="navbar-brand" href="/c">c</a>
        </span>
    </div>
</nav>
{{ end }}

我的假设是,因为我在为匿名用户执行模板时没有传入admin.html模板,所以 Jmeter 板模板不会被解析。但是,我遇到了这个错误:

template: index.html:18:14: executing "index.html" at <{{template "dashboard"}}>: template "dashboard" not defined

我该如何解决这个问题,或者有更好的方法来解决这个问题?

goqiplq2

goqiplq21#

使用if操作有条件地渲染dashboard模板:

{{ if eq .Name "Admin" }} {{ template "dashboard" }} {{ end }}

实际做法是只解析模板一次,而不是在每个请求中都解析它:

package main

import (
    "log"
    "net/http"
    "sync"
    "text/template"

    "github.com/julienschmidt/httprouter"
)

func BasicAuth(h httprouter.Handle, requiredUser, requiredPassword string) httprouter.Handle {
    return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
        user, password, hasAuth := r.BasicAuth()

        if hasAuth && user == requiredUser && password == requiredPassword {
            h(w, r, ps)
        } else {
            w.Header().Set("WWW-Authenticate", "Basic realm=Restricted")
            http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
        }
    }
}

func Anonymous(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
    err := tmpl.Execute(w, map[string]string{"Name": "Anonymous"})
    if err != nil {
        log.Fatalln(err)
    }
}

func Admin(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
    err := tmpl.Execute(w, map[string]string{"Name": "Admin"})
    if err != nil {
        log.Fatalln(err)
    }
}

var (
    tmpl     *template.Template
    tmplOnce sync.Once
)

func main() {
    user := "admin"
    pass := "1234"

    tmplOnce.Do(func() {
        tmpl = template.Must(template.ParseFiles("index.html", "admin.html"))
    })

    router := httprouter.New()
    router.GET("/", Anonymous)
    router.GET("/admin/", BasicAuth(Admin, user, pass))

    log.Fatal(http.ListenAndServe(":8080", router))
}

相关问题