随机数未呈现的HTML模板

I am running the Go [go1.12.9 windows/amd64] program below (to test out the Go HTML Templates) in

localhost/8080/

But the templates just don't render in the browser (Chrome, Edge).

Also there are no errors given in the console.

How should one get this program to render in the browser?

package main

import (

    // "fmt"
    "html/template"
    "log"
    "math/rand"
    "net/http"
    "time"
    // "golang.org/x/mobile/app"
)

func main() {
    http.HandleFunc("/", randNum)
    log.Fatal(http.ListenAndServe(":8080", nil))

}

func randNum(w http.ResponseWriter, r *http.Request) {
    // Create random number
    type RNumber struct {
        A int
    }

    aRand := rand.Intn(10)
    Rnum := RNumber{aRand}

    //Show Template
    Tmpl, _ := template.New("randNum1").Parse("HTML NUMBER ======> {{.A}}  ")
    // Tmpl := template.Must(template.ParseFiles("ui0.html"))<===Also passed values to Html files not rendering
    err := Tmpl.Execute(w, Rnum)
    if err != nil {
        print(err)
    }
    time.Sleep(3000 * time.Millisecond)

    //Loop
    randNum(w, r)
}

EDIT 1

Please note that a new random number shown every 3s is a requirement .In this edit , the recursive randnum call has been removed and a new "for" loop has been added to the above script.However ,the html renders a random number and then renders the same number.It doesn't render a new random number every 3 seconds ,as expected.

import (
// "fmt"
    "html/template"
    "log"
    "math/rand"
    "net/http"
    "time"
    // "golang.org/x/mobile/app"
)

func main() {
    http.HandleFunc("/", randNum)
    log.Fatal(http.ListenAndServe(":8080", nil))
}

func randNum(w http.ResponseWriter, r *http.Request) {
    // Create random number
    type Rnumber struct {
        A int
    }

    aRand := rand.Intn(10)
    Rnumber1 := Rnumber{aRand}

    //Create Template
    Tmpl, _ := template.New("randNum1").Parse("HTML NUMBER ======> {{.A}}  ")

    // Render a new random number every 3s
    loop := 5
    for loop > 0 {
            fmt.Println("loop = ", loop)
        loop --
        err := Tmpl.Execute(w, Rnumber1)
        if err != nil {
            print(err)
        }
        time.Sleep(3000 * time.Millisecond)
    }
}

**

EDIT 2

I have added an fmt.Println("loop = ", loop) line in the above script to check how the looping happens in a for loop(-5times) with a Sleep function(3s).Below is the result of the above "for loop".Still ,not sure how a new random number is not getting displayed?

HTML RENDERED

HTML NUMBER ======> 425  HTML NUMBER ======> 425  HTML NUMBER ======> 425  HTML NUMBER ======> 425  HTML NUMBER ======> 425   

CONSOLE OUTPUT

loop =  4
loop =  4
loop =  4
loop =  4
loop =  4
loop =  4
loop =  3
loop =  4
loop =  3
loop =  3
loop =  3
loop =  3
loop =  3
loop =  2
loop =  3
loop =  2
loop =  2
loop =  2
loop =  2
loop =  2
loop =  1
loop =  2
loop =  1
loop =  1
loop =  1
loop =  1
loop =  1
loop =  0
loop =  1
loop =  0
loop =  0
loop =  0
loop =  0
loop =  0
loop =  0

randNum is an enabled recursion, it'll call itself every 3 seconds until it crashes with a stack overflow. And since it never returns, http server will not close the connection expecting the handler to finish writing. Remove the sleep and randnum call lines. Instead, return from the function after writing the template to the writer w.

The problem

For every request, the handler is called as a goroutine, meaning that your thread.Sleep() will run for request r. When a new request r+1 comes in, the whole handler is executed again.

A solution

What you need to have is a goroutine manipulating the random number every 3 seconds atomically and independent from your handler code.

package main

import (
    "html/template"
    "log"
    "math/rand"
    "net/http"
    "sync/atomic"
    "time"
)

// We make the template String a const to make the code more readable.
const templateString = "HTML Number ==> {{.Random}}"

// We use an int32 here, as it is by far big enough to
// hold our values and since the atomic package we
// use later down the road requires us to be specific.
var a int32

// Make the template global for convenience.
var tmpl *template.Template

// Initialize the stuff we need.
func init() {

    // We seed our random to make it less predictable
    // Note that you should use "crypto/rand" in
    // production environments.
    rand.Seed(time.Now().Unix())

    // We atomically set a to a random value.
    // Strictly speaking, this would not be necessary, as init is called
    // before main starts, but it shows how to set a value.
    atomic.StoreInt32(&a, rand.Int31n(10))

    // Either the template parses or the program panics.
    tmpl = template.Must(template.New("randNum1").Parse(templateString))
}

func main() {

    // Create a goroutine...
    go func(d time.Duration) {

        // ...which creates a ticker triggering every d.
        tick := time.NewTicker(d)

        // After every d...
        for range tick.C {
            // ...atomically change the value of a to a new random number
            n := rand.Int31n(10)
            atomic.SwapInt32(&a, rand.Int31n(10))
            log.Printf("Set a to %d", n)
        }
    }(3 * time.Second)

    // Now, our handler becomes trivial.
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        // We use an anonymous struct here.
        // No need to clutter the code with unnecessary type definitions.
        tmpl.Execute(w, struct{ Random int32 }{atomic.LoadInt32(&a)})
    })

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

The result

Above code renders as expected:

Screenshot of rendered template in browser

And the log output looks like this:

2019/09/01 14:15:24 Set a to 2
2019/09/01 14:15:27 Set a to 1
2019/09/01 14:15:30 Set a to 1
2019/09/01 14:15:33 Set a to 3
2019/09/01 14:15:36 Set a to 9
2019/09/01 14:15:39 Set a to 4
2019/09/01 14:15:42 Set a to 2