如何处理和获得golang goroutines的响应

如何处理和获得golang goroutines的响应,go,grpc,server-sent-events,goroutine,Go,Grpc,Server Sent Events,Goroutine,我在无人机的getPosition、getStatus和rerouting中调用了go例程。目前,我在我的主函数中调用go getStatus,该函数有go func(),用于处理grpc和sse流的事件 目前这是我的代码,我试过了 func GetPositionContext(ctx context.Context, uav pb.UAVControllerClient, uavID *pb.UAVID, projectID string) { log.Printf("getPosi

我在无人机的getPosition、getStatus和rerouting中调用了go例程。目前,我在我的主函数中调用go getStatus,该函数有go func(),用于处理grpc和sse流的事件

目前这是我的代码,我试过了

func GetPositionContext(ctx context.Context, uav pb.UAVControllerClient, uavID *pb.UAVID, projectID string) {
    log.Printf("getPosition start")

    stream, err := uav.GetPosition(ctx)

    if err != nil {
        fmt.Printf("ERROR getPosition:%s", err.Error())
    }

    streamID, eventName := EventsSubscribe(projectID, uavID.Aircraft, "get_position")

    position := make(chan models.DronePosition)

    // 受信ループ開始
    go func() {
        fmt.Print("start getPosition loop")
        for {
            msg, err := stream.Recv() // msg UAVPosition
            if err == io.EOF {
                // read done.
                fmt.Print("start getPosition loop closed")
                close(position)
                return
            }
            if err != nil {
                log.Fatalf("Failed to receive getPosition : %v", err)
                close(position)
                return
            }
            // log.Printf("Position point[%s](%f, %f, %f) H:%f", uavID.Aircraft, msg.Latitude, msg.Longitude, msg.Altitude, msg.Heading)

            wayPoint := models.WaypointItem{
                Latitude:  msg.Latitude,
                Longitude: msg.Longitude,
                Altitude:  msg.Altitude,
                Heading:   msg.Heading,
            }

            dronePosition := models.DronePosition{
                Name:          uavID.Aircraft,
                ItemParameter: wayPoint,
            }

            // publish to eventgo
            publishNotif(dronePosition, streamID, eventName)
            return
        }
    }()

    startMsg := pb.UAVControllerPositionRequest{
        UavID:       uavID,
        Instruction: true,
        Interval:    2,
    }

    fmt.Print("send getPosition start")

    if err := stream.Send(&startMsg); err != nil {
        log.Fatalf("Failed to send getPosition: %v", err)
    }

    <-position

    stream.CloseSend()
    fmt.Print("end of getPosition")
}
我想从go func获取返回值,比如如果grpc服务器中一切正常,没有问题,我应该返回200 success,如果失败,返回500

for {
        time.Sleep(time.Duration(60) * time.Second)
    }
在调用之后,我有了这个代码,它应该每10秒返回一次成功

return c.JSON(500, failed or pass)

如果go例程成功或失败,当流媒体部分为响应不挂起而工作,或者其他api调用将不工作时,我希望返回到ui。

我建议设置一个通道来接收来自go例程的事件。在调用函数中,您可以在循环中侦听这些事件(可以包含您想要的任何信息),直到go例程自行关闭,表示失败。

如果您想知道在GetPositionContext中处理go func()时是否有错误,可以执行以下操作。我修改了所有错误,使其冒泡,而不是调用log.Fatal。另一方面,推迟
stream.CloseSend()
可能是明智的,但我缺少上下文,这超出了问题的范围

我尽力去理解这个问题,但是如果我遗漏了什么,请告诉我

该代码已修改为直接在GetPositionContext中冒泡出现错误,而不是调用log.Fatal。此外,如果go func()中存在错误,它将通过通道发送回GetPositionContext,然后返回给调用方

func GetPositionContext(ctx context.Context, uav pb.UAVControllerClient, uavID *pb.UAVID, projectID string) error {
    log.Printf("getPosition start")

    stream, err := uav.GetPosition(ctx)

    if err != nil {
        return fmt.Errorf("ERROR getPosition: %v", err.Error())
    }

    streamID, eventName := EventsSubscribe(projectID, uavID.Aircraft, "get_position")

    errC := make(chan error)

    // 受信ループ開始
    go func() {
        fmt.Print("start getPosition loop")
        for {
            msg, err := stream.Recv() // msg UAVPosition
            if err == io.EOF {
                // read done.
                fmt.Print("start getPosition loop closed")
                close(errC)
                return
            }
            if err != nil {
                errC <- fmt.Errorf("Failed to receive getPosition : %v", err)
                return
            }
            // log.Printf("Position point[%s](%f, %f, %f) H:%f", uavID.Aircraft, msg.Latitude, msg.Longitude, msg.Altitude, msg.Heading)

            wayPoint := models.WaypointItem{
                Latitude:  msg.Latitude,
                Longitude: msg.Longitude,
                Altitude:  msg.Altitude,
                Heading:   msg.Heading,
            }

            dronePosition := models.DronePosition{
                Name:          uavID.Aircraft,
                ItemParameter: wayPoint,
            }

            // publish to eventgo
            publishNotif(dronePosition, streamID, eventName)

            // Did you mean to return here? The for loop will only ever execute one time.
            // If you didn't mean to return, then remove this close
            close(errC)
            return
        }
    }()

    startMsg := pb.UAVControllerPositionRequest{
        UavID:       uavID,
        Instruction: true,
        Interval:    2,
    }

    fmt.Print("send getPosition start")

    if err := stream.Send(&startMsg); err != nil {
        return fmt.Errorf("Failed to send getPosition: %v", err)
    }

    err = <- errC

    stream.CloseSend()
    fmt.Print("end of getPosition")
    return err
}
func GetPositionContext(ctx context.context,uav pb.UAVControllerClient,uavID*pb.uavID,projectd string)错误{
log.Printf(“getPosition开始”)
流,错误:=uav.GetPosition(ctx)
如果错误!=零{
返回fmt.Errorf(“ERROR getPosition:%v”,err.ERROR())
}
streamID,eventName:=EventsSubscribe(projectID,uavID.Aircraft,“获取位置”)
errC:=制造(chan错误)
// 受信ループ開始
go func(){
fmt.打印(“启动getPosition循环”)
为了{
msg,err:=stream.Recv()//msg UAVPosition
如果err==io.EOF{
//阅读完毕。
fmt.打印(“开始-获取-位置循环关闭”)
关闭(errC)
返回
}
如果错误!=零{

errC如果您有任何想法,请提供帮助。您根本无法获得“来自goroutine的响应”:这是不可能的。如果您想将goroutine的任何结果传达给其他goroutine,您通常会使用一个频道。(您应该提供一个简化的示例,因为我不知道您的代码的用途。)。当前是。我正在调用另一个go例程来传递值
func F(n int,wg*sync.WaitGroup){//defer wg.Done()defer wg.Done()//在此处执行作业结果这是代码非常感谢您的回复。我会检查并让您知道它看起来不错。但是,即使结果是返回的,除了删除关闭(errC)之外,这是否可能继续运行?这是来自grpc的流,因此我不想停止go func()中的for循环将继续循环,直到到达返回。在任何一点,您都希望结束循环(返回),请确保向频道发送错误或关闭频道。啊,好的,这也很好,但我当前的目标是,当流媒体工作正常时,它应该返回200或500,如果err!=nil,那么这就是我发送错误的时间。我现在正在修改它,但无法获得好的结果。
func GetPositionContext(ctx context.Context, uav pb.UAVControllerClient, uavID *pb.UAVID, projectID string) error {
    log.Printf("getPosition start")

    stream, err := uav.GetPosition(ctx)

    if err != nil {
        return fmt.Errorf("ERROR getPosition: %v", err.Error())
    }

    streamID, eventName := EventsSubscribe(projectID, uavID.Aircraft, "get_position")

    errC := make(chan error)

    // 受信ループ開始
    go func() {
        fmt.Print("start getPosition loop")
        for {
            msg, err := stream.Recv() // msg UAVPosition
            if err == io.EOF {
                // read done.
                fmt.Print("start getPosition loop closed")
                close(errC)
                return
            }
            if err != nil {
                errC <- fmt.Errorf("Failed to receive getPosition : %v", err)
                return
            }
            // log.Printf("Position point[%s](%f, %f, %f) H:%f", uavID.Aircraft, msg.Latitude, msg.Longitude, msg.Altitude, msg.Heading)

            wayPoint := models.WaypointItem{
                Latitude:  msg.Latitude,
                Longitude: msg.Longitude,
                Altitude:  msg.Altitude,
                Heading:   msg.Heading,
            }

            dronePosition := models.DronePosition{
                Name:          uavID.Aircraft,
                ItemParameter: wayPoint,
            }

            // publish to eventgo
            publishNotif(dronePosition, streamID, eventName)

            // Did you mean to return here? The for loop will only ever execute one time.
            // If you didn't mean to return, then remove this close
            close(errC)
            return
        }
    }()

    startMsg := pb.UAVControllerPositionRequest{
        UavID:       uavID,
        Instruction: true,
        Interval:    2,
    }

    fmt.Print("send getPosition start")

    if err := stream.Send(&startMsg); err != nil {
        return fmt.Errorf("Failed to send getPosition: %v", err)
    }

    err = <- errC

    stream.CloseSend()
    fmt.Print("end of getPosition")
    return err
}
errC := make(chan error)
go func() {
  errC <- GetPositionContext(..........)
}()
// Do some other stuff here
// Until you need the result
err := <- errC


// ... and Eventually when you want to return the success or failure as JSON
if err != nil {
  return c.JSON(500, failed)
}
return c.JSON(500, pass)