当前位置: 首页 > news >正文

Go有限状态机实现和实战

Go有限状态机实现和实战

在这里插入图片描述

有限状态机

什么是状态机

有限状态机(Finite State Machine, FSM)是一种用于建模系统行为的计算模型,它包含有限数量的状态,并通过事件或条件实现状态之间的转换。FSM的状态数量是有限的,因此称为有限状态机

关于有限的解释:也就是被描述的事物的状态的数量是有限的,例如开关的状态只有“开”和“关”两个;灯的状态只有“亮”和“灭”等等。

特点

状态机的状态数量是有限的,在确定的状态下,给定特定的事件,系统会转换到明确的下一个状态。

作用

使用状态机来表达状态的流转,会使语义会更加清晰,会增强代码的稳定性可控性可维护性

适用场景

面对复杂的状态流转都可以使用状态机来实现

状态机是描述系统行为的强大工具,其核心是状态、事件和状态转换。它的清晰逻辑和确定性使其在复杂流程控制、嵌入式设备、游戏开发等领域非常适用,为系统开发提供了简洁、高效的解决方案。

状态机核心概念

状态机有四个核心概念,这是所有状态机的基础

  • State:状态。一个状态机至少要包含两个状态。
  • Transition:过渡。也就是从一个状态变化为另一个状态(即状态转移)。
  • Event:事件。事件会触发状态转移,也就是状态转移的条件
  • Action:动作。事件发生以后要执行动作,即事件处理

有限状态机的工作原理如图所示,发生事件(event)后,根据当前状态(cur_state) ,决定执行的动作(action),并设置下一个状态(next_state)。

Go状态机设计

我们根据上面的概念设计一个状态机

示例:自动贩卖机状态机

在这里插入图片描述

