调用 eq 时出错:Go 模板中的比较类型无效

error calling eq: invalid type for comparison in Go template

背景:几个静态网页共享相同的header。我将通过判断其状态(在 Go 模板中)来突出显示活动的 header 项,使用

<a href="/home" class="{{ if eq .Active "home"}} active{{end}}">Home</a>

在终端中以

结尾
2018/08/19 16:46:49 template: _header.html:21:53: executing "_header.html" at <eq . "home">: error calling eq: invalid type for comparison

错误主要是抱怨未定义的“.Active”,这让我相信加载视图模型失败。
这里是commit and repo。我将在下面显示关键文件:

_layout.html

<!DOCTYPE html>

<html>

<head>
    <title>{{.Title}}</title>
    <link href="/css/app.css" rel="stylesheet" /> {{block "styles" .}}{{end}}
</head>

<body>
    {{template "_header.html"}} {{template "content" .}} {{template "_footer.html"}}{{block "scripts" .}}{{end}}
</body>

</html>

_header.html

<header class="row">
    <div class="columns small-2">
        <div class="logo-container">
            <div class="logo"></div>
            <h1>Lemonade Stand Supply</h1>
        </div>
    </div>
    <div class="columns small-10">
        <div class="row">
            <div class="columns small-1 small-offset-9">
                <a class="secondary-color tiny" href="/login"> login </a>
            </div>
            <div class="columns small-2">
                <img src="/img/cart_small.png" alt="cart" />
            </div>
        </div>
        <div class="row">
            <nav class="columns small-6 small-offset-6">
                <div class="row">
                    <div class="columns small-3 item">
                        <a href="/home" class="{{ if eq .Active "home"}} active {{end}}">Home</a>
                    </div>
                    <div class="columns small-3 item">
                        <a href="/shop" class="{{ if eq .Active "shop"}} active {{end}}">Shop</a>
                    </div>
                    <div class="columns small-6 item">
                        <a href="." class="{{ if eq .Active "standlocator"}} active {{end}}">Stand Locator</a>
                    </div>
                </div>
            </nav>
        </div>
    </div>
</header>

main.go

package main

import (
    "html/template"
    "io/ioutil"
    "log"
    "net/http"
    "os"

    "TutorialCreatingWebApplicationsWithGo/src/github.com/lss/webapp/viewmodel"
)

func main() {
    templates := populateTemplates()
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        requestedFile := r.URL.Path[1:]
        template := templates[requestedFile+".html"]
        var context interface{}
        switch requestedFile {
        case "shop":
            context = viewmodel.NewShop()
        default:
            context = viewmodel.NewHome()
        }
        if template != nil {
            err := template.Execute(w, context)
            if err != nil {
                log.Println(err)
            }
        } else {
            w.WriteHeader(http.StatusNotFound)
        }
    })
    http.Handle("/img/", http.FileServer(http.Dir("../../../../public")))
    http.Handle("/css/", http.FileServer(http.Dir("../../../../public")))
    http.ListenAndServe(":8080", nil)
}

func populateTemplates() map[string]*template.Template {
    result := make(map[string]*template.Template)
    const basePath = "../../../../templates"
    layout := template.Must(template.ParseFiles(basePath + "/_layout.html"))
    template.Must(layout.ParseFiles(basePath+"/_header.html", basePath+"/_footer.html"))
    dir, err := os.Open(basePath + "/content")
    if err != nil {
        panic("Failed to open template blocks directory: " + err.Error())
    }
    fis, err := dir.Readdir(-1)
    if err != nil {
        panic("Failed to read contents of content directory: " + err.Error())
    }
    for _, fi := range fis {
        f, err := os.Open(basePath + "/content/" + fi.Name())
        if err != nil {
            panic("Failed to open template '" + fi.Name() + "'")
        }
        content, err := ioutil.ReadAll(f)
        if err != nil {
            panic("Failed to read content from file '" + fi.Name() + "'")
        }
        f.Close()
        tmpl := template.Must(layout.Clone())
        _, err = tmpl.Parse(string(content))
        if err != nil {
            panic("Failed to parse contents of '" + fi.Name() + "' as template")
        }
        result[fi.Name()] = tmpl
    }
    return result
}

查看模型 - home.go

package viewmodel

type Home struct {
    Title  string
    Active string
}

func NewHome() Home {
    result := Home{
        Active: "home",
        Title:  "Lemonade Stand Supply",
    }
    return result
}

视图模型 - shop.go

package viewmodel

type Shop struct {
    Title      string
    Active     string
    Categories []Category
}

type Category struct {
    URL         string
    ImageURL    string
    Title       string
    Description string
}

func NewShop() Shop {
    result := Shop{
        Title:  "Lemonade Stand Supply - Shop",
        Active: "shop",
    }
    juiceCategory := Category{
        URL:      "/shop_details",
        ImageURL: "lemon.png",
        Title:    "Juices and Mixes",
        Description: `Explore our wide assortment of juices and mixes expected by today's
        lemonade stand clientelle. Now featuring a full line of organic juices that are guaranceed
        to be obtained from trees that have never been treated with pesticide or artificial fertilizers.`,
    }
    supplyCategory := Category{
        URL:      ".",
        ImageURL: "kiwi.png",
        Title:    "Cups, Straws, and Other Supplies",
        Description: `From paper cups to bio-degradable plastic to straws and napkins,
        LSS is your source for the sundries that keep you stand running smoothl.`,
    }
    advertiseCategory := Category{
        URL:      ".",
        ImageURL: "pineapple.png",
        Title:    "Signs and Advertising",
        Description: `Sure, you could just wait for people to find your stand along
        the side of the road, but if you want to take it to the next level, our premium
        line of advertising supplies.`,
    }
    result.Categories = []Category{juiceCategory, supplyCategory, advertiseCategory}
    return result
}

这是课程 Creating Web Application with Go by Mike Van Sickle (module 5.7, Logical Tests) 的字面跟进。仔细匹配每个文件与讲师提供的示例代码(完美运行),我发现代码是相同的,但仍然找不到问题的原因。

把你的template/_layout.html改成这个

<!DOCTYPE html>
<html>
<head>
<title>{{.Title}}</title>
<link href="/css/app.css" rel="stylesheet" />
{{block "styles" .}}{{end}}
</head>
<body>
    {{template "_header.html" .}}
    {{template "content" .}}
    {{template "_footer.html" .}}
    {{block "scripts" .}}{{end}}
</body>
</html>

您的基本模板不正确,这就是您收到此错误的原因。