我有以下字符串作为TCP连接的响应返回:
220 Connected.\ncommand:connect\nemail:ERROR_MAIL_MISSING\nstatus:CMD_ERROR\nend
我希望将此响应转换为以下golang结构:
type Message struct {
Key string
Value string
}
type Response struct {
Connect string
Messages []Message
}
如果始终存在220已连接,则表示:
Response.Connect => TRUE
220 Connected之间的所有响应。和结束可以使用:
访问Response[0].Key => "command"
Response[0].Value => "connect"
这就是我实际取得的成就:
result, err := ioutil.ReadAll(conn)
data := strings.Split(string(result), "\n")
for i := range data {
Reply := new(Response)
if data[i] == "220 Connected." {
Reply.Connect = "TRUE"
Response = append(Response, Reply)
}
}
任何提示如何实现这一目标?我是Golang的新手
答案 0 :(得分:1)
您需要做更多工作来提取所需的数据。这是一个正确填充Messages
数组的示例程序。我会更新一些关于我从你的尝试转移到你正在寻找什么的做法的笔记。
package main
import "fmt"
import "strings"
type Message struct {
Key string
Value string
}
type Response struct {
Connect string
Messages []Message
}
func main() {
result := `220 Connected.\ncommand:connect\nemail:ERROR_MAIL_MISSING\nstatus:CMD_ERROR\nend`
data := strings.Split(string(result), "\\")
r := &Response{}
for i := range data {
if data[i] == "220 Connected." {
r.Connect = "TRUE"
} else {
tokens := strings.Split(data[i], ":")
if len(tokens) == 2 {
m := Message{tokens[0], tokens[1]}
r.Messages = append(r.Messages, m)
}
}
}
for i := range r.Messages {
fmt.Println(r.Messages[i])
}
}
https://play.golang.org/p/Hs8aqYPyuM
好吧,首先让我们列出一些问题。在你的尝试中,for循环看起来像这样;
for i := range data {
Reply := new(Response)
if data[i] == "220 Connected." {
Reply.Connect = "TRUE"
Response = append(Response, Reply)
}
}
这与您的类型/数据布局不一致。在每次迭代中,您创建一个新的Response
实例,实际上只需要一个实例。您希望每次迭代都需要一个新的Message
实例。这会导致一些问题,首先,您正在查看的数据不是响应,它是一条消息,其次是您继续覆盖前一个(该对象仅限于循环的范围)。为了纠正这个问题,我们在循环之前实例化Response
对象。其次,您需要进行第二次拆分才能获取数据。因此,在循环内部,我们拆分冒号以分隔每条消息的键和值。然后我在添加它之前快速检查长度(我在第一次运行时遇到了恐慌,第一次可能失败了,这意味着你需要编辑一下。如果你没有得到220连接你想要设置如果将值设置为false,则应该将消息拆分为最后的其他但仅仅是220 Connected.
不足以假设当前项为Message
这就是我添加边界检查的原因)。请注意,在此循环中,我为每个键值对实例化一条新消息。我们使用追加附加到Messages
数组,而不是将Response
附加到彼此上(因为它是结构,而不是切片或地图,所以永远不会有效)。这也使得Message
持续存在而不是在每次触及循环底部时超出范围(m
将超出范围,但r.Messages
中的实例仍将是左右)。