package mainimport ("fmt"
)// 定义状态类型
type State string
//  1.State:状态。一个状态机至少要包含两个状态。
const (StateIdle     State = "Idle(空闲)"     // 空闲状态StateCoin     State = "Coin(投币)"     // 投币状态StateItem     State = "Item(选择商品)"     // 选择商品状态
)// 定义事件类型
type Event string
// 2.Event:事件。事件会触发状态转移,也就是状态转移的条件。
const (EventInsertCoin  Event = "InsertCoin"  // 投币事件EventSelectItem  Event = "SelectItem"  // 选择商品事件EventDispense    Event = "Dispense"    // 出货事件
)// 定义状态转移 
// 3.Transition:过渡。也就是从一个状态变化为另一个状态(即状态转移)。
const(Transitions = map[State]map[Event]State{StateIdle: {EventInsertCoin: StateCoin,},StateCoin: {EventSelectItem: StateItem,},StateItem: {EventDispense: StateIdle,},}
)// 定义状态机结构体
type FSM struct {currentState Statetransitions  map[State]map[Event]State // 状态-事件转换映射
}
// 创建状态机
func NewFSM() *FSM {return &FSM{currentState: StateIdle, // 初始状态transitions: Transitions,}
}// 处理事件并进行状态转换
// 4.Action:动作。事件发生以后要执行动作,即事件处理。
func (fsm *FSM) HandleEvent(event Event) {nextState, ok := fsm.transitions[fsm.currentState][event]if !ok {fmt.Printf("事件 %s 无法从状态 %s 转换\n", event, fsm.currentState)return}fmt.Printf("从状态 %s 转到状态 %s 通过事件 %s\n", fsm.currentState, nextState, event)fsm.currentState = nextState
}// 获取当前状态
func (fsm *FSM) CurrentState() State {return fsm.currentState
}func main() {fsm := NewFSM()// 测试状态机fsm.HandleEvent(EventInsertCoin)  // 投币,进入选择商品状态fsm.HandleEvent(EventSelectItem)  // 选择商品,准备出货fsm.HandleEvent(EventDispense)    // 出货,返回初始状态
}

运行结果

从状态 Idle(空闲) 转到状态 Coin(投币) 通过事件 InsertCoin(投币事件)
从状态 Coin(投币) 转到状态 Item(选择商品) 通过事件 SelectItem(选择商品事件)
从状态 Item(选择商品) 转到状态 Idle(空闲) 通过事件 Dispense(出货事件)

代码解释:

  • State(对应State) :定义了有限状态机的状态和事件。状态有 Idle、Coin、Item 和 Dispense。

  • Event(对应Event):事件有 InsertCoin、SelectItem、Dispense 和 ReturnCoins。

  • Transitions(对应Transition):定义了状态转移规则,即当某个状态收到某个事件时,会转移到另一个状态。

  • HandleEvent(对应Action):该方法处理事件,并根据当前状态和事件查找下一个状态。如果找不到对应的转换,则表示事件在当前状态下无效。

  • FSM 结构体:负责存在状态机的信息,FSM 包含当前状态和状态转换规则。transitions 映射定义了每个状态在不同事件下的下一个状态。

事件处理

我们可以将Action进行拓展,对状态机进行扩展,比如添加日志记录、超时处理、错误处理、通知等。
在这里插入图片描述
具体实现我们可以参考下面生产使用的代码。

生产使用

上面的代码是一个简单的状态机,实际使用中,需要考虑更多的因素,比如状态的初始化、状态的持久化、状态的恢复、状态的监听等。

  1. 状态的初始化:在创建状态机时,需要初始化当前状态,并设置初始状态的转换规则。

  2. 状态的持久化:在状态机中,需要将状态的转换记录持久化到数据库或者文件中,以便在系统重启时恢复状态。

  3. 状态的恢复:在系统重启时,需要根据持久化的状态记录恢复状态机。

  4. 状态的监听:在状态机中,需要监听状态的变化,以便在状态发生变化时进行通知。

  5. 状态的校验:在状态机中,需要校验状态的转换是否合法,比如不允许从空闲状态直接进入选择商品状态。

  6. 状态的错误处理:在状态机中,需要处理状态转换过程中出现的错误,比如转换失败、超时等。

  7. 状态的日志记录:在状态机中,需要记录状态的转换记录,以便后续分析

生产上我们可以使用 github.com/looplab/fsm
这个库提供了一些常用的功能,如状态的初始化、状态的持久化、状态的恢复、状态的监听等。

package fsm_demoimport ("context""fmt""testing""github.com/looplab/fsm"
)// 定义状态类型
type State string// 1.State:状态。一个状态机至少要包含两个状态。
const (StateIdle State = "Idle(空闲)"   // 空闲状态StateCoin State = "Coin(投币)"   // 投币状态StateItem State = "Item(选择商品)" // 选择商品状态
)// 定义事件类型
type Event string// 2. Event:事件。事件会触发状态转移,也就是状态转移的条件。
const (EventInsertCoin Event = "InsertCoin" // 投币事件EventSelectItem Event = "SelectItem" // 选择商品事件EventDispense   Event = "Dispense"   // 出货事件
)type FSM struct {Id  string   // 数据idFSM *fsm.FSM // 状态机
}func NewFSM(id string) *FSM {d := &FSM{Id: id,}d.FSM = fsm.NewFSM(string(StateIdle),// 3. Transition 定义转换fsm.Events{{Name: string(EventInsertCoin), Src: []string{string(StateIdle)}, Dst: string(StateCoin)},{Name: string(EventSelectItem), Src: []string{string(StateCoin)}, Dst: string(StateItem)},{Name: string(EventDispense), Src: []string{string(StateItem)}, Dst: string(StateIdle)},},// 4. Action 定义动作fsm.Callbacks{"before_event": func(ctx context.Context, e *fsm.Event) {fmt.Println(e.Args[0])e.FSM.SetMetadata("error", "error")fmt.Println("before_event 通用(可以记录日志)", e.Event, e.FSM.Current())e.Err = fmt.Errorf("error")e.Cancel()// e.Event = "error"},fmt.Sprintf("before_%s", EventInsertCoin): func(ctx context.Context, e *fsm.Event) {fmt.Println("before", EventInsertCoin, e.Event, e.FSM.Current())// e.Err = fmt.Errorf("error")},fmt.Sprintf("enter_%s", StateCoin): func(ctx context.Context, e *fsm.Event) {fmt.Println("enter", StateCoin, e.Event, e.FSM.Current())// e.Err = fmt.Errorf("error")},"enter_state": func(_ context.Context, e *fsm.Event) { d.enterState(e) },fmt.Sprintf("after_%s", EventInsertCoin): func(ctx context.Context, e *fsm.Event) {fmt.Println("after", EventInsertCoin, e.Event, e.FSM.Current())// e.Err = fmt.Errorf("error")},"after_event": func(_ context.Context, e *fsm.Event) {fmt.Println(e.FSM.Metadata("error"))fmt.Println("after_event 通用(可以记录日志)", e.Event, e.FSM.Current())},},)return d
}// 更新状态
func (d *FSM) enterState(e *fsm.Event) {// called after entering all states// todo 更新数据库,持久化fmt.Println("enter_state 通用 更新数据库", e.FSM.Current())
}func Test_Main(t *testing.T) {plan := NewFSM(string(StateIdle))err := plan.FSM.Event(context.Background(), string(EventInsertCoin), 1)if err != nil {fmt.Println(err)}fmt.Println(plan.FSM.Current())err = plan.FSM.Event(context.Background(), string(EventSelectItem))if err != nil {fmt.Println(err)}fmt.Println(plan.FSM.Current())err = plan.FSM.Event(context.Background(), string(EventDispense))if err != nil {fmt.Println(err)}fmt.Println(plan.FSM.Current())err = plan.FSM.Event(context.Background(), string(EventDispense))if err != nil {fmt.Println(err)}fmt.Println(plan.FSM.Current())
}

使用去起来和我们自己写的代码类似,也是定义 State ,Evnent,Transition,Action。这个是所有FSM通用的。

这个库可以很灵活的配置事件处理。可以配置很多前置和后置事件。

// 1. before_<EVENT> - 在名为 <EVENT> 的事件之前调用
// 2. before_event - 在所有事件之前调用
// 3. leave_<OLD_STATE> - 在离开 <OLD_STATE> 之前调用
// 4. leave_state - 在离开所有状态之前调用
// 5. enter_<NEW_STATE> - 在进入 <NEW_STATE> 之后调用
// 6. enter_state - 在进入所有状态之后调用
// 7. after_<EVENT> - 在名为 <EVENT> 的事件之后调用
// 8. after_event - 在所有事件之后调用

而且错误处理机制也很完善。使用这个库后大家可以把更多的精力关注业务层。

参考:

https://github.com/looplab/fsm

https://www.cnblogs.com/huageyiyangdewo/p/17351310.html

相关文章:

Go有限状态机实现和实战

Go有限状态机实现和实战 有限状态机 什么是状态机 有限状态机&#xff08;Finite State Machine, FSM&#xff09;是一种用于建模系统行为的计算模型&#xff0c;它包含有限数量的状态&#xff0c;并通过事件或条件实现状态之间的转换。FSM的状态数量是有限的&#xff0c;因此称…...

使用torch模拟 BMM int8量化计算。

使用torch模型BMM int8计算。 模拟&#xff1a;BMM->softmax->BMM 计算流程 import torch import numpy as np torch.manual_seed(777) def int8_quantize_per_token(x: torch.Tensor, axis: int -1, attnsFalse):if x.dtype ! torch.float32:x x.type(torch.float32)…...

vue3的watch一次性监听多个值用法

vue3的watch一次性监听多个值 1、监听单个值 watch(() > route.params.keyword, (newValue, oldValue) > {console.log(监听值变化, newVal, oldVal)state.a newValue});2、监听多个值 watch(() > [route.params.id, route.params.keyword], (newValue, oldValue) &g…...

【one-api和ollama结合使用】

将Ollama接入one-api one-api是一个开源AI中间件服务&#xff0c;可以聚合各家大模型API&#xff0c;比如OpenAI、ChatGLM、文心一言等&#xff0c;聚合后提供统一的OpenAI调用方法。举个例子&#xff1a;ChatGLM和文心一言的API调用方法并不相同&#xff0c;one-api可以对其进…...

Oracle PDB的开启和关闭

[生产环境关闭与开启Oracle PDB] 【运维场景】 在运维Oracle PDB的时候经常要开启和关闭PDB&#xff0c;对关闭和开启PDB的操作要非常熟悉。 【操作方法】 1. PDB的打开与关闭 关闭和开启DB的时候要看DB的警告日志&#xff0c;日志位置&#xff08;在Oracle用户下查看&…...

十一、动态构建UI元素

装饰器Builder 装饰器BuilderParam <font style"color:rgba(0, 0, 0, 0.9);">BuilderParam</font> 该装饰器用于声明任意UI描述的一个元素&#xff0c;类似slot占位符。 链接 简而言之&#xff1a;就是自定义组件允许外部传递 UI // SonCom 的实现略…...

智能时代的基石:神经网络

智能时代的基石&#xff1a;神经网络 第一节&#xff1a;神经网络简介 课程目标 本节课程旨在全面介绍神经网络的基本概念、结构以及其在历史发展中的重要里程碑。通过深入理解神经网络的工作原理和演变过程&#xff0c;学员将能够掌握神经网络在现实世界中的多种应用&#…...

VScode配置GIT

在Visual Studio Code&#xff08;VSCode&#xff09;中检测不到已安装的Git可以通过以下步骤来解决‌&#xff1a; ‌确认Git是否正确安装‌&#xff1a;首先&#xff0c;确保在计算机上正确安装了Git。可以通过打开命令行窗口并输入git --version来检查是否能够显示Git的版本…...

【CSS】css 如何实现固定宽高比

今天和同事讨论这个问题&#xff0c;一时间还想不到了&#xff0c;于是学习了下&#xff0c;就顺便当个记录吧 要在CSS中实现固定宽高比&#xff0c;有两种主要的方法可以选择。一种是使用新的aspect-ratio属性&#xff0c;另一种是利用padding技巧。随着现代浏览器对aspect-ra…...

使用webrtc-streamer查看实时监控

摄像头配置&#xff08;海康摄像头为例&#xff09; 摄像头视频编码应改成H264格式 webrtc-streamer下载 webrtc-streamer下载地址 下载后解压出来双击运行&#xff0c;端口默认8000 VUE2项目引入文件 在项目静态文件“public”中需引入两个js文件“webrtcstreamer.js”与“…...

ansible部署nginx:1个简单的playbook脚本

文章目录 hosts--ventoryroles执行命令 使用ansible向3台centos7服务器上安装nginx hosts–ventory [rootstand playhook1]# cat /root/HOSTS # /root/HOSTS [webservers] 192.168.196.111 ansible_ssh_passpassword 192.168.196.112 ansible_ssh_passpassword 192.168.196.1…...

Ubuntu安装Gitlab详细图文教程

1、环境准备 1.1、Ubuntu环境 Ubuntu24.04Sever版安装教程 1.2、更新系统 sudo apt update -y sudo apt-get update sudo apt-get upgrade 2、安装Nginx 2.1 安装nginx # 安装 apt install nginx -y 2.2 修改nginx配置⽂件 # 修改nginx配置 vim /etc/nginx/si…...

前端面试准备问题2

1.防抖和节流分别是什么&#xff0c;应用场景 防抖&#xff1a;在事件被触发后&#xff0c;只有在指定的延迟时间内没有再次触发&#xff0c;才执行事件处理函数。 在我的理解中&#xff0c;简单的说就是在一个指定的时间内&#xff0c;仅触发一次&#xff0c;如果有多次重复触…...

uni-app之web-view组件 postMessage 通信【跨端开发系列】

&#x1f517; uniapp 跨端开发系列文章&#xff1a;&#x1f380;&#x1f380;&#x1f380; uni-app 组成和跨端原理 【跨端开发系列】 uni-app 各端差异注意事项 【跨端开发系列】uni-app 离线本地存储方案 【跨端开发系列】uni-app UI库、框架、组件选型指南 【跨端开…...

IntelliJ IDEA 使用技巧与插件推荐

目录 常用使用技巧 1. 使用快捷键提升开发效率 2. 多光标编辑 3. 代码自动补全 4. 使用 Find Action 快速执行操作 5. 集成版本控制系统&#xff08;VCS&#xff09; 6. 快速查看代码文档 推荐插件 1. Lombok Plugin 2. Rainbow Brackets 3. Key Promoter X 4. Chec…...

zookeeper基础命令详解

zookeeper基础命令详解目录 文章目录 zookeeper基础命令详解目录一、列出所有基础命令 一、列出所有基础命令 先启动一个zookeeper客户端连接zookeeper&#xff0c;如果还没有启动zookeeper集群的参考本文启动之后再做后续操作。 https://blog.csdn.net/weixin_42924400/artic…...

2025周易算命网站搭建详细方法+源码选择php环境的配置

以下是一个详细的搭建教程&#xff0c;包括网站分类、环境配置、程序设计和功能实现。 1. 环境准备 1.1 服务器选择 操作系统: Linux&#xff08;推荐使用Ubuntu或CentOS&#xff09;Web服务器: Nginx数据库: MySQLPHP版本: 7.4.x&#xff08;确保小于8.0&#xff09; 1.2 安…...

16:00面试,16:06就出来了,问的问题有点变态。。。

从小厂出来&#xff0c;没想到在另一家公司又寄了。 到这家公司开始上班&#xff0c;加班是每天必不可少的&#xff0c;看在钱给的比较多的份上&#xff0c;就不太计较了。没想到5月一纸通知&#xff0c;所有人不准加班&#xff0c;加班费不仅没有了&#xff0c;薪资还要降40%…...

《杨辉三角》

题目描述 给出 n(1≤n≤20)n(1≤n≤20)&#xff0c;输出杨辉三角的前 nn 行。 如果你不知道什么是杨辉三角&#xff0c;可以观察样例找找规律。 输入格式 无 输出格式 无 输入输出样例 输入 #1复制 6 输出 #1复制 1 1 1 1 2 1 1 3 3 1 1 4 6 4 1 1 5 10 10 5 1 C语言…...

2024年03月中国电子学会青少年软件编程(Python)等级考试试卷(五级)答案 + 解析

青少年软件编程(Python)等级考试试卷(五级) 分数:100 题数:38 一、单选题(共25题,共50分) 1. 以下代码的输出结果是?( ) nums = list(range(100, 201)) print...

【游戏设计原理】7 - 加德纳的多元智能理论

虽然多元智能理论是对认知方式的分类&#xff0c;但它也可以为游戏设计提供丰富的思路和策略&#xff0c;帮助设计师创建更具吸引力、包容性和多样性的游戏。通过理解不同玩家的认知方式和优势&#xff0c;我们可以更精准地设计游戏的元素和玩法&#xff0c;使其能够吸引广泛的…...

Jackson @JsonProperty 注解

1. 概述 Jackson 是一个流行的Java库&#xff0c;用于将Java对象转换为JSON格式以及从JSON反序列化回Java对象。一种常见的需求是在序列化为JSON或从JSON反序列化时自定义字段的命名。Jackson 的 JsonProperty 注解正好满足了这一需求。 JsonProperty 注解概览 JsonProperty…...

【数据结构——栈与队列】链栈的基本运算(头歌实践教学平台习题)【合集】

目录&#x1f60b; 任务描述 相关知识 测试说明 我的通关代码: 测试结果&#xff1a; 任务描述 本关任务&#xff1a;编写一个程序实现链栈的基本运算。 相关知识 为了完成本关任务&#xff0c;你需要掌握&#xff1a; 初始化栈、销毁栈、判断栈是否为空、进栈、出栈、取栈…...

数据库乐观锁和悲观锁、redis分布式锁使用场景

前言 最近发现我们同事&#xff0c;但凡需要加锁的地方都用的是分布式锁。而且我们的后台系统&#xff0c;并没有什么并发量&#xff0c;而且还是单体应用。我真的有点怀疑我的同事不太清楚数据乐观锁、悲观锁和redis分布式的使用场景。 请今天就说一下各种锁的应用场景吧。 …...

React的状态管理库-Redux

核心思想&#xff1a;单一数据源、状态是只读的、以及使用纯函数更新状态。 组成部分 Store&#xff08;存储&#xff09; 应用的唯一状态容器&#xff0c;存储整个应用的状态树,使用 createStore() 创建。 getState()&#xff1a;获取当前状态。dispatch(action)&#xff…...

《自制编译器》--青木峰郎 -读书笔记 编译hello

在该书刚开始编译hello.cb时就遇到了问题。 本人用的是wsl&#xff0c;环境如下&#xff0c; 由于是64位&#xff0c;因此根据书中的提示&#xff0c;从git上下载了64位的cb编译器 cbc-64bit 问题一: 通过如下命令编译时,总是报错。 cbc -Wa,"--32" -Wl,"-…...

XSS(跨站攻击)

XSS漏洞&#xff08;跨站脚本&#xff09; 1.XSS 漏洞简介 ​ XSS又叫CSS&#xff08;Cross Site Script&#xff09;跨站脚本攻击是指恶意攻击者往Web页面里插入恶意Script代码&#xff0c;当用户浏览该页之时&#xff0c;嵌入其中Web里面的Script代码会被执行&#xff0c;从…...

华为自反ACL实验

一、实验背景 做这个实验的原因是最近公司里上了三台小程序服务器&#xff0c;由于三台服务器的端口都映射出去了&#xff0c;领导要求A网段的三台服务器不能访问内网B&#xff0c;C网段&#xff0c;同时B、C网段内网用户可以访问A段的94、95、96服务器&#xff1b; 也就是PC4\…...

MyBatisPlus实现多表查询

在MyBatisPlus中实现多表查询&#xff0c;主要有以下几种方法&#xff1a; 使用注解进行多表查询&#xff1a; 你可以在Mapper接口中使用Select注解来编写SQL查询语句&#xff0c;实现多表查询。例如&#xff0c;如果你想根据用户ID查询用户信息和对应的区域名称&#xff0c;可…...

【人工智能-中级】循环神经网络(RNN)与Transformer在自然语言处理中的进阶应用

循环神经网络(RNN)与Transformer在自然语言处理中的进阶应用 自然语言处理(NLP)是人工智能领域中的重要分支,其主要任务是使计算机能够理解、生成和处理人类语言。近年来,循环神经网络(RNN)和Transformer模型已成为NLP领域的两大核心技术。本文将探讨这两类模型在自然…...

ZED相机应用

下载SDK wget https://stereolabs.sfo2.cdn.digitaloceanspaces.com/zedsdk/3.6/ZED_SDK_Ubuntu18_cuda11.5_v3.6.5.run 安装 ./ZED_SDK_Ubuntu18_cuda11.5_v3.6.5.run skip_python 测试 cd /usr/local/zed/tools ls ZED_Calibration ZED_Depth_Viewer ZED_Diagnostic ZED_E…...

大模型呼入机器人如何赋能呼叫中心?(转)

大模型呼入机器人如何赋能呼叫中心&#xff1f;(转) 原作者&#xff1a;开源呼叫中心FreeIPCC 大模型呼入机器人在赋能呼叫中心方面发挥着重要作用&#xff0c;主要体现在以下几个方面&#xff1a; 一、提升服务效率与质量 24小时不间断服务&#xff1a; 大模型呼入机器人能…...

基于Python对xslxslx文件进行操作

利用python操作表格文件 读取xsl格式文件-源码 import xlrd# 读取xls文件中的工作对象 wb xlrd.open_workbook(示例文件/xxx物理学与信息技术学院.xls) print(wb)# 获取所有的工作表名称 sheet_names wb.sheet_names() # print(sheet_names)# 选择要读取的具体工作表对象 s…...

预处理器Stylus的介绍及使用,并同Less、Sass进行对比(简单介绍)

目录 一、安装与配置 安装Node.js&#xff1a; 安装Stylus&#xff1a; 配置Webpack&#xff1a; 二、编写Stylus代码 定义变量&#xff1a; 使用变量&#xff1a; 嵌套语法&#xff1a; 混合&#xff08;Mixins&#xff09;&#xff1a; 函数&#xff1a; 6.关键字参…...

ansible自动化运维(四)jinjia2模板

Jinjia2模板 前面说到playbook组成的时候&#xff0c;有介绍到template模块&#xff0c;而template模块对模板文件进行渲染时&#xff0c;使用的就是jinja2模板引擎&#xff0c;jinja2本身就是基于python的模板引擎&#xff0c;所以下面先来了解一下jinjia2模板的一些用法 基…...

ubuntu系统的docker安装(2)

查看系统版本 lsb_release -asudo systemctl status docker查看docker是否安装成功 docker pull拉取镜像不成功/docker run不成功 可能有多种原因&#xff1a;网络链接不稳定&#xff0c;没有重启docker&#xff0c;可以先将docker源设置为国内镜像源 sudo systemctl rest…...

.Net C#医院检验系统源码,实验室管理信息LIS系统

LIS系统源代码&#xff0c;.Net C#医院检验系统源码&#xff0c;三级医院应用案例&#xff0c;自主版权&#xff0c;适合二次开发上项目。 本套实验室管理信息LIS系统采用.Net C#语言开发&#xff0c;用C/S架构。支持DB2,Oracle,MS SQLServer等主流数据库。可根据医院情况配置…...

STM32-FATFS文件系统

一、FATFS文件系统介绍&#xff1a; FATFS 是一个完全免费开源的 FAT/exFAT 文件系统模块&#xff0c;专门为小型的嵌入式系统而设计。它完全用标准 C 语言&#xff08;ANSI C C89&#xff09;编写&#xff0c;所以具有良好的硬件平台独立性&#xff0c;只需做简单的修改就可以…...

【多模态】swift框架使用qwen2-vl

前言 前几篇里面学习了常见的一些多模态模型的典型架构和源代码&#xff0c;上一篇里面测试使用了minicpm-v系列模型&#xff0c;在尝试RLHF的时候发现swift特别好用特别全&#xff0c;记录一下对swift的一些使用&#xff0c;欢迎批评指正&#xff5e;   前一篇里面写了minic…...

什么是全局对象和全局变量

在JavaScript中&#xff0c;全局对象和全局变量是两个重要的概念&#xff0c;它们与代码的执行环境和作用域紧密相关。 全局对象 全局对象&#xff08;Global Object&#xff09;是在代码的任何地方都能访问到的对象。在浏览器环境中&#xff0c;全局对象通常是window对象&…...

【收藏】Cesium billboard添加icon图片、label文字带背景图片(使用canvas绘制实现,附完整源码,vue2或vue3+vite都适用)

1.效果 在项目开发过程中&#xff0c;有一个需求是有若干个需要展示的点&#xff0c;每个点icon不一样、对应的广告牌文字不一样、并且文字还需要有图片背景、每个文字背景也不同&#xff08;抓狂&#xff09;。这种需求只能编写canvas来绘制“icon文字背景文字”的image&#…...

【安卓开发】【Android Studio】启动时报错“Unable to access Android SDK add-on list”

一、问题描述 在启动Android Studio时&#xff0c;软件报错&#xff1a;Unable to access Android SDK add-on list&#xff0c;报错截图如下&#xff1a; 二、原因及解决方法 初步推测是由于网络节点延迟&#xff0c;无法接入谷歌导致的。点击Cancel取消即可。...

前缀和的两种构造方法

方法1 public preSum(int[] nums) {// preSum[0] 0&#xff1b;preSum new int[nums.length 1];// 计算 nums 的累加和for (int i 1; i < preSum.length; i) {preSum[i] preSum[i - 1] nums[i - 1];}} 方法2 public preSum(int[] nums) {preSum[0] nums[0];preSum …...

Linux —— vim 编辑器

一、什么是vim vim是一个功能强大、高度可定制的文本编辑器。以下是对vim编辑器的具体介绍&#xff1a; 历史背景&#xff1a;vim最初由Bram Moolenaar在1991年开发&#xff0c;作为vi编辑器的增强版&#xff0c;增加了许多新的特性和改进。它继承了vi的基本编辑功能和键盘快捷…...

pytorch torch.where函数

torch.where 是 PyTorch 中用于条件选择的函数。它可以根据一个布尔条件在两个张量中选择元素&#xff0c;从而生成一个新的张量。 函数定义 torch.where(condition, input, other)参数说明&#xff1a; condition 一个布尔张量&#xff0c;表示条件判断结果。形状可以与 in…...

【JAVA】Java项目实战—Java EE项目:企业资源规划(ERP)系统

在企业管理中&#xff0c;企业资源规划&#xff08;ERP&#xff09;系统是不可或缺的工具。它能够帮助企业高效管理各种资源&#xff0c;包括人力资源、财务资源和库存等。Java作为一种成熟的编程语言&#xff0c;因其跨平台特性、强大的生态系统以及良好的社区支持&#xff0c…...

操作系统笔记

操作系统 历史 无操作系统 : 1946年&#xff5e;1950年代末期&#xff1a;第1代计算机&#xff0c;硬件以电子管为主&#xff0c;无操作系统。使用纸带传输程序和数据&#xff0c;操作系统只起加载作用。批处理操作系统 :1960年代初期&#xff5e;1960年代中期&#xff1a;第…...

go-zero(十二)消息队列

go zero 消息队列 在微服务架构中&#xff0c;消息队列主要通过异步通信实现服务间的解耦&#xff0c;使得各个服务可以独立发展和扩展。 go-zero中使用的队列组件go-queue&#xff0c;是gozero官方实现的基于Kafka和Beanstalkd 的消息队列框架,我们使用kafka作为演示。 一、…...

CSS3 常用特性及应用全解析

CSS3 常用特性及应用全解析 在前端开发领域&#xff0c;CSS3 以其丰富多样的特性为网页增添了绚丽的视觉效果与流畅的交互体验。本文将详细介绍一些 CSS3 的常见知识及其使用方法&#xff0c;助力开发者打造更具吸引力的网页。 一、边框效果升级 &#xff08;一&#xff…...

revit转gltf,revit转3dtiles,如何将Revit模型转为3DTiles格式并在Cesiumjs中高效可视化

Revit模型导出gltf、glb与3dtiles有多种方式&#xff0c;但一般的商业工具收费普遍较高&#xff1a;Cesiumlab导出3dTile格式数据&#xff0c;Cesiumlab暂时可试用3天&#xff0c;会员版收费每年800&#xff1b;BimAngleEngine导出3dTile格式数据BimAngleEngine暂时可试用30天&…...