Formatting a CHANGES text file as HTML I have a function which is used to convert text (a CHANGES file) into HTML for reading. The function is essentially line-based: if the line is of this type, do this thing; if some other type, do that thing; etc. Further logic needs to be added before the fallback

b.WriteString("&lt;p&gt;" + line + "&lt;/p&gt;\n")


but I wanted to better organize my code before adding the more complex logic.

As written the code looks like a nightmare to me -- there has to be some better, more idiomatic way to write this. I'm new enough to Go that I'm not sure what the best way forward is.

var h3Regex = regexp.MustCompile("^Done for version ([1-9]\\.[0-9]\\.[0-9]) \\(released ([0-9/-]+)\\):$")
var h4Regex = regexp.MustCompile("^  (Fixed|Added|Changed|Removed)$")
var variable = "[a-zA-Z][a-zA-Z0-9_]*(?:\\(\\))?"
var stuff = "^  (?:[A-Z]+ )?[0-9]+- GP functions? (" + variable + "(?:, ?" + variable + ")*)$"
var GPRegex = regexp.MustCompile(stuff)

func layout(text string) string {
    lines := strings.Split(html.EscapeString(text), "\n")
    var b bytes.Buffer
    for _, line := range lines {
        match := h3Regex.FindStringSubmatch(line)
        if len(match) &gt; 0 {
            b.WriteString("&lt;h3&gt;Version " + match[1] + ", released " + match[2] + "&lt;/h3&gt;\n")
            continue
        }
        match = h4Regex.FindStringSubmatch(line)
        if len(match) &gt; 0 {
            b.WriteString("&lt;h4&gt;" + match[1] + "&lt;/h4&gt;\n")
            continue
        }
        match = GPRegex.FindStringSubmatch(line)
        if len(match) &gt; 0 {
            funcs := strings.Split(match[1], ",")
            if len(funcs) &gt; 1 {
                b.WriteString("&lt;p&gt;GP functions ")
            } else {
                b.WriteString("&lt;p&gt;GP function ")
            }
            for idx, f := range funcs {
                if idx &gt; 0 {
                    b.WriteString(", ")
                }
                b.WriteString(`&lt;code class="GP"&gt;` + f + `&lt;/code&gt;`)
            }
            b.WriteString("&lt;/p&gt;\n")
            continue
        }
        b.WriteString("&lt;p&gt;" + line + "&lt;/p&gt;\n")
    }
    return b.String()
}
Take a look at html/template package from standard library. It will help you a lot in separating parsing code and HTML generation. Also it will escape all input by default.



Some other notes:


It is handy to use ` instead of " when writing regular expressions with lots of escapes.
GPRegex variable will be exported. Should it be?
Kudos for using bytes.Buffer and not concating strings by hand (: