1

I'm trying to make a function that will look through a list (type container/list) of elevator-structs and return a pointer to the elevator that has the correct ip-address (the program is meant to control elevators on multiple computers) or nil if there is no elevator with this address.

Here is the function code:

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
}

I think the casting in the first return line looks kind of fishy but it's one of the few implementations that hasn't caused compiler errors. When I run the program I first get the output from other functions, and when the IPIsInList() function is called i get the following:

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

How should this be done? I have rewritten the function many times and I think it's the use of c.Value.(elevator) and/or c.Value.(*elevator) that's causing the problem. Here are the structs for elevator and 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

}

The elevators are added to the list with the function

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

}

2 Answers 2

2

Obviously container/list works, but the answer to "How should this be done?" may be "don't use container/list, just use plain slices." Here's an alternative version:

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

Note that there was no need for ElevatorList to be a struct. I completely tossed the AddToList method. You might even toss IPIsInList. Without it the method PrintOne doesn't look any more complex.

func (list ElevatorList) PrintOne(ip string) {
    for _, e := range list {
        if e.Ip == ip {
            fmt.Println("found:", *e)
        }
    }
    fmt.Println(ip, "not found")
}
Sign up to request clarification or add additional context in comments.

Comments

1

In your add function, you are taking a *elevator and taking the address of the pointer before putting it in your list. In your retrieve function you are asserting that the type is an elevator twice. Once in the if statement and once in the return. Both of them disagree with the true type (*elevator). Your if statement is the first one so it panics explaining that the variable is an **elevator and not an elevator:

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

I would do two things. First, add *elevators to the list, not **elevators:

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

Next, I would change the if statement so it does a type assertion to *elevator, not elevator:

if(*(c.Value.(*elevator)).Ip == ip){

6 Comments

Thank you. I think we are on the right track, but now it gives me "panic: interface conversion: interface is *main.elevator, not main.elevator" When I try to add an * like this: e.Elevators.Pushback(*newElevator), I get "panic: interface conversion: interface is main.elevator, not *main.elevator"
You have a second error that is in your retrieval function. if(c.Value.(elevator).Ip == ip). That is another type assertion that is again wrong. It is an *elevator, not an elevator.
Yes, I get an compiler error: "cannot use c.Value.(elevator) (type elevator) as type *elevator in return argument" unless I have the * there.
So you need to explicitly reference the pointer. if(*(c.Value.(*elevator)).Ip == ip){
Sorry, I think it should be if((*c.Value.(*elevator)).Ip == ip. I am never good with the priority of the * operator. I normally do it as a separate step. Anyways, I do not know why it is saying that the interface is a main.elevator. I would add an ampersand where we took it away before, but that makes no sense.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.