[英]Getting pointer to struct in list in Go
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. 我正在尝试创建一个函数,它将查看电梯结构的列表(类型容器/列表)并返回指向具有正确IP地址的电梯的指针(该程序用于控制多台计算机上的电梯)如果没有带此地址的电梯,则为零。
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: 当我运行程序时,我首先从其他函数获取输出,并且当
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
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. 我已多次重写该功能,我认为这是使用
c.Value.(elevator)
和/或c.Value.(*elevator)
导致问题。 Here are the structs for elevator
and Elevator_list
: 以下是
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
}
The elevator
s are added to the list with the function elevator
被添加到具有该功能的列表中
func (e *ElevatorList) AddToList(newElevator *elevator){
e.Elevators.PushBack(&newElevator)
}
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. 请注意,ElevatorList不需要是struct。 I completely tossed the AddToList method.
我完全抛弃了AddToList方法。 You might even toss IPIsInList.
你甚至可能会抛出IPIsInList。 Without it the method PrintOne doesn't look any more complex.
没有它,PrintOne的方法看起来就不复杂了。
func (list ElevatorList) PrintOne(ip string) {
for _, e := range list {
if e.Ip == ip {
fmt.Println("found:", *e)
}
}
fmt.Println(ip, "not found")
}
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.
一旦进入if语句,一次进入返回。 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:
你的if语句是第一个,所以它恐慌地解释变量是**电梯而不是电梯:
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语句,以便它对*电梯进行类型断言,而不是电梯:
if(*(c.Value.(*elevator)).Ip == ip){
For example, 例如,
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)
}
}
Output: 输出:
{192.168.0.10}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.