Thursday, November 21, 2019

go lang, html/template and sort...

I have created a simple page that prints running local docker images with their metadata. Using simple go lang and html/template. Then things went complicated: I couldn't sort a slice.

Quick introduction to go lang

Go language is a language created (and released) by google. It is based on many existing "things" that got compiled to a target environment, where really many environments are available. Code is executed in some kind of a sandbox (similar to java runtime environment). You could also run the code without storing compiled binary using `go run whatever.go` or compile and run using `go build whatever.go && ./whatever`.
Pros: supports multiple environments, is "managed" (garbage collector), has good support, is simple, has built-in testing framework, is compiled into a binary, can be compiled on runtime
Cons: different from most languages, extensible only to some extend (at some point you need to get into low level sources), has "different" source management/versioning, testing package is pretty "raw",large binary footprint (simple "hello world" app would be probably 10MB large or 5MB after stripping)

Source code before

Note the error handling is omitted.
package main
import (
        "html/template"
        "net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
        data := []map[string]string{{"k": "2", "v": "a"}, {"k": "1", "v": "b"}}
        t, _ := template.ParseFiles("template.tmpl")
        t.Execute(w, data)
}
func main() {
        http.HandleFunc("/", handler)
        http.ListenAndServe(":8081", nil)
}


<html><body>
{{range .}}
        {{.v}},
{{end}}

</body></html>
 
Output: a,b,

Quick solution

Source code after

Note the error handling is omitted.
package main
import (
        "html/template"
        "net/http"
)
func mySort(s []map[string]string) map[string]map[string]string{
        m := make(map[string]map[string]string, len(s))
        for i:=0; i
                m[s[i]["k"]] = s[i]
        }
        return m 
} 
func handler(w http.ResponseWriter, r *http.Request) {
        data := []map[string]string{{"k": "2", "v": "a"}, {"k": "1", "v": "b"}}
        t, _ := template.New("template.tmpl").Funcs(template.FuncMap{"mySort":mySort}).ParseFiles("template.tmpl")
        // Note that I cannot simply use ParseFiles as it calls New() inside 
        t.Execute(w, data)
}
func main() {
        http.HandleFunc("/", handler)
        http.ListenAndServe(":8081", nil)
}
 
<html><body>
{{range .|mySort}}
        {{.v}},
{{end}}

</body></html> 
 
Output: b,a,

Final comments

Please let me know what you think about it. And leave a comment if you find it useful (just to let me know it is used by anyone and it has any value to the community).

No comments: