-1

seems like go slice append (string) changes all items when I render it to the template (also when I log the slice to the terminal) I think this is a golang thing but I am not sure with Django template

Updated the code, but I still have the same problem with mutex and regular Html template

package main

import (
    "log"
    "sync"

    "github.com/gofiber/fiber/v2"
    "github.com/gofiber/template/html"
)

func main() {
    engine := html.New("./views", ".html")
    app := fiber.New(fiber.Config{
        Views: engine,
    })

    type Whatever struct {
        Whatever string `json:"whatever" form:"whatever"`
    }
    var (
        itemsMu sync.RWMutex
        items   = []string{}
    )

    app.Get("/", func(c *fiber.Ctx) error {
        itemsMu.RLock()
        defer itemsMu.RUnlock()
        return c.Render("index", fiber.Map{
            "Title": "Hello, World!",
            "Slice": items,
        })
    })

    app.Post("/", func(c *fiber.Ctx) error {
        w := new(Whatever)
        if err := c.BodyParser(w); err != nil {
            return err
        }
        itemsMu.Lock()
        items = append(items, w.Whatever)
        log.Println(items)
        itemsMu.Unlock()
        return c.Redirect("/")
    })
    log.Fatal(app.Listen(":3000"))
}
  • I'd suspect the problem is with your iteration. The append should be fine. Can you show your iteration code? – TehSphinX Oct 04 '21 at 09:25
  • If you print `items` in the GET handler, it is correct. So the problem must be somewhere in the template, which we can't look at. – TehSphinX Oct 04 '21 at 09:45
  • `{% extends "./layouts/base.html" %} {% block title %}Index{% endblock title %} {% block content %}
    {{ Title }}
      {% for s in slice %}
    • {{ s }}
    • {% endfor %}
    {% endblock %}`
    – Eduard Khiaev Oct 04 '21 at 10:01

1 Answers1

0

HTTP requests are served on different goroutines. Variables scoped outside of requests (such as your items) that are accessed from requests must be synchronized.

Accessing (writing) writing variables from different goroutines is a data race and undefined behaviour.

Add proper synchronization, then see the result.

For example:

var (
    itemsMu sync.RWMutex
    items = []string{}
) 

app.Get("/", func(c *fiber.Ctx) error {
    itemsMu.RLock()
    defer itemsMu.RUnlock()
    return c.Render("index", fiber.Map{
        "Title": "Hello, World!",
        "slice": items,
    })
})

app.Post("/", func(c *fiber.Ctx) error {
    w := new(Whatever)
    if err := c.BodyParser(w); err != nil {
        return err
    }
    itemsMu.Lock()
    items = append(items, w.Whatever)
    itemsMu.Unlock()
    return c.Redirect("/")
})
icza
  • 389,944
  • 63
  • 907
  • 827