Home Backend Development Golang Minimalist flow programming in golang

Minimalist flow programming in golang

Jul 03, 2021 pm 02:56 PM
golang

The disadvantages brought by the traditional procedural coding method are obvious. We often have this experience. It takes a long time to suddenly pull back the code that has not been maintained for a period of time or other people's code to understand the original idea. If If there is a document or well-written annotation at this time, it may take a shorter time, but even so, many calling relationships must be confirmed repeatedly before dare to change.

The following is a piece of pseudo code describing the procedural coding method:

func A(){
    B()
    C()
}

func B(){    do something
    D()
}
func C(){    do something    
}
func D(){    do something
}
func main(){
    A()
}
Copy after login

Compare the writing method of the streaming style:

NewStream().
Next(A).
Next(B).
Next(D).
Next(C).
Go()
Copy after login

When the procedural style code call relationship is complex, the program Engineers need to act cautiously and carefully. Compared with flow-style code, it is cleaner and has a clear backbone, which has obvious advantages especially when responding to changes in requirements.

Java8 borrows lambda expressions to implement a relatively perfect streaming programming style. As a simple language, golang does not have an official streaming style package (maybe it already exists, maybe I am ignorant) ) is a bit of a pity.

I referred to the code of gorequest and implemented a relatively common streaming style package. The implementation principle is to form a task linked list, and each node saves the first node, the next node and the node. The callback function pointer that should be executed. After the streaming task is started, it will be executed one by one starting from the first node. If an exception is encountered, the streaming task will be terminated until the last one is executed, ending the task chain. Let’s take a look at the code first:

package Stream

import (    "errors"
    "fmt")/**
流式工作原理:
各个任务都过指针链表的方式组成一个任务链,这个任务链从第一个开始执行,直到最后一个
每一个任务节点执行完毕会将结果带入到下一级任务节点中。
每一个任务是一个Stream节点,每个任务节点都包含首节点和下一个任务节点的指针,
除了首节点,每个节都会设置一个回调函数的指针,用本节点的任务执行,
最后一个节点的nextStream为空,表示任务链结束。
**///定回调函数指针的类型type CB func(interface{}) (interface{}, error)//任务节点结构定义type Stream struct {    //任务链表首节点,其他非首节点此指针永远指向首节点
    firstStream *Stream    //任务链表下一个节点,为空表示任务结束
    nextStream *Stream    //当前任务对应的执行处理函数,首节点没有可执行任务,处理函数指针为空    cb CB
}/**
创建新的流
**/func NewStream() *Stream {    //生成新的节点
    stream := &Stream{}    //设置第一个首节点,为自己    //其他节点会调用run方法将从firs指针开始执行,直到next为空
    stream.firstStream = stream    //fmt.Println("new first", stream)
    return stream
}/**
流结束
arg为流初始参数,初始参数放在End方法中是考虑到初始参数不需在任务链中传递
**/func (this *Stream) Go(arg interface{}) (interface{}, error) {    //设置为任务链结束
    this.nextStream = nil    //fmt.Println("first=", this.firstStream, "second=", this.firstStream.nextStream)    //检查是否有任务节点存在,存在则调用run方法    //run方法是首先执行本任务回调函数指针,然后查找下一个任务节点,并调用run方法
    if this.firstStream.nextStream != nil {        return this.firstStream.nextStream.run(arg)
    } else {        //流式任务终止
        return nil, errors.New("Not found execute node.")
    }
}
func (this *Stream) run(arg interface{}) (interface{}, error) {    //fmt.Println("run,args=", args)    //执行本节点函数指针
    result, err := this.cb(arg)    //然后调用下一个节点的Run方法
    if this.nextStream != nil && err == nil {        return this.nextStream.run(result)
    } else {        //任务链终端,流式任务执行完毕
        return result, err
    }
}
func (this *Stream) Next(cb CB) *Stream {    //创建新的Stream,将新的任务节点Stream连接在后面
    this.nextStream = &Stream{}    //设置流式任务链的首节点
    this.nextStream.firstStream = this.firstStream    //设置本任务的回调函数指针
    this.nextStream.cb = cb    //fmt.Println("next=", this.nextStream)
    return this.nextStream
}
Copy after login

The following is an example of streaming. Here is the process from getting up in the morning to going out to work:

//起床func GetUP(arg interface{}) (interface{}, error) {
    t, _ := arg.(string)
    fmt.Println("铃铃.......", t, "###到时间啦,再不起又要迟到了!")    return "醒着的状态", nil
}//蹲坑func GetPit(arg interface{}) (interface{}, error) {
    s, _ := arg.(string)
    fmt.Println(s, "###每早必做的功课,蹲坑!")    return "舒服啦", nil
}//洗脸func GetFace(arg interface{}) (interface{}, error) {
    s, _ := arg.(string)
    fmt.Println(s, "###洗脸很重要!")    return "脸已经洗干净了,可以去见人了", nil
}//刷牙func GetTooth(arg interface{}) (interface{}, error) {
    s, _ := arg.(string)
    fmt.Println(s, "###刷牙也很重要!")    return "牙也刷干净了,可以放心的大笑", nil
}//吃早饭func GetEat(arg interface{}) (interface{}, error) {
    s, _ := arg.(string)
    fmt.Println(s, "###吃饭是必须的(需求变更了,原来的流程里没有,这次加上)")    return "吃饱饱了", nil
}//换衣服func GetCloth(arg interface{}) (interface{}, error) {
    s, _ := arg.(string)
    fmt.Println(s, "###还要增加一个换衣服的流程!")    return "找到心仪的衣服了", nil
}//出门func GetOut(arg interface{}) (interface{}, error) {
    s, _ := arg.(string)
    fmt.Println(s, "###一切就绪,可以出门啦!")    return "", nil

}
func main() {
    NewStream().
        Next(GetUP).
        Next(GetPit).
        Next(GetTooth).
        Next(GetFace).
        Next(GetEat).//需求变更了后加上的        Next(GetCloth).
        Next(GetOut).
        Go("2018年1月28日8点10分")
}
Copy after login

From the above code, streaming coding After a large task is decomposed into multiple small tasks, the style is very intuitive at the code level. You no longer have to work hard to find out which one calls which one. In addition, it is easier to change requirements. In the above example, eating breakfast is What was not implemented in the first version is that the customer said that he must eat in the morning, otherwise he would easily develop gallstones. The second version needs to be added. We need to complete the eating function and then add it to the response position. Relative to procedural coding, it is much simpler.

For more golang related technical articles, please visit the golang tutorial column!

The above is the detailed content of Minimalist flow programming in golang. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

AI Hentai Generator

AI Hentai Generator

Generate AI Hentai for free.

Hot Article

R.E.P.O. Energy Crystals Explained and What They Do (Yellow Crystal)
3 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Best Graphic Settings
3 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. How to Fix Audio if You Can't Hear Anyone
3 weeks ago By 尊渡假赌尊渡假赌尊渡假赌

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

How to safely read and write files using Golang? How to safely read and write files using Golang? Jun 06, 2024 pm 05:14 PM

Reading and writing files safely in Go is crucial. Guidelines include: Checking file permissions Closing files using defer Validating file paths Using context timeouts Following these guidelines ensures the security of your data and the robustness of your application.

How to configure connection pool for Golang database connection? How to configure connection pool for Golang database connection? Jun 06, 2024 am 11:21 AM

How to configure connection pooling for Go database connections? Use the DB type in the database/sql package to create a database connection; set MaxOpenConns to control the maximum number of concurrent connections; set MaxIdleConns to set the maximum number of idle connections; set ConnMaxLifetime to control the maximum life cycle of the connection.

Comparison of advantages and disadvantages of golang framework Comparison of advantages and disadvantages of golang framework Jun 05, 2024 pm 09:32 PM

The Go framework stands out due to its high performance and concurrency advantages, but it also has some disadvantages, such as being relatively new, having a small developer ecosystem, and lacking some features. Additionally, rapid changes and learning curves can vary from framework to framework. The Gin framework is a popular choice for building RESTful APIs due to its efficient routing, built-in JSON support, and powerful error handling.

What are the best practices for error handling in Golang framework? What are the best practices for error handling in Golang framework? Jun 05, 2024 pm 10:39 PM

Best practices: Create custom errors using well-defined error types (errors package) Provide more details Log errors appropriately Propagate errors correctly and avoid hiding or suppressing Wrap errors as needed to add context

How to save JSON data to database in Golang? How to save JSON data to database in Golang? Jun 06, 2024 am 11:24 AM

JSON data can be saved into a MySQL database by using the gjson library or the json.Unmarshal function. The gjson library provides convenience methods to parse JSON fields, and the json.Unmarshal function requires a target type pointer to unmarshal JSON data. Both methods require preparing SQL statements and performing insert operations to persist the data into the database.

Golang framework vs. Go framework: Comparison of internal architecture and external features Golang framework vs. Go framework: Comparison of internal architecture and external features Jun 06, 2024 pm 12:37 PM

The difference between the GoLang framework and the Go framework is reflected in the internal architecture and external features. The GoLang framework is based on the Go standard library and extends its functionality, while the Go framework consists of independent libraries to achieve specific purposes. The GoLang framework is more flexible and the Go framework is easier to use. The GoLang framework has a slight advantage in performance, and the Go framework is more scalable. Case: gin-gonic (Go framework) is used to build REST API, while Echo (GoLang framework) is used to build web applications.

How to solve common security problems in golang framework? How to solve common security problems in golang framework? Jun 05, 2024 pm 10:38 PM

How to address common security issues in the Go framework With the widespread adoption of the Go framework in web development, ensuring its security is crucial. The following is a practical guide to solving common security problems, with sample code: 1. SQL Injection Use prepared statements or parameterized queries to prevent SQL injection attacks. For example: constquery="SELECT*FROMusersWHEREusername=?"stmt,err:=db.Prepare(query)iferr!=nil{//Handleerror}err=stmt.QueryR

What are the common dependency management issues in the Golang framework? What are the common dependency management issues in the Golang framework? Jun 05, 2024 pm 07:27 PM

Common problems and solutions in Go framework dependency management: Dependency conflicts: Use dependency management tools, specify the accepted version range, and check for dependency conflicts. Vendor lock-in: Resolved by code duplication, GoModulesV2 file locking, or regular cleaning of the vendor directory. Security vulnerabilities: Use security auditing tools, choose reputable providers, monitor security bulletins and keep dependencies updated.

See all articles