使用Golang从文件中填充结构体字段

5
我对golang的开发还比较新,所以如果这是一个初级问题,我很抱歉。我没有看到类似的问题; 如果有,请指向它(谢谢)。
完整代码(在我提问时的版本,因为它不是不变的)位于http://play.golang.org/p/idDp1E-vZo 我声明了一个具有四个基本字段的结构体,并且我正在从本地文件系统上的文件中读取用于Node.ipaddr的值(我在运行时获取fileName的值作为标志; 该代码已被削减,但在上面提供的链接中)。
type Node struct {
    hostname string
    ipaddr   string
    pstatus  string
    ppid     int
}

file, err := os.Open(fileName)
if err != nil {
    panic(fmt.Sprintf("error opening %s: %v", fileName, err))
}

因为这个文件是以行为单位的,所以我认为使用bufio.Scanner来读取数据是理想的。但我在如何将数据传递到结构体元素上面遇到了困难。
我创建了一个Node元素的数组,并考虑过使用map,但我还不确定如何实际应用它。
var nodes []*Node
var nodemap = make(map[string]*Node) //do I even need this?

scanner := bufio.NewScanner(file)
for scanner.Scan() {
    if err := scanner.Err(); err != nil {
        fmt.Fprintln(os.Stderr, "error reading from file:", err)
        os.Exit(3)
    }

    //pass scanner.Text() into Node.ipaddr

}

除了将scanner.Scan()放在一个有索引的for循环中,我不确定该如何继续进行。如果我确实将scanner.Scan()放在一个有索引的for循环中,那么这个for循环能够优雅地处理EOF吗?我猜我不确定在这种情况下索引限制/最大比较值应该是什么。

一如既往,感谢您所提供的任何建议。

编辑:输入文件的格式如下:

10.1.1.1
10.1.1.2
10.1.1.3

我预计文件中会有大约150个条目,每行一个IPv4地址。


1
您是否对文件格式有控制权?如果没有,还可以在某个地方显示文件的示例。 - OneOfOne
是的,我可以控制格式。我会编辑原始帖子并提供当前格式,但它们是IPv4地址,每行一个。 - Patrick
鉴于当前情况,最简单的方法就是像你现在所做的那样扫描每一行并使用http://golang.org/pkg/net/#ParseIP解析ip,然后根据需要将解析值的结果简单地分配给您的节点值。 - Ralph Caraveo
2个回答

2
你可以使用类似 this 的东西:
func main() {
    file := strings.NewReader(IPS) //os.Open(fileName)

    var nodes []*Node

    scanner := bufio.NewScanner(file)
    for scanner.Scan() {
        if err := scanner.Err(); err != nil {
            fmt.Fprintln(os.Stderr, "error reading from file:", err)
            os.Exit(3)
        }
        ip := net.ParseIP(scanner.Text())
        if ip != nil {
            nodes = append(nodes, &Node{ipaddr: net.ParseIP(scanner.Text())})
        }

    }
    for _, n := range nodes {
        fmt.Printf("%s, %+v\n", n.ipaddr, n)
    }
}

2
我认为这是一个不错的解决方案,前提是文件内容始终是IP地址。我选择了另一个答案,因为我认为它会提供一个更通用的模式,但我也会利用从这个解决方案中学到的东西。感谢您提供的上下文,我已经点赞了。 - Patrick
1
在Go编程中的一个技巧是,始终尽可能具体地处理数据,这将使您的代码更好、更快,并且更难被破坏。 - OneOfOne
我同意@OneOfOne的观点,你不想一直使用更通用的解决方案。有一天文件会包含其他内容,而且可能有一段时间没有人注意到,最终由于通用的“ipaddr:scanner.Text()”而在ipaddr字段中出现随机内容。始终验证数据并具体说明或抛出错误。这将在某一天拯救你的生命 :) - Lukas Lukac

2
你唯一缺少的是append函数,用于向切片中添加新节点。
nodes = append(nodes, &Node{ipaddr: scanner.Text()})

此外,您可以在for循环中设置索引,同时仍然将scanner.Scan()作为条件。这样可以优雅地处理EOF,同时仍然允许您在需要时访问新的Node

for i := 0; scanner.Scan(); i++ {
    if err := scanner.Err(); err != nil {
        fmt.Fprintln(os.Stderr, "error reading from file:", err)
        os.Exit(3)
    }

    nodes = append(nodes, &Node{ipaddr: scanner.Text()})
    fmt.Println(nodes[i])
}

完整代码:http://play.golang.org/p/RvMQp-jgWF

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接