[]uint8 printing in html template does weird things

I was trying to print a []uint8 slice in an html template within a <script></script> block, but it does weird things. I say that, because printing a []int8 behaves as I would expect.

Incase the above play link ever vanishes, the code is:

package main

import (
	"html/template"
	"os"
)

func main() {
	Create := func(name, t string) *template.Template {
		return template.Must(template.New(name).Parse(t))
	}
	t2 := Create("t2", "outside script:\n{{.INT8_ARR}}\n{{.UINT8_ARR}}\n{{.INT8}}\n{{.UINT8}}\n<script>\n{{.INT8_ARR}}\n{{.UINT8_ARR}}\n{{.INT8}}\n{{.UINT8}}\n</script>")

	t2.Execute(os.Stdout, struct {
		INT8_ARR  []int8
		UINT8_ARR []uint8
		INT8      int8
		UINT8     uint8
	}{
		INT8_ARR:  []int8{2, 3, 4},
		UINT8_ARR: []uint8{2, 3, 4},
		INT8:      5,
		UINT8:     6,
	})
}

With the output being:

outside script:
[2 3 4]
[2 3 4]
5
6
<script>
[2,3,4]
"AgME"
 5 
 6 
</script>

For some reason, it looks to be base64 encoding a uint8 array (the "AgME"). Any idea what’s going on here? Does html/template think it’s a byte array and attempting to sanitize it?

Ran the template code in a debugger, and found a shorter example to show the same thing.

package main

import (
	"encoding/json"
	"fmt"
)

func main() {
	v, _ := json.Marshal([]int8{3, 4, 5})
	fmt.Println(string(v))
	v, _ = json.Marshal([]uint8{3, 4, 5})
	fmt.Println(string(v))
}

Which will print:

[3,4,5]
"AwQF"

Digging a little, I found: src/encoding/json/encode.go - go - Git at Google

So I was right. It looks like the code is mixing up byte slice with a uint8 slice. :frowning: Looks like the spec says a byte is just an alias for uint8 (per: The Go Programming Language Specification - The Go Programming Language). So uint8 with the json.Encoder just don’t play together well.

1 Like