Golang:结构体中的字段未定义错误

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

Golang: Undefined field in struct error

问题

我正在尝试使用golang解析一个xml文件。我已经创建了所需的结构体,但是当我尝试编译go文件时,出现以下错误:

./main_v4.go:146: aggInfoXml.IpAddr.Hports未定义(类型[]Addr没有字段或方法Hports)

我对这个问题感到困惑。以下是我的代码:

package main

import (
	"net/http"
	"html/template"
	"os/exec"
	"io/ioutil"
	"os"
	"encoding/xml"
	"encoding/json"
	"fmt"
	"bufio"
	"github.com/gorilla/websocket"
	"time"
	"log"
)

type PercentInfo struct {
	Percent IntPercent `xml:"taskprogress,omitempty"`
} 

type AggInfoXml struct {
	Percent     IntPercent  `xml:"taskprogress,omitempty"`
	IpAddr      []Addr      `xml:"host>address,omitempty"`
}

type IntPercent struct {
	Value float64 `xml:"percent,attr,omitempty"` // works
}

type Addr struct {
	Ip      string   `xml:"addr,attr"`
	Hports  []Ports  `xml:"host>ports>port,omitempty"` //failing to be recognized
}

type Ports struct {
	Port string `xml:"portid,attr"`
}

func (p *Addr) ipaddr() string {
	return p.Ip
}

func (p *Ports) ports() string {
	return p.Port
}

func (p *IntPercent) percent() float64 {
	return p.Value
}

func (f *Test) Name() string {
	return f.Value
}

var upgrader = websocket.Upgrader{
	ReadBufferSize: 1024,
	WriteBufferSize: 1024,
}

type Test struct {
	Value string    
}

func wsHandler(w http.ResponseWriter, r *http.Request) {

	conn, err := upgrader.Upgrade(w, r, nil)
	if err != nil {
		fmt.Println(err)
	}

	cmd := exec.Command("nmap", "-F", "-sS", "172.16.2.0/24", "-oX", "output.xml", "--stats-every", "1s")

	if err := cmd.Start(); err != nil {
		log.Fatal(err)
	}

	time.Sleep( 1000 * time.Millisecond) 

	fp, err := os.Open("output.xml")
	if err != nil {
		log.Fatal(err)
	}

	// create scanner on the output.xml file
	in := bufio.NewScanner(fp)

	// change this loop to buffer read the xml file...
	aggInfoXml  := AggInfoXml{}

	fmt.Printf("hello")

	for in.Scan() {

		err = xml.Unmarshal([]byte(in.Text()), &aggInfoXml.Percent) 
		if err != nil {
			fmt.Printf("Could not unmarshal the line <%v>", in.Text())
		} else {
			fmt.Printf("%+v\n", aggInfoXml.Percent.Value)
		}

		// bail out of slow loop if 100% reached
		if aggInfoXml.Percent.Value == 100 {
			break
		}

		time.Sleep(1000*time.Millisecond)

		bytesArray, err := json.Marshal(aggInfoXml.Percent)

		err = conn.WriteMessage(websocket.TextMessage, bytesArray)  // send JSON over
		if err != nil {
			panic(err)
		}

	}//this is the end of the in.Scan loop now

	fmt.Println("After loop")

	if err := cmd.Wait(); err != nil {  
		log.Fatal(err)
	}

	data, err := ioutil.ReadFile("output.xml")

	if err != nil {
		panic(err)
	}

	err = xml.Unmarshal(data, &aggInfoXml.IpAddr)
	if err != nil {
		log.Fatal("Could not unmarshal host")
	}

	for _, port := range aggInfoXml.IpAddr.Hports {
		fmt.Printf("Port: %s\n", port.ports())
	}

	for _, ip := range aggInfoXml.IpAddr {
		fmt.Printf("IpAdd: %s\n", ip.ipaddr())
	}

	conn.Close()
	fp.Close()
}

func handler(w http.ResponseWriter, r *http.Request) {

	t, _ := template.ParseFiles("index.html")
	t.Execute(w,nil)
}

func main() {

	http.HandleFunc("/", handler)
	http.Handle("/layout/", http.StripPrefix("/layout/", http.FileServer(http.Dir("layout"))))
	http.HandleFunc("/websocket", wsHandler)
	http.ListenAndServe(":8080", nil) 
}

有任何建议吗?

英文:

I am trying to parse an xml file using golang. I have created my structs needed but when I try to compile the go file, I get an error saying the following:

./main_v4.go:146: aggInfoXml.IpAddr.Hports undefined (type []Addr has no field or method Hports)

I am stumped on this problem. Here is my code:

package main
import(
&quot;net/http&quot;
&quot;html/template&quot;
&quot;os/exec&quot;
&quot;io/ioutil&quot;
&quot;os&quot;
&quot;encoding/xml&quot;
&quot;encoding/json&quot;
&quot;fmt&quot;
&quot;bufio&quot;
&quot;github.com/gorilla/websocket&quot;
&quot;time&quot;
&quot;log&quot;
)
type PercentInfo struct {
Percent IntPercent `xml:&quot;taskprogress,omitempty&quot;`
} 
type AggInfoXml struct {
Percent     IntPercent  `xml:&quot;taskprogress,omitempty&quot;`
IpAddr      []Addr      `xml:&quot;host&gt;address,omitempty&quot;`
}
type IntPercent struct {
Value float64 `xml:&quot;percent,attr,omitempty&quot;` // works
}
type Addr struct {
Ip      string   `xml:&quot;addr,attr&quot;`
Hports  []Ports  `xml:&quot;host&gt;ports&gt;port,omitempty&quot;` //failing to be recognized
}
type Ports struct {
Port string `xml:&quot;portid,attr&quot;`
}
func (p *Addr) ipaddr() string {
return p.Ip
}
func (p *Ports) ports() string {
return p.Port
}
func (p *IntPercent) percent() float64 {
return p.Value
}
func (f *Test) Name() string {
return f.Value
}
var upgrader = websocket.Upgrader{
ReadBufferSize: 1024,
WriteBufferSize: 1024,
}
type Test struct {
Value string    
}
func wsHandler(w http.ResponseWriter, r *http.Request) {
conn, err := upgrader.Upgrade(w, r, nil)
if err != nil {
fmt.Println(err)
}
cmd := exec.Command(&quot;nmap&quot;, &quot;-F&quot;, &quot;-sS&quot;, &quot;172.16.2.0/24&quot;, &quot;-oX&quot;, &quot;output.xml&quot;, &quot;--stats-every&quot;, &quot;1s&quot;)
if err := cmd.Start(); err != nil {
log.Fatal(err)
}
time.Sleep( 1000 * time.Millisecond) 
fp, err := os.Open(&quot;output.xml&quot;)
if err != nil {
log.Fatal(err)
}
// create scanner on the output.xml file
in := bufio.NewScanner(fp)
// change this loop to buffer read the xml file...
aggInfoXml  := AggInfoXml{}
fmt.Printf(&quot;hello&quot;)
for in.Scan() {
err = xml.Unmarshal([]byte(in.Text()), &amp;aggInfoXml.Percent) 
if err != nil {
fmt.Printf(&quot;Could not unmarshal the line &lt;%v&gt;&quot;, in.Text())
} else {
fmt.Printf(&quot;%+v\n&quot;, aggInfoXml.Percent.Value)
}
// bail out of slow loop if 100% reached
if aggInfoXml.Percent.Value == 100 {
break
}
time.Sleep(1000*time.Millisecond)
bytesArray, err := json.Marshal(aggInfoXml.Percent)
err = conn.WriteMessage(websocket.TextMessage, bytesArray)  // send JSON over
if err != nil {
panic(err)
}
}//this is the end of the in.Scan loop now
fmt.Println(&quot;After loop&quot;)
if err := cmd.Wait(); err != nil {  
log.Fatal(err)
}
data, err := ioutil.ReadFile(&quot;output.xml&quot;)
if err != nil {
panic(err)
}
err = xml.Unmarshal(data, &amp;aggInfoXml.IpAddr)
if err != nil {
log.Fatal(&quot;Could not unmarshal host&quot;)
}
for _, port := range aggInfoXml.IpAddr.Hports {
fmt.Printf(&quot;Port: %s\n&quot;, port.ports())
}
for _, ip := range aggInfoXml.IpAddr {
fmt.Printf(&quot;IpAdd: %s\n&quot;, ip.ipaddr())
}
conn.Close()
fp.Close()
}
func handler(w http.ResponseWriter, r *http.Request) {
t, _ := template.ParseFiles(&quot;index.html&quot;)
t.Execute(w,nil)
}
func main() {
http.HandleFunc(&quot;/&quot;, handler)
http.Handle(&quot;/layout/&quot;, http.StripPrefix(&quot;/layout/&quot;, http.FileServer(http.Dir(&quot;layout&quot;))))
http.HandleFunc(&quot;/websocket&quot;, wsHandler)
http.ListenAndServe(&quot;:8080&quot;, nil) 
}

Any suggestions would be helpful.

答案1

得分: 1

type AggInfoXml struct {
Percent IntPercent xml:"taskprogress,omitempty"
IpAddr []Addr xml:"host>address,omitempty"
}

type Addr struct {
Ip string xml:"addr,attr"
Hports []Ports xml:"host>ports>port,omitempty" // 无法识别
}

IpAddr 是一个数组。它没有名为 Hports 的属性。你需要像这样引用该数组的一个元素。

aggInfoXml.IpAddr[0].Hports

但是,如果你想访问 Hports 的端口,则需要这样做。

aggInfoXml.IpAddr[0].Hports[0]

英文:
type AggInfoXml struct {
Percent     IntPercent  `xml:&quot;taskprogress,omitempty&quot;`
IpAddr      []Addr      `xml:&quot;host&gt;address,omitempty&quot;`
}
type Addr struct {
Ip      string   `xml:&quot;addr,attr&quot;`
Hports  []Ports  `xml:&quot;host&gt;ports&gt;port,omitempty&quot;` //failing to be recognized
}

IpAddr is an Array. It has no attribute called Hports. You will have to refer one of the elements of that array like this.

aggInfoXml.IpAddr[0].Hports 

but if you want to access port of Hports, then you will have to do this.

aggInfoXml.IpAddr[0].Hports[0] 

答案2

得分: 0

我已经给Prajwal的答案点了赞,因为他指出了问题,但实际上,在你的代码中,你应该将你的for循环替换为类似这样的代码:

for _, ip := range aggInfoXml.IpAddr {
    fmt.Printf("IpAdd: %s\n", ip.ipaddr())

    for _, port := range ip.Hports {
        fmt.Printf("Port: %s\n", port.ports())
    }
}
英文:

I have upvoted the answer from Prajwal as it points to the problem, but actually, in your code it seems you should be replacing your for loops with something like this:

for _, ip := range aggInfoXml.IpAddr {
fmt.Printf(&quot;IpAdd: %s\n&quot;, ip.ipaddr())
for _, port := range ip.Hports {
fmt.Printf(&quot;Port: %s\n&quot;, port.ports())
}
}

huangapple
  • 本文由 发表于 2016年11月25日 15:02:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/40799391.html
匿名

发表评论

匿名网友

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

确定