英文:
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(
"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)
}
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:"taskprogress,omitempty"`
IpAddr []Addr `xml:"host>address,omitempty"`
}
type Addr struct {
Ip string `xml:"addr,attr"`
Hports []Ports `xml:"host>ports>port,omitempty"` //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("IpAdd: %s\n", ip.ipaddr())
for _, port := range ip.Hports {
fmt.Printf("Port: %s\n", port.ports())
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论