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

huangapple go评论139阅读模式
英文:

golang populate struct field from file

问题

我对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) //我甚至需要这个吗?

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)
	}

	//将scanner.Text()传递给Node.ipaddr

}

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

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

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

10.1.1.1
10.1.1.2
10.1.1.3

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

英文:

I'm pretty new to developing in golang, so if this is an elementary question I apologize. I didn't see a comparable question already asked; if there is one, please point me to it (thanks).

The full code (at the time of my asking this question, since it's not immutable) is at http://play.golang.org/p/idDp1E-vZo

I've declared a struct with four primitive fields, and I'm reading the values destined for Node.ipaddr from a file on the local filesystem (I'm getting the value of fileName as a flag at runtime; that code is trimmed out here but is in the link provided above.)

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))
}

Because the file is line-delimited, I thought a bufio.Scanner would be ideal for reading the data from the file. Where I am struggling is finding an elegant way to actually pass the data into the struct elements.

I created an array of Node elements, and have considered a map, but I am not sure how I'd make practical use of it (yet).

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

}

Short of wrapping scanner.Scan() in an indexed for loop, I'm not at all sure how to proceed. If I do wrap scanner.Scan() in an indexed for loop, will the for loop be able to handle EOF elegantly -- I guess I'm not sure what the index limit/max comparison value should be in that case.

As always, thanks for any advice that you're willing to offer.

edit: The format of the input file is like this:

10.1.1.1
10.1.1.2
10.1.1.3

I anticipate approx 150 entries in the file, one IPv4 address per line.

答案1

得分: 2

你可以使用类似于这个的代码:

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)
    }
}

请注意,这只是一个示例代码,其中的IPSNode是未定义的变量。你需要根据实际情况进行适当的修改。

英文:

You could use something along the lines of 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

得分: 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

英文:

The only thing you're missing is the append function to add a new node to the slice.

nodes = append(nodes, &Node{ipaddr: scanner.Text()})

Also, you can have an index on your for loop while still having the scanner.Scan() as the condition. This lets the EOF be handled elegantly while still allowing you to access that new Node if need be.

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])
}

Full code: http://play.golang.org/p/RvMQp-jgWF

huangapple
  • 本文由 发表于 2014年5月15日 06:14:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/23666085.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定