I was wondering what would be the most elegant way to write a Key Value Form encoded map to a http.ResponseWriter.
Respond(kv map[string]string) {
for key, value := range kv {
fmt.Fprintf(a.w, "%s:%s
", key, value)
}
}
I have to follow this Key-Value format:
Key-Value Form Encoding
A message in Key-Value form is a sequence of lines. Each line begins with a key, followed by a colon, and the value associated with the key. The line is terminated by a single newline (UCS codepoint 10, " "). A key or value MUST NOT contain a newline and a key also MUST NOT contain a colon.
Additional characters, including whitespace, MUST NOT be added before or after the colon or newline. The message MUST be encoded in UTF-8 to produce a byte string.
I thought about using encoding/csv but isn't that a bit overkill?
Edit: What I came up with so far. (Thanks for all the suggested answers)
If you want to write strings to any Writer
in Go (including an http.ResponseWriter
) without using the fmt
package, you can use the bytes
package to read the strings and write them to the Writer
.
The code below creates a Buffer
from the key
and value
strings using bytes.NewBufferString
and then writes them to the http.ResponseWriter
using the WriteTo
function.
package main
import (
"bytes"
"log"
"net/http"
)
func main() {
kv := map[string]string{"key1": "val1", "key2": "val2", "key3": "val3", "key4": "val4", "key5": "val5"}
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
for key, value := range kv {
kvw := bytes.NewBufferString(key + ":" + value + "
")
if _, err := kvw.WriteTo(w); err != nil {
log.Fatal("Error: ", err)
}
}
})
if err := http.ListenAndServe("localhost:8080", nil); err != nil {
log.Fatal("ListenAndServe: ", err)
}
}
Will output:
key1:val1
key2:val2
key3:val3
key4:val4
key5:val5
Hopefully that's close to what you're after.
EDIT: You can also use the strings.Reader
Type and the corresponding WriteTo
function from the strings
package.
For example,
package main
import (
"bufio"
"bytes"
"fmt"
"io"
)
func WriteRespond(w io.Writer, kv map[string]string) error {
var buf bytes.Buffer
for k, v := range kv {
buf.WriteString(k)
buf.WriteByte(':')
buf.WriteString(v)
buf.WriteByte('
')
_, err := buf.WriteTo(w)
if err != nil {
return err
}
}
return nil
}
func main() {
kv := map[string]string{
"k1": "v1",
"k2": "v2",
}
var buf = new(bytes.Buffer)
w := bufio.NewWriter(buf)
err := WriteRespond(w, kv)
if err != nil {
fmt.Println(err)
return
}
err = w.Flush()
if err != nil {
fmt.Println(err)
return
}
fmt.Println(buf.Bytes())
fmt.Println(buf.String())
}
Output:
[107 49 58 118 49 10 107 50 58 118 50 10]
k1:v1
k2:v2
The standard library provides support for this: Look at http://godoc.org/net/url#Values.
You can do something like:
f := make(url.Values)
for k, v := range myMap {
f.Set(k, v)
}
myOutput.WriteString(f.Encode())