>백엔드 개발 >Golang >golang의 미니멀리스트 흐름 프로그래밍

golang의 미니멀리스트 흐름 프로그래밍

藏色散人
藏色散人앞으로
2021-07-03 14:56:292534검색

기존 절차적 코딩 방식이 가져오는 단점은 분명합니다. 오랫동안 유지되지 않은 코드나 다른 사람의 코드가 갑자기 원래 아이디어를 이해하는 데 오랜 시간이 걸리는 경우가 있습니다. 이때 잘 작성된 문서나 주석이 있으면 시간이 덜 걸릴 수 있지만, 그럼에도 불구하고 많은 호출 관계는 감히 변경하기 전에 반복적으로 확인해야 합니다.

다음은 절차적 코딩 방법을 설명하는 의사 코드입니다.

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

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

스트리밍 스타일의 작성 스타일 비교:

NewStream().
Next(A).
Next(B).
Next(D).
Next(C).
Go()

절차적 스타일 코드의 호출 관계가 복잡할 때 프로그래머는 신중하고 신중하게 행동해야 합니다. 스트리밍 스타일과 비교하면 코드가 상대적으로 깨끗하고 백본이 명확하여 특히 요구 사항 변경을 처리할 때 분명한 이점이 있습니다.

Java8은 상대적으로 완벽한 스트리밍 프로그래밍 스타일을 구현하기 위해 람다 표현식을 차용합니다. 단순한 언어인 golang에는 아직 공식 스트리밍 스타일 패키지가 없습니다(오랫동안 존재했을 수도 있고 제가 무지할 수도 있습니다). 연민. .

gorequest 코드를 참조하여 비교적 일반적인 스트리밍 스타일 패키지를 구현했습니다. 구현 원리는 작업 연결 목록을 구성하는 것입니다. 각 노드는 첫 번째 노드, 다음 노드 및 노드가 실행해야 하는 콜백을 저장합니다. 스트리밍 작업이 시작된 후 첫 번째 노드부터 하나씩 실행되며, 예외가 발생하면 마지막 작업이 실행될 때까지 스트리밍 작업이 종료되어 작업 체인이 종료됩니다. 먼저 코드를 살펴보겠습니다.

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
}

다음은 스트리밍 예시로, 아침에 일어나서 출근하는 과정을 예시로 들었습니다.

//起床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分")
}

위 코드에서 스트리밍 코딩 스타일은 다음과 같습니다. 큰 작업을 위해 분해 여러 개의 작은 작업으로 나눈 후 코드 수준에서 매우 직관적이며 더 이상 어떤 작업이 호출되는지 찾기 위해 열심히 노력할 필요가 없습니다. 또한 요구 사항을 변경하는 것도 더 쉽습니다. 위의 예에서는 첫 번째 버전에서는 아침 식사가 구현되지 않았습니다. 고객은 아침에 식사를 해야 한다고 말했습니다. 그렇지 않으면 담석이 쉽게 생길 수 있습니다. 두 번째 버전에서는 식사 기능을 추가해야 합니다. 응답 위치로 이동합니다. 절차적 코딩에 비해 훨씬 간단합니다.

더 많은 golang 관련 기술 기사를 보려면 golang튜토리얼 칼럼을 방문하세요!

위 내용은 golang의 미니멀리스트 흐름 프로그래밍의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 cnblogs.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제