2013-07-16 34 views
0

我想知道什么是最优雅的方式来编写一个键值表 编码地图到http.ResponseWriter。如何优雅或有效地写一个地图到http.ResponseWriter

Respond(kv map[string]string) { 
    for key, value := range kv { 
    fmt.Fprintf(a.w, "%s:%s\n", key, value) 
    } 
} 

我必须遵循该键值格式:

键值形成编码

在关键值形式的消息是线的序列。每行用一个键开始 ,后跟一个冒号,以及与 键相关联的值。该行由一个换行符终止(UCS代码点10, “\ n”)。一个键或值不能包含一个换行符,而且一个键也不能包含冒号。

不得在 之前或冒号或换行符后面添加其他字符,包括空格。该消息必须以UTF-8编码为 产生一个字节字符串。

我想过使用编码/ csv,但不是有点矫枉过正?

编辑:到目前为止我想出了。 (感谢所有的建议答案)

http://godoc.org/github.com/kugutsumen/encoding/keyvalue

https://github.com/kugutsumen/encoding/tree/master/keyvalue

回答

1

如果不想使用fmt包写在Go字符串任何Writer(包括http.ResponseWriter),你可以使用bytes包读取字符串并将它们写入Writer

下面的代码创建使用bytes.NewBufferStringkeyvalue串的Buffer,然后使用WriteTo函数它们写入http.ResponseWriter

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 + "\n") 
      if _, err := kvw.WriteTo(w); err != nil { 
       log.Fatal("Error: ", err) 
      } 
     } 
    }) 
    if err := http.ListenAndServe("localhost:8080", nil); err != nil { 
     log.Fatal("ListenAndServe: ", err) 
    } 
} 

将输出:

KEY1:VAL1
KEY2:VAL2
KEY3:VAL3
KEY4:VAL4
KEY5:val5

希望这很接近你以后的事情。

编辑:你也可以使用strings.Reader类型和strings包中相应的WriteTo函数。

+0

我没有使用http.HandleFunc :)我一直在寻找的东西效率比调用fmt.Fprintf问题...... – Kugutsumen

+0

我已经编辑我的答案使用'bytes'包而不是'fmt'包。它可能更接近你想要的。 – Intermernet

+0

你也可以使用'strings'包来实现相同的功能。 – Intermernet

1

例如,

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('\n') 
     _, 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()) 
} 

输出:

[107 49 58 118 49 10 107 50 58 118 50 10] 
k1:v1 
k2:v2 
+0

写入“缓冲​​区”后无需检查错误。 'Buffer'的Write函数总是返回'nil'作为错误。 – Mostafa

+0

@Mostafa:欢迎提出意见。不要改变答案。你的改变是错误的。 – peterSO

+0

为什么不换?这就是工作原理。删除总是假的子句会出现什么问题? – Mostafa

3

标准库提供这种支持:看http://godoc.org/net/url#Values

你可以这样做:

f := make(url.Values) 
for k, v := range myMap { 
    f.Set(k, v) 
} 
myOutput.WriteString(f.Encode()) 
+0

感谢这是一个很好的提示...我开始通过编写我的encode()函数基于url.Values的encode(),但不喜欢它使用一个字符串数组作为值,而Add()方法只是附加到数组,而Get()方法返回数组中的第一个条目。此外,我使用的编码必须遵循Openid Auth 2.0(4.1.1)。 – Kugutsumen