目录

1.创建一个yaml文件,名字可以是student.yaml

2.创建go文件测试

3.执行结果


欢迎关注公众号:天天说编程

你的关注是我最大的动力!

本文章内容,只是一个简单的案例,但足够映射到一个大的项目中。

工作流作用:工作流的作用就是通过yaml配置文件,将关于本工作流的一个个task任务串联起来形成一个大的功能体。通过加载yaml,将任务执行的顺序固定化。

说白了就是对任务进行编排,当大流量来的时候,可以让线程排队执行。

比如:用户注册,需要验证哪些参数,比如验证邮件地址,验证手机号,可以把这些小功能放到一个小任务中,也就是task。然后将这些任务串起来,形成一个大功能,也就是工作流。

现在举个具体的案例,来实现一个简易的工作流,更加通俗易懂。

这里举了一个用户注册的功能。

1.创建一个yaml文件,名字可以是student.yaml

yaml都是key:value结构。- 代表的是一个数组,数组中的元素是key:value结构,这个value还可以是数组类型等等。

# 工作流名字
workflow: "user"

# 具体执行的任务
tasks:
    # 邮件地址的有效性
    # 单斜杠后面 - 后面是一个列表
    # name:task的名字
    # action:具体task对应的方法
    # params:相关参数,这个参数可能是前端传来的,需要取出,也可能是上一个task的结果。
    # requires:这个任务是否有依赖,也就是这个任务执行的时候需要执行的另一个任务。

  - name: "validate_email"
    action: "validate_email_action"
    params:
      email: "user@example.com"
    requires: []

  - name: "create_user"
    action: "create_user_action"
    params:
      "username": "yaml"
      "password": "123456"
    
    # 这儿创建用户的时候需要验证邮件地址是否有效
    requires:
      - "validate_email"

  - name: "send_welcome_email"
    action: "send_welcome_email_action"
    params:
        "recipient": "user@example.com"
        "subject": "Welcome to our platform!"
        "body":
          "Dear John Doe,
          Welcome to our platform! We are excited to have you on board.
          Best regards,
          The Team"
    # 发送这个welcome消息的时候,代表创建成功。
    "requires":
          - "create_user"
2.创建go文件测试

创建一个main.go

package main

import (
	"fmt"
	"gopkg.in/yaml.v3"
	"io/ioutil"
)
// Workflow 结构体
type Workflow struct {
	Name  string `yaml:"workflow"`
	Tasks []Task `yaml:"tasks"`
}

// Task 结构体
type Task struct {
	Name     string         `yaml:"name"`
	Action   string         `yaml:"action"`
	Params   map[string]any `yaml:"params"`
	Requires []string       `yaml:"requires"`
}

func main() {
	data, err := ioutil.ReadFile("workflow/student.yml")
	if err != nil {
		fmt.Println("读取配置文件失败:", err)
		return
	}

	var workflow Workflow
	// yaml反序列化,将字节类型的数据反序列化到结构体中
	err = yaml.Unmarshal(data, &workflow)
	if err != nil {
		fmt.Println("data反序列化错误:", err)
		return
	}

	// 执行工作流的任务
	// 获取工作流
	for _, task := range workflow.Tasks {
		if checkDependecies(task.Requires) {
			fmt.Println("执行任务", task.Name)
			result, err := executeTask(task.Action, task.Params)
			if err != nil {
				fmt.Println("任务执行失败!", err)
				return
			}
			fmt.Println("执行的结果为:", result)
			fmt.Println("---")
		} else {
			fmt.Println("跳过任务:", task.Name)
		}
		fmt.Println("task.Params:", task.Params)
		fmt.Println("task.Action:", task.Action)
		fmt.Println("task.Requires:", task.Requires)
		fmt.Println("task.Name:", task.Name)
		if task.Params["username"] != "" {
			fmt.Println("task.Params username:", task.Params["username"])
		}
	}
	fmt.Println("用户执行成功!~")

}

// 检查任务的依赖是否满足
func checkDependecies(requires []string) bool {
	// todo 验证参数
	return true
}
// 执行任务
func executeTask(action string, params map[string]any) (string, error) {
	switch action {
	case "validate_email_action":
		// todo 验证邮件地址的有效性
		return "ok", nil
	case "create_user_action":
		//todo 创建用户
		return "user_id", nil
	case "send_welcome_email_action":
		// 发送消息
		return "ok", nil
	default:
		return "", fmt.Errorf("未知的任务:%s", action)
	}
}
3.执行结果

我把参数信息都打印出来了

执行任务 validate_email
执行的结果为: ok
---
task.Params: map[email:user@example.com]
task.Action: validate_email_action
task.Requires: []
task.Name: validate_email
task.Params username: <nil>
执行任务 create_user
执行的结果为: user_id
---
task.Params: map[password:123456 username:yaml]
task.Action: create_user_action
task.Requires: [validate_email]
task.Name: create_user
task.Params username: yaml
执行任务 send_welcome_email
执行的结果为: ok
---
task.Params: map[body:Dear John Doe, Welcome to our platform! We are excited to 
have you on board. Best regards, The Team recipient:user@example.com subject:Wel
come to our platform!]
task.Action: send_welcome_email_action
task.Requires: [create_user]
task.Name: send_welcome_email
task.Params username: <nil>
用户执行成功!~