Go routine 编排框架:oklog/run 包

目录

  • Go routine 编排框架:oklog/run 包

    • 问题引入
    • oklog/run 包介绍
    • 使用例子
    • 参考资料

Go routine 编排框架:oklog/run 包

问题引入

oklog/run 包提供了一套非常简单、易用的 Go routine 编排框架。在介绍 oklog/run 前,我们先考虑以下问题:

假设我们有四个 Go routine 组件,如图所示,分别是运行一个状态机 sm.Run 、启动一个 HTTP 服务器、执行定时任务 cronJobs(sm) 读取状态机状态、和运行信号监听器。每个 Go routine 组件互相独立运行。

问题在于,我们如何将各个组件作为一个整体运行,并有序地结束?

对于每一个 Go routine 组件,我们都有相应的办法来执行结束操作。状态机通过 Context 对象,HTTP 服务器通过调用 Listener 的 Close 方法,定时任务和监听器通过 channel。当一个组件结束的时候,需要通知其他组件有序执行结束操作。这个问题的解决方法可以用 Actor 模型来描述。每个 Go routine 都是一个 actor,互相独立,互相之间只能通过 message 通信。oklog/run 包实现了 Actor 模型,能非常简洁的实现 Go routine 编排功能。

oklog/run 包介绍

oklog/run 包非常简单,只有一个类型,两个方法,共 60 行代码。其中 Group 是一组 actor,通过调用 Add 方法将 actor 添加到 Group 中。

type Group
func (g *Group) Add(execute func() error, interrupt func(error))
func (g *Group) Run() error
type Group struct {
    actors []actor
}

func (g *Group) Add(execute func() error, interrupt func(error)) {
    g.actors = append(g.actors, actor{execute, interrupt})
}

每个 actor 有两个方法:execute 和 interrupt。execute 完成 Go routine 的计算任务,interrupt 结束 Go routine 并退出。

type actor struct {
    execute   func() error
    interrupt func(error)
}

调用 Run 方法后会启动所有 Go routine(或者称为 actor),并等待第一个结束的 Go routine(无论正常退出或因为异常终止)。一旦捕获到第一个结束信号,会依次结束其他 Go routine 直到所有 Go routine 完全退出。

func (g *Group) Run() error {
    if len(g.actors) == 0 {
        return nil
    }

    // Run each actor.
    errors := make(chan error, len(g.actors))
    for _, a := range g.actors {
        go func(a actor) {
            errors <- a.execute()
        }(a)
    }

    // Wait for the first actor to stop.
    err := <-errors

    // Signal all actors to stop.
    for _, a := range g.actors {
        a.interrupt(err)
    }

    // Wait for all actors to stop.
    for i := 1; i < cap(errors); i++ {
        <-errors
    }

    // Return the original error.
    return err
}

使用例子

下面例子定义了三个 actor,前两个 actor 一直等待。第三个 actor 在 3s 后结束退出。引起前两个 actor 退出。

package main

import (
    "fmt"
    "github.com/oklog/run"
    "time"
)

func main() {
    g := run.Group{}
    {
        cancel := make(chan struct{})
        g.Add(
            func() error {

                select {
                case <- cancel:
                    fmt.Println("Go routine 1 is closed")
                    break
                }

                return nil
            },
            func(error) {
                close(cancel)
            },
        )
    }
    {
        cancel := make(chan struct{})
        g.Add(
            func() error {

                select {
                case <- cancel:
                    fmt.Println("Go routine 2 is closed")
                    break
                }

                return nil
            },
            func(error) {
                close(cancel)
            },
        )
    }
    {
        g.Add(
            func() error {
                for i := 0; i <= 3; i++ {
                    time.Sleep(1 * time.Second)
                    fmt.Println("Go routine 3 is sleeping...")
                }
                fmt.Println("Go routine 3 is closed")
                return nil
            },
            func(error) {
                return
            },
        )
    }
    g.Run()
}

打印结果:

Go routine 3 is sleeping...
Go routine 3 is sleeping...
Go routine 3 is sleeping...
Go routine 3 is closed
Go routine 2 is closed
Go routine 1 is closed

参考资料

Ways To Do Things - Peter Bourgon

原文地址:https://www.cnblogs.com/guangze/p/11695602.html

时间: 2024-10-18 06:23:09

Go routine 编排框架:oklog/run 包的相关文章

Spring 框架的架包分析、功能作用、优点,及jar架包简介

Spring 框架的架包详解    Spring的作用     Spring的优势 由于刚搭建完一个MVC框架,决定分享一下我搭建过程中学习到的一些东西.我觉得不管你是个初级程序员还是高级程序员抑或是软件架构师,在学习和了解一个框架的时候,首先都应该知道的是这个框架的原理和与其有关jar的作用.关系.这篇文章总结一下spring框架的相关知识. 一.spirng的简介(高手可以跳过) Spring是一个开源框架,它由Rod Johnson创建.它是为了解决企业应用开发的复杂性而创建的.Sprin

Struts2+Hibernate+Spring(SSH)三大框架整合jar包

Struts2 + Spring3 + Hibernate3 框架整合 1. 每个框架使用 (开发环境搭建 )* 表现层框架 struts2 1) jar包导入: apps/struts2_blank.war 包含struts2 开发最基本的jar包 struts2-convention-plugin-2.3.7.jar用于struts使用注解 (如果不使用注解开发,无需导入) struts2-json-plugin-2.3.7.jar 用于struts2整合Ajax struts2-sprin

SSH框架整合jar包时的注意事项

SSH框架整合jar包时的注意事项: 在将三个框架所需的jar整合到一起后,要看一下有没有相同类型但是版本不同的jar包,如果有的话,需要把低版本的jar包删除掉,否则会报错.我这里整合的时候javassit的jar出现了两个不同版本的,需要把低版本的删除掉. 原文地址:https://www.cnblogs.com/wyhluckdog/p/10139375.html

c#基于事件模型的UDP通讯框架(适用于网络包编解码)

之前写过一篇关于c#udp分包发送的文章 这篇文章里面介绍的方法是一种实现,可是存在一个缺点就是一个对象序列化后会增大非常多.不利于在网络中的传输. 我们在网络中的传输是须要尽可能的减小传送的数据包的大小.于是我參考了网上一些资料和一些开源的项目(http://www.fishlee.net/)这个上面的那个开源的飞鸽传输的框架. 事实上也就是把要传送的数据依照某种规定放在一个byte数组中,然后接收到后依照对应的格式把数据解析出来,为了减小数据还使用了GZipStream的压缩,之前出的问题就

Spring MVC 框架的架包分析,功能作用,优点

由于刚搭建完一个MVC框架,决定分享一下我搭建过程中学习到的一些东西.我觉得不管你是个初级程序员还是高级程序员抑或是软件架构师,在学习和了解一个框架的时候,首先都应该知道的是这个框架的原理和与其有关jar的作用.关系.这篇文章总结一下spring框架的相关知识. 一.spirng的简介(高手可以跳过) Spring是一个开源框架,它由Rod Johnson创建.它是为了解决企业应用开发的复杂性而创建的.Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情.然而,Spring的

手把手安装Laravel框架(permissions扩展包)实现RBAC权限---以及一些安装时的ERROR

a.依赖管理工具,框架,环境 1.composer 2.laravel(我的是5.5) 3.PHP(我的7.2),MySql(我的5.7) b,安装 1.首先需要安装一个干净的 Laravel 项目,然后在项目根目录下通过 Composer 来安装扩展包依赖: composer create-project laravel/laravel permission --prefer-dist      2.进入安装完时生成的文件夹 cd permission 执行以下命令 composer requ

[原创][LaTex]LaTex学习笔记之框架及宏包

0. 简介 LaTex在书写文档时的最基本单元就是首部的写作,变相的也可以说是头文件.本文章就来总结一下文档的基本格式和常用宏包. 1. 基本单元 基本单元需要对LaTex语法有一定的了解,这个很简单,找本书或者网上的教程看看已大家学习LaTex的劲头来说都是简简单单的.下面直接写出来,请往下看. \documentclass[a4paper]{article} \begin{document} Hello World! \end{document} 其中\documentclass是声明文档的

命令行工具命令 - run包到手机里

命令行工具命令 你完全可以选择不输入以下这些命令,执行这些命令的结果与在 Android Studio 中单击"运行"按钮是一样的. chmod +x gradlew - 此命令只需运行一次,它用于提供 gradlew 正确的执行权限. ./gradlew assembleDebug - 此命令对代码进行编译.(此时会生成一个apk包在app/build/apk) adb install -r app/build/outputs/apk/app-debug-unaligned.apk

Android 网络通信开源框架 Volley JAR包的生成(一)

#:-/code/android/frameworks/volley$ mm -B 运行结果如下: PRODUCT_COPY_FILES frameworks/base/data/sounds/letv_effects/Effect_Tick.ogg:system/media/audio/ui/Effect_Tick.ogg ignored. PRODUCT_COPY_FILES frameworks/base/data/sounds/letv_effects/camera_click.ogg: