Получение указателя на структуру в списке в Go - PullRequest
1 голос
/ 15 марта 2012

Я пытаюсь создать функцию, которая просматривает список (тип контейнер / список) структур лифта и возвращает указатель на лифт, который имеет правильный IP-адрес (программа предназначена для управления лифтами на несколько компьютеров) или ноль, если нет лифта с этим адресом.

Вот код функции:

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.(elevator) и / или c.Value.(*elevator) вызывает проблему. Вот структуры для elevator и Elevator_list:

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

type ElevatorList struct {

Elevators *list.List

}

elevator добавляются в список с помощью функции

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

}

Ответы [ 3 ]

2 голосов
/ 15 марта 2012

Очевидно, контейнер / список работает, но ответ на вопрос «Как это сделать?» может быть «не используйте контейнер / список, просто используйте простые кусочки». Вот альтернативная версия:

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. Вы могли бы даже бросить IPIsInList. Без этого метод PrintOne не выглядит более сложным.

func (list ElevatorList) PrintOne(ip string) {
    for _, e := range list {
        if e.Ip == ip {
            fmt.Println("found:", *e)
        }
    }
    fmt.Println(ip, "not found")
}
1 голос
/ 15 марта 2012

В вашей функции добавления вы берете * лифт и берете адрес указателя, прежде чем добавить его в свой список. В своей функции извлечения вы утверждаете, что типом является лифт дважды. Один раз в операторе if и один раз в ответе. Оба они не согласны с истинным типом (* лифт). Ваш оператор if является первым, поэтому он паникует, объясняя, что переменная - это ** лифт, а не лифт:

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

Я бы сделал две вещи. Сначала добавьте в список * лифты, а не ** лифты:

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

Далее я бы изменил оператор if, чтобы он делал утверждение типа на * elevator, а не elevator:

if(*(c.Value.(*elevator)).Ip == ip){
0 голосов
/ 15 марта 2012

Например,

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}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...