Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Golang unexpected EOF with nested templates

I am trying to display the contents of a slice on a page. Displaying the templates with static text works. As soon as I try and range over the slice sent to ExTpl(), I get an EOF error.

type Miner struct {
    IP          string `bson:"ip"`
    Port        int32  `bson:"port"`
    FailCount   int    `bson:"failcount"`
}

type (
    MinerController struct {
        Session *mgo.Session
    }
)

func ExTpl(w http.ResponseWriter, data []Miner) {
    t, _ := template.ParseFiles("templates/header.tmpl", "templates/footer.tmpl", "templates/data.tmpl")
    t.ExecuteTemplate(w, "data", data)
}

func FilterMiners(c *mgo.Collection, key, value string, limit int) ([]Miner, int, error) {
    var results []Miner
    query := bson.M{key: value}
    if len(key) == 0 {
        query = nil
    }

    err := c.Find(query).Limit(limit).All(&results)
    if err != nil {
        return results, 0,errors.New("error retrieving hosts")
    }
    return results, len(results), nil
}

func (mc MinerController) GetSpecificMiners(w http.ResponseWriter, r *http.Request) {
    vars := mux.Vars(r)
    l, err := strconv.Atoi(vars["limit"])
    if err != nil {
        l = 0
    }

    collection := Collection("miners", "NASty", mc.Session)
    fleet, _ , _ := FilterMiners(collection, vars["key"], vars["value"], l)
    ExTpl(w, fleet)
}

Here are the templates in question:

header.tmpl

{{define "header"}}
<!DOCTYPE html>
<html>
  <head>
    <title></title>
    <link href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1">
  </head>
  <body>
{{end}}

data.tmpl

{{define "data"}}
{{template "header"}}
{{range .}}
    {{.IP}}
{{template "footer"}}
{{end}}

footer.tmpl

{{define "footer"}}
</body>
</html>
{{end}}

When I run this, I get the following error:

2017/10/27 12:24:56 http: panic serving [::1]:50252: template: data.tmpl:6: unexpected EOF
goroutine 49 [running]:
net/http.(*conn).serve.func1(0xc042138000)
    C:/Go/src/net/http/server.go:1721 +0xd7
panic(0x7abbc0, 0xc042170360)
    C:/Go/src/runtime/panic.go:489 +0x2dd
git.REDACTED.duckdns.org/REDACTED/RESTingMongo/controllers.ExTpl(0x9b7820, 0xc04211c460, 0xc042172000, 0x2, 0x2)
    D:/_projects/Go/src/git.REDACTED.duckdns.org/REDACTED/RESTingMongo/controllers/handlers.go:25 +0x84
git.REDACTED.duckdns.org/REDACTED/RESTingMongo/controllers.MinerController.GetSpecificMiners(0xc04203b040, 0x9b7820, 0xc04211c460, 0xc0420f6600)
    D:/_projects/Go/src/git.REDACTED.duckdns.org/REDACTED/RESTingMongo/controllers/miners.go:74 +0x2b9
git.REDACTED.duckdns.org/REDACTED/RESTingMongo/controllers.(MinerController).GetSpecificMiners-fm(0x9b7820, 0xc04211c460, 0xc0420f6600)
    D:/_projects/Go/src/git.REDACTED.duckdns.org/REDACTED/RESTingMongo/routes/routes.go:33 +0x55
net/http.HandlerFunc.ServeHTTP(0xc04203f210, 0x9b7820, 0xc04211c460, 0xc0420f6600)
    C:/Go/src/net/http/server.go:1942 +0x4b
git.REDACTED.duckdns.org/REDACTED/RESTingMongo/routes.Logger.func1(0x9b7820, 0xc04211c460, 0xc0420f6600)
    D:/_projects/Go/src/git.REDACTED.duckdns.org/REDACTED/RESTingMongo/routes/handlers.go:12 +0x18d
net/http.HandlerFunc.ServeHTTP(0xc0420467c0, 0x9b7820, 0xc04211c460, 0xc0420f6600)
    C:/Go/src/net/http/server.go:1942 +0x4b
github.com/gorilla/mux.(*Router).ServeHTTP(0xc04203c420, 0x9b7820, 0xc04211c460, 0xc0420f6600)
    D:/_projects/Go/src/github.com/gorilla/mux/mux.go:133 +0x108
net/http.serverHandler.ServeHTTP(0xc04208e2c0, 0x9b7820, 0xc04211c460, 0xc042116100)
    C:/Go/src/net/http/server.go:2568 +0x99
net/http.(*conn).serve(0xc042138000, 0x9b7fe0, 0xc042104280)
    C:/Go/src/net/http/server.go:1825 +0x619
created by net/http.(*Server).Serve
    C:/Go/src/net/http/server.go:2668 +0x2d5

I am not sure what is going on, since all of my templates have the correct format, and the Miner struct contains an IP field, which I should be able to access in the range loop with .IP.

like image 330
ChaChaPoly Avatar asked Oct 27 '17 10:10

ChaChaPoly


2 Answers

Your data template definition is invalid. Both the {{define}} and {{range}} actions need a closing {{end}}, so it should be:

{{define "data"}}
    {{template "header"}}
    {{range .}}
        {{.IP}}
    {{end}}
    {{template "footer"}}
{{end}}

Some advices:

  • Never omit errors, always check them and the least you can do is print them (you omit errors returned by template.ParseFiles() and FilterMiners()).

  • Never parse templates in HTTP handlers, for details see: It takes too much time when using "template" package to generate a dynamic web page to client in golang

like image 183
icza Avatar answered Sep 21 '22 19:09

icza


From what I can see you have an {{end}} missing in data.tmpl.

{{define "data"}}
{{template "header"}}
{{range .}}
    {{.IP}}
{{template "footer"}}
{{end}}

should be:

{{define "data"}}
{{template "header"}}
{{range .}}
    {{.IP}}
{{end}}
{{template "footer"}}
{{end}}
like image 26
Pharrisee Avatar answered Sep 18 '22 19:09

Pharrisee