Go语言学习13-常见软件架构的实现

Go语言学习13-常见软件架构的实现

架构模式

An architectural pattern is a general, reusable solution to a commonly occurring problem in software architectural within a given context. ——wikipedia

Pipe-Filter 架构

Pipe-Filter 模式
  • 非常适合于数据处理及数据分析系统

  • Filter 封装数据处理的功能

  • 松耦合: Filter只跟数据(格式) 耦合

  • Pipe用于连接 Filter 传递数据或者在异步处理过程中缓冲数据流

    进程内同步调用时, pipe 演变为数据在方法调用间传递

Filter和组合模式

示例
// filter.go
// Package pipefilter is to define the interfaces
// and the structures for pipe-filter style implementation
package pipefilter

// Request is the input of the filter
type Request interface{}

// Response is the output of the filter
type Response interface{}

// Filter interface is the definition of the data processing components
// Pipe-Filter structure
type Filter interface {
	Process(data Request) (Response, error)
}

// split_filter.go
package pipefilter

import (
	"errors"
	"strings"
)

var SplitFilterWrongFormatError = errors.New("input data should be string")

type SplitFilter struct {
	delimiter string
}

func NewSplitFilter(delimiter string) *SplitFilter {
	return &SplitFilter{delimiter}
}

func (sf *SplitFilter) Process(data Request) (Response, error) {
	str, ok := data.(string) // 检查数据格式/类型, 是否可以处理
	if !ok {
		return nil, SplitFilterWrongFormatError
	}
	parts := strings.Split(str, sf.delimiter)
	return parts, nil
}

// to_int_filter.go
package pipefilter

import (
	"errors"
	"strconv"
)

var ToIntFilterWrongFormatError = errors.New("input data should be []string")

type ToIntFilter struct {
}

func NewToIntFilter() *ToIntFilter {
	return &ToIntFilter{}
}

func (tif *ToIntFilter) Process(data Request) (Response, error) {
	parts, ok := data.([]string)
	if !ok {
		return nil, ToIntFilterWrongFormatError
	}
	ret := []int{}
	for _, part := range parts {
		s, err := strconv.Atoi(part)
		if err != nil {
			return nil, err
		}
		ret = append(ret, s)
	}
	return ret, nil
}

// sum_filter.go
package pipefilter

import "errors"

var SumFilterWrongFormatError = errors.New("input data should be []int")

type SumFilter struct {
}

func NewSumFilter() *SumFilter {
	return &SumFilter{}
}

func (sf *SumFilter) Process(data Request) (Response, error) {
	elems, ok := data.([]int)
	if !ok {
		return nil, SumFilterWrongFormatError
	}
	ret := 0
	for _, elem := range elems {
		ret += elem
	}
	return ret, nil
}

// straight_pipeline.go
package pipefilter

// StraightPipeline is composed of the filters, and the filters are piled as a straight line.
type StraightPipeline struct {
	Name    string
	Filters *[]Filter
}

// NewStraightPipeline create a new StraightPipelineWithWallTime
func NewStraightPipeline(name string, filters ...Filter) *StraightPipeline {
	return &StraightPipeline{
		Name:    name,
		Filters: &filters,
	}
}

// Process is to process the coming data by the pipeline
func (f *StraightPipeline) Process(data Request) (Response, error) {
	var ret interface{}
	var err error
	for _, filter := range *f.Filters {
		ret, err = filter.Process(data)
		if err != nil {
			return ret, err
		}
		data = ret
	}
	return ret, err
}

Micro Kernel架构

  • 特点
    • 易于扩展
    • 错误隔离
    • 保持架构一致性
  • 要点
    • 内核包含公共流程或通用逻辑
    • 将可变或可扩展部分规划为扩展点
    • 抽象扩展点行为, 定义接口
    • 利用插件进行扩展
示例

package microkernel

import (
	"context"
	"errors"
	"fmt"
	"strings"
	"sync"
)

const (
	Waiting = iota
	Running
)

var WrongStateError = errors.New("can not take the operation in the current state")

type CollectorsError struct {
	CollectorsErrors []error
}

func (ce CollectorsError) Error() string {
	var strs []string
	for _, err := range ce.CollectorsErrors {
		strs = append(strs, err.Error())
	}
	return strings.Join(strs, ";")
}

type Event struct {
	Source  string
	Content string
}

type EventReceiver interface {
	OnEvent(evt Event)
}

type Collector interface {
	Init(evtReceiver EventReceiver) error
	Start(agtCtx context.Context) error
	Stop() error
	Destroy() error
}

type Agent struct {
	collectors map[string]Collector
	evtBuf     chan Event
	cancel     context.CancelFunc
	ctx        context.Context
	state      int
}

func (agt *Agent) EventProcessGroutine() {
	var evtSeg [10]Event
	for {
		for i := 0; i < 10; i++ {
			select {
			case evtSeg[i] = <-agt.evtBuf:
			case <-agt.ctx.Done():
				return
			}
		}
		fmt.Println(evtSeg)
	}
}

func NewAgent(sizeEvtBuf int) *Agent {
	agt := Agent{
		collectors: map[string]Collector{},
		evtBuf:     make(chan Event, sizeEvtBuf),
		state:      Waiting,
	}

	return &agt
}

func (agt *Agent) RegisterCollector(name string, collector Collector) error {
	if agt.state != Waiting {
		return WrongStateError
	}
	agt.collectors[name] = collector
	return collector.Init(agt)
}

func (agt *Agent) startCollectors() error {
	var err error
	var errs CollectorsError
	var mutex sync.Mutex

	for name, collector := range agt.collectors {
		go func(name string, collector Collector, ctx context.Context) {
			defer func() {
				mutex.Unlock()
			}()
			err = collector.Start(ctx)
			mutex.Lock()
			if err != nil {
				errs.CollectorsErrors = append(errs.CollectorsErrors,
					errors.New(name+":"+err.Error()))
			}
		}(name, collector, agt.ctx)
	}
	if len(errs.CollectorsErrors) == 0 {
		return nil
	}
	return errs
}

func (agt *Agent) stopCollectors() error {
	var err error
	var errs CollectorsError
	for name, collector := range agt.collectors {
		if err = collector.Stop(); err != nil {
			errs.CollectorsErrors = append(errs.CollectorsErrors,
				errors.New(name+":"+err.Error()))
		}
	}
	if len(errs.CollectorsErrors) == 0 {
		return nil
	}
	return errs
}

func (agt *Agent) destroyCollectors() error {
	var err error
	var errs CollectorsError
	for name, collector := range agt.collectors {
		if err = collector.Destroy(); err != nil {
			errs.CollectorsErrors = append(errs.CollectorsErrors,
				errors.New(name+":"+err.Error()))
		}
	}
	if len(errs.CollectorsErrors) == 0 {
		return nil
	}
	return errs
}

func (agt *Agent) Start() error {
	if agt.state != Waiting {
		return WrongStateError
	}
	agt.state = Running
	agt.ctx, agt.cancel = context.WithCancel(context.Background())
	go agt.EventProcessGroutine()
	return agt.startCollectors()
}

func (agt *Agent) Stop() error {
	if agt.state != Running {
		return WrongStateError
	}
	agt.state = Waiting
	agt.cancel()
	return agt.stopCollectors()
}

func (agt *Agent) Destroy() error {
	if agt.state != Waiting {
		return WrongStateError
	}
	return agt.destroyCollectors()
}

func (agt *Agent) OnEvent(evt Event) {
	agt.evtBuf <- evt
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/470773.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

taro之Picker,PickerView基础用法

1.Picker 直接上代码 import Taro,{Component} from "tarojs/taro"; import {View,Picker} from tarojs/components import { AtIcon } from taro-ui import { putKey } from /src/utils/storage-utilsclass AgriculturePolicy extends Component{constructor (prop…

su: authentication failure 解决方法

产生问题的原因&#xff1a;使用su和sudo是有区别的&#xff0c;root的密码可能是原始的密码&#xff0c;你现在用户的密码大概率是更改过的 解决办法&#xff1a; 在Linux上切换root时&#xff0c;密码正确。。但提示&#xff1a;su: authentication failure ->sudo pa…

统计学基础概念和在AI中的应用

基本概念 统计学是一门研究数据收集、分析、解释和展示的科学&#xff0c;它提供了一套方法论&#xff0c;用于理解数据并从数据中得出结论。统计学在各个领域都有应用&#xff0c;包括经济学、医学、工程学、社会科学等。以下是统计学的一些基本概念&#xff1a; 描述性统计…

wireshark数据捕获实验简述

Wireshark是一款开源的网络协议分析工具&#xff0c;它可以用于捕获和分析网络数据包。是一款很受欢迎的“网络显微镜”。 实验拓扑图&#xff1a; 实验基础配置&#xff1a; 服务器&#xff1a; ip:172.16.1.88 mask:255.255.255.0 r1: sys sysname r1 undo info enable in…

B站python爬虫课程笔记(Q16-)

下面是学习的网址&#xff1a; ​​​​​​【Python爬虫】 16、捕捉异常try&except语句的一些问题 1&#xff09;一些常见的异常类型 IndexError索引错误ZeroDivisionError除零错误FileNotFindError找不到文件错误TypeError类型错误KeyError键错误ValueError值错误Ind…

代理IP品质对Tik Tok代理的重要性

随着Tik Tok的迅速崛起&#xff0c;越来越多的人开始关注如何透过Tik Tok进行行销和推广。其中&#xff0c;使用Tik Tok代理程式是常见的方法。 然而&#xff0c;在选择和使用代理时&#xff0c;IP品质是一个不可忽视的因素。本文将探讨IP品质对Tik Tok代理的重要性&#xff0…

【征稿进行时|见刊、检索快速稳定】2024年区块链、物联网与复合材料与国际学术会议 (ICBITC 2024)

【征稿进行时|见刊、检索快速稳定】2024年区块链、物联网与复合材料与国际学术会议 (ICBITC 2024) 大会主题: (主题包括但不限于, 更多主题请咨询会务组苏老师) 区块链&#xff1a; 区块链技术和系统 分布式一致性算法和协议 块链性能 信息储存系统 区块链可扩展性 区块…

Springboot笔记-04

1.PropertySource&ImportResource&Bean PropertySource&#xff1a;加载指定的配置文件&#xff0c;只能用于properties文件&#xff0c;不支持yml文件&#xff1b; 以person为例子: ConfigurationProperties:告诉springboot将本类中所有属性和配制文件相关的配制进行…

docker入门(一)—— docker概述

docker 概述 docker 官网&#xff1a;http://www.docker.com 官网文档&#xff1a; https://docs.docker.com/get-docker/ Docker Hub官网&#xff1a;https://hub.docker.com &#xff08;仓库&#xff09; 什么是 docker docker 是一个开源的容器化平台&#xff0c;可以…

ARM Cortex-R82处理器在压缩SSD场景的应用

ScaleFlux公司宣布在其下一代企业级SSD控制器产品线中采用Arm公司的Cortex-R82处理器。这一决策旨在应对企业环境中对高带宽存储解决方案日益增长的需求&#xff0c;并通过提升数据传输速度和效率来满足市场期待。 Arm Cortex-R82处理器是Arm公司迄今为止性能最强的实时处理器…

maven手动上传的第三方包 打包项目报错 Could not find xxx in central 解决办法

背景: 在Maven私服手动上传了第三方的jar包, 只有jar包, 没有pom文件, 项目在ide中可以正常编译启动,但打包报错无法找到jar包 解决办法: 上传jar包的时候, 点击生成pom. 则打包的时候不会报错

2.28线程

注意被抢占时是返回原队列&#xff0c;优先级不变。越往下优先级越小。往下没有优先级时&#xff0c;在最低的优先级队列里循环 到达了不一定会被服务&#xff0c;会进入就绪态进行等待 。核心等式就是周转时间运行时间等待时间&#xff0c;带权就是周转/运行&#xff0c; 随着…

wayland(xdg_wm_base) + egl + opengles 使用 Assimp 加载带光照信息的材质文件Mtl 实现光照贴图的最简实例(十七)

文章目录 前言一、3d 立方体 model 属性相关文件1. cube1.obj2. cube1.Mtl3. 纹理图片 cordeBouee4.jpg二、实现光照贴图的效果1. 依赖库和头文件1.1 assimp1.2 stb_image.h2. egl_wayland_obj_cube1.cpp3. Matrix.h 和 Matrix.cpp4. xdg-shell-client-protocol.h 和 xdg-shell…

无人机助力违法毒品种植,基于轻量级YOLOv5n开发构建无人机航拍场景下的农村田园场景下非法种植罂粟花检测预警识别系统

打击毒品人人有责&#xff0c;毒品带来的危害是人尽皆知的&#xff0c;我们不仅自身要严厉拒绝接触任何形式的毒品&#xff0c;更要言传身教告诫他人不要与任何形式的任何渠道的毒品有关联&#xff0c;但是在实际生活中&#xff0c;在一些偏远的乡村、田园、山丘、村落等地方&a…

网络安全的几个关键领域

网络安全是一个复杂且多维度的领域&#xff0c;涵盖了多个关键领域&#xff0c;涉及到信息保护、网络防护、应用安全、用户教育以及物理安全等多个方面。这些关键领域相互交织&#xff0c;共同构成了网络安全这一宏大且细致入微的领域。 今天德迅云安全就分享下网络安全的几个…

STP环路避免实验(华为)

思科设备参考&#xff1a;STP环路避免实验&#xff08;思科&#xff09; 一&#xff0c;技术简介 Spanning Tree Protocol&#xff08;STP&#xff09;&#xff0c;即生成树协议&#xff0c;是一种数据链路层协议。主要作用是防止二层环路&#xff0c;并自适应网络变化和故障…

【RabbitMQ | 第一篇】消息队列基础知识

文章目录 1.消息队列基础知识1.1什么是消息队列&#xff1f;1.2消息队列有什么用&#xff1f;&#xff08;结合项目说&#xff09;1.2.1异步处理1.2.2削峰/限流1.2.3降低系统耦合性1.2.4实现分布式事务 1.3消息队列的缺点1.4JMS和AMQP1.4.1 JMS的两种消息模型&#xff08;1&…

Python 自然语言处理库之stanza使用详解

概要 在自然语言处理(NLP)领域,Python Stanza 库是一个备受推崇的工具,它提供了强大的功能和易用的接口,帮助开发者处理文本数据、进行语言分析和构建NLP应用。本文将深入探讨 Stanza 库的特性、用法,并通过丰富的示例代码展示其在实际项目中的应用。 Stanza 简介 Stan…

【Oracle】Linux——Centos7安装Oracle12c

安装前拍快照、安装前拍快照、安装前拍快照 目录 安装前拍快照、安装前拍快照、安装前拍快照1.下载Oracle12C安装包2.基本环境搭建2.1创建用户和组2.2创建oralce安装目录,oracle用户分配目录权限2.3上传安装包 3.系统参数配置及服务器设置3.1依赖安装3.2内核参数配置3.3配置完成…

swagger3快速使用

目录 &#x1f37f;1.导入依赖 &#x1f32d;2.添加配置文件 &#x1f9c2;3.添加注解 &#x1f96f;4.访问客户端 1.导入依赖 引入swagger3的依赖包 <dependency><groupId>io.springfox</groupId><artifactId>springfox-boot-starter</artif…
最新文章