tags:

views:

136

answers:

2

In one of the example servers given at golang.org:

package main

import (
    "flag"
    "http"
    "io"
    "log"
    "template"
)

var addr = flag.String("addr", ":1718", "http service address") // Q=17, R=18
var fmap = template.FormatterMap{
    "html": template.HTMLFormatter,
    "url+html": UrlHtmlFormatter,
}
var templ = template.MustParse(templateStr, fmap)

func main() {
    flag.Parse()
    http.Handle("/", http.HandlerFunc(QR))
    err := http.ListenAndServe(*addr, nil)
    if err != nil {
        log.Exit("ListenAndServe:", err)
    }
}

func QR(c *http.Conn, req *http.Request) {
    templ.Execute(req.FormValue("s"), c)
}

func UrlHtmlFormatter(w io.Writer, v interface{}, fmt string) {
    template.HTMLEscape(w, []byte(http.URLEscape(v.(string))))
}


const templateStr = `
<html>
<head>
<title>QR Link Generator</title>
</head>
<body>
{.section @}
<img src="http://chart.apis.google.com/chart?chs=300x300&amp;cht=qr&amp;choe=UTF- 8&chl={@|url+html}"
/>
<br>
{@|html}
<br>
<br>
{.end}
<form action="/" name=f method="GET"><input maxLength=1024 size=70
name=s value="" title="Text to QR Encode"><input type=submit
value="Show QR" name=qr>
</form>
</body>
</html>
`  

Why is template.HTMLEscape(w, []byte(http.URLEscape(v.(string)))) contained within UrlHtmlFormatter? Why can't it be directly linked to "url+html"?

Also, how could I change func QR to accept parameter values? What I'd like for it to do is accept a command-line flag in place of req *http.Request ... Thanks in advance...

+1  A: 

The signature for function template.HTMLEscape is:

func(w io.Writer, s []byte)

The type declaration for template.FormatterMap is:

type FormatterMap map[string]func(io.Writer, interface{}, string)

Therefore, the signature for a FormatterMap map element value function is:

func(io.Writer, interface{}, string)

The UrlHtmlFormatter function is a wrapper to give the HTMLEscape function the FormatterMap map element value function signature.

func UrlHtmlFormatter(w io.Writer, v interface{}, fmt string) {
    template.HTMLEscape(w, []byte(http.URLEscape(v.(string))))
}
peterSO
A: 

You edited your original question to add this second question.

Also, how could I change func QR to accept parameter values? What I'd like for it to do is accept a command-line flag in place of req *http.Request.

If you read The Go Programming Language Specification, §Types, including §Function types, you will see that Go has strong static typing, including function types. While this does not guarantee to catch all errors, it usually catches attempts to use invalid, non-matching function signatures.

You don't tell us why you want to change the function signature for QR, in what appears to be an arbitrary and capricious fashion, so that it is no longer a valid HandlerFunc type, guaranteeing that the program will fail to even compile. We can only guess what you want to accomplish. Perhaps it's as simple as this: you want to modify the http.Request, based on a runtime parameter. Perhaps, something like this:

// Note: flag.Parse() in func main() {...}
var qrFlag = flag.String("qr", "", "function QR parameter")

func QR(c *http.Conn, req *http.Request) {
    if len(*qrFlag) > 0 {
        // insert code here to use the qr parameter (qrFlag)
        // to modify the http.Request (req)
    }
    templ.Execute(req.FormValue("s"), c)
}

Perhaps not! Who knows?

peterSO
Sorry. The purpose of changing the function QR is to pass it a variable as a parameter.
danwoods