Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
List 在Go中获取指向列表中结构的指针_List_Go - Fatal编程技术网

List 在Go中获取指向列表中结构的指针

List 在Go中获取指向列表中结构的指针,list,go,List,Go,我正在尝试创建一个函数,该函数将查看电梯结构的列表(类型为container/list),并返回一个指针,指向具有正确ip地址的电梯(该程序用于控制多台计算机上的电梯),如果没有具有此地址的电梯,则返回nil 以下是功能代码: func (e *ElevatorList)IPIsInList(ip string) *elevator{ for c := e.Elevators.Front(); c != nil; c = c.Next(){ if(c.Value.(ele

我正在尝试创建一个函数,该函数将查看电梯结构的列表(类型为container/list),并返回一个指针,指向具有正确ip地址的电梯(该程序用于控制多台计算机上的电梯),如果没有具有此地址的电梯,则返回nil

以下是功能代码:

func (e *ElevatorList)IPIsInList(ip string) *elevator{
    for c := e.Elevators.Front(); c != nil; c = c.Next(){
        if(c.Value.(elevator).Ip == ip){
                return c.Value.(*elevator)
        }
    }
    return nil
}
我认为第一个返回行中的强制转换看起来有点可疑,但它是少数几个没有导致编译器错误的实现之一。当我运行程序时,我首先从其他函数获得输出,当调用
IPIsInList()
函数时,我得到以下结果:

panic: interface conversion: interface is **main.elevator, not main.elevator

runtime.panic+0xac /home/fredrik/go/src/pkg/runtime/proc.c:1254
runtime.panic(0x4937a8, 0xf84002aaf0)
assertE2Tret+0x11d /home/fredrik/go/src/pkg/runtime/iface.c:312
assertE2Tret(0x4927f8, 0x45e6d8, 0xf8400004f0, 0x7fbae00c1ed8, 0x10, ...)
runtime.assertE2T+0x50 /home/fredrik/go/src/pkg/runtime/iface.c:292
runtime.assertE2T(0x4927f8, 0x45e6d8, 0xf8400004f0, 0x28)
main.(*ElevatorList).IPIsInList+0x5b /home/fredrik/Dropbox/Programmering/go/listtest/elevatorList.go:72
main.(*ElevatorList).IPIsInList(0xf8400001c8, 0x4a806c, 0x2e3332310000000f, 0x0, 0x0, ...)
main.main+0x1f3 /home/fredrik/Dropbox/Programmering/go/listtest/main.go:53
main.main()
runtime.mainstart+0xf /home/fredrik/go/src/pkg/runtime/amd64/asm.s:78
runtime.mainstart()
runtime.goexit /home/fredrik/go/src/pkg/runtime/proc.c:246
runtime.goexit()
----- goroutine created by -----
_rt0_amd64+0xc9 /home/fredrik/go/src/pkg/runtime/amd64/asm.s:65
如何做到这一点?我已经多次重写了这个函数,我认为是使用了
c.Value.(电梯)
和/或
c.Value.(*电梯)
导致了这个问题。以下是
电梯
电梯列表
的结构:

type elevator struct {
Ip string
OrderList [FLOORS][3]int32
Floor int32
Dir int
Ms_since_ping int32
}

type ElevatorList struct {

Elevators *list.List

}
电梯s随功能添加到列表中

func (e *ElevatorList) AddToList(newElevator *elevator){
e.Elevators.PushBack(&newElevator)

}

在add函数中,您使用*电梯并在将指针放入列表之前获取其地址。在检索函数中,您两次断言类型为电梯。一次在if语句中,一次在return中。两者都不同意真正的类型(*电梯)。您的if语句是第一个语句,因此它解释变量是**电梯而不是电梯时会惊慌失措:

panic: interface conversion: interface is **main.elevator, not main.elevator
if(*(c.Value.(*elevator)).Ip == ip){
我会做两件事。首先,将*电梯添加到列表中,而不是**电梯:

func (e *ElevatorList) AddToList(newElevator *elevator){
    e.Elevators.PushBack(newElevator)
}
接下来,我将if语句更改为*lifter,而不是lifter:

panic: interface conversion: interface is **main.elevator, not main.elevator
if(*(c.Value.(*elevator)).Ip == ip){

显然,容器/列表是有效的,但是“应该如何做?”的答案可能是“不要使用容器/列表,只使用普通切片。”下面是另一个版本:

package main

import "fmt"

const FLOORS = 6

type elevator struct {
    Ip            string
    OrderList     [FLOORS][3]int32
    Floor         int32
    Dir           int
    Ms_since_ping int32
}

type ElevatorList []*elevator

func (list ElevatorList) IPIsInList(ip string) *elevator {
    for _, e := range list {
        if e.Ip == ip {
            return e
        }
    }
    return nil
}

func (list ElevatorList) PrintAll() {
    fmt.Println(len(list), "items in list:")
    for _, e := range list {
        fmt.Println("  ", *e)
    }
}

func main() {
    var list ElevatorList
    list = append(list, &elevator{Ip: "1.1.1.1"})
    list = append(list, &elevator{Ip: "2.2.2.2"})
    list.PrintAll()
    list.PrintOne("1.1.1.1")
}

func (list ElevatorList) PrintOne(ip string) {
    if e := list.IPIsInList(ip); e == nil {
        fmt.Println(ip, "not found")
    } else {
        fmt.Println("found:", *e)
    }
}
请注意,ElevatorList不需要是一个结构。我完全抛弃了AddToList方法。你甚至可以把它扔掉。没有它,PrintOne方法看起来就不再复杂了

func (list ElevatorList) PrintOne(ip string) {
    for _, e := range list {
        if e.Ip == ip {
            fmt.Println("found:", *e)
        }
    }
    fmt.Println(ip, "not found")
}
比如说,

package main

import (
    "container/list"
    "fmt"
)

type Elevator struct {
    Ip string
}

type Elevators struct {
    List *list.List
}

func (e *Elevators) AddToList(elevator *Elevator) {
    e.List.PushBack(elevator)
}

func (e *Elevators) IPIsInList(ip string) *Elevator {
    for c := e.List.Front(); c != nil; c = c.Next() {
        if c.Value.(*Elevator).Ip == ip {
            return c.Value.(*Elevator)
        }
    }
    return nil
}

func main() {
    elevators := Elevators{list.New()}
    ip := "192.168.0.10"
    elevator := Elevator{Ip: ip}
    elevators.AddToList(&elevator)
    eip := elevators.IPIsInList(ip)
    if eip != nil {
        fmt.Println(*eip)
    }
}
输出:

{192.168.0.10}

非常感谢。我认为我们的思路是对的,但现在它给了我“恐慌:接口转换:接口是*main.lifter,而不是*main.lifter”当我尝试添加一个*像这样:e.lifests.Pushback(*newlifter),我得到“恐慌:接口转换:接口是main.lifter,而不是*main.lifter”检索函数中还有第二个错误<代码>如果(c.Value.(电梯).Ip==Ip)。这是又一个错误的类型断言。这是一个*电梯,不是电梯。是的,我得到一个编译器错误:“不能在返回参数中使用c.Value.(电梯)(类型电梯)作为类型*电梯”,除非我有*在那里。所以你需要显式引用指针
if(*(c.Value.(*lifter)).Ip==Ip{
对不起,我想应该是
if((*c.Value.(*lifter)).Ip==Ip
。我对*运算符的优先级从来都不太熟悉。我通常将其作为一个单独的步骤来执行。无论如何,我不知道为什么它会说该接口是一个main.lifter。我会在我们之前拿走它的地方添加一个符号AND,但这没有任何意义。