2.经典项目-海量用户即使通讯系统
1.实现功能-完成注册用户
完成用户注册的步骤(客户端)
1.将User移动到common/message文件夹下
2.在message中新增注册用户的结构体
const (LoginMesType = "LoginMes"LoginResMesType = "LoginResMes"RegisterMesType = "RegisterMes"RegisterResMesType = "RegisterResMes"
)type RegisterMes struct {User User `json:"user"` //类型就是User机构体
}
type RegisterResMes struct {Code int `json:"code"` //返回状态码 400表示该用户已存在 200表示注册成功Error string `json:"error"` //返回错误信息
}
3.在client/process/userProcess.go中添加注册函数
func (this *UserProcess) Register(userId int, userPwd, userName string) (err error) {conn, err := net.Dial("tcp", "localhost:8889")if err != nil {fmt.Println("net.Dial err = ", err)return}defer conn.Close()var mes = message.Message{}mes.Type = message.RegisterMesTyperegisterMes := message.RegisterMes{}registerMes.User.UserId = userIdregisterMes.User.UserPwd = userPwdregisterMes.User.UserName = userNamedata, err := json.Marshal(registerMes)if err != nil {fmt.Println("json.Marshal err = ", err)return}mes.Data = string(data)data, err = json.Marshal(mes)if err != nil {fmt.Println("json.Marshal err = ", err)return}tf := &utils.Transfer{Conn: conn,}err = tf.WritePkg(data)if err != nil {fmt.Println("注册发送信息错误 err = ", err)return}//处理服务器端返回的消息mes, err = tf.ReadPkg() //mes就是 RegisterResMesif err != nil {fmt.Println("utils.ReadPkg(conn) err = ", err)return}var registerResMes message.RegisterResMeserr = json.Unmarshal([]byte(mes.Data), ®isterResMes)if registerResMes.Code == 200 {fmt.Println("注册成功,请重新登录")} else {fmt.Println(registerResMes.Error)}return
}
4.在client/main/main.go中修改注册相关代码
case 2:fmt.Println("注册用户")fmt.Println("请输入用户id:")fmt.Scanf("%d\n", &userId)fmt.Println("请输入用户密码:")fmt.Scanf("%s\n", &userPwd)fmt.Println("请输入用户名称:")fmt.Scanf("%s", &userName)up := &process2.UserProcess{}up.Register(userId, userPwd, userName)
完成用户注册的步骤(服务器端)
1.在model/userDao.go中添加
func (this *UserDao) Register(user *message.User) (err error) {conn := this.pool.Get()defer conn.Close()_, err = this.getUserById(conn, user.UserId)if err == nil {err = ERROR_USER_EXISTSreturn}//账户不存在,则可以正常注册data, err := json.Marshal(user) //序列化if err != nil {return}//入库_, err = conn.Do("HSet", "users", user.UserId, string(data))if err != nil {fmt.Println("保存注册用户错误 err = ", err)return}return
}
2.在process/userProcess.go中添加
func (this *UserProcess) ServerProcessRegister(mes *message.Message) (err error) {var registerMes message.RegisterMeserr = json.Unmarshal([]byte(mes.Data), ®isterMes)if err != nil {fmt.Println("json.Marshal err = ", err)return}var resMes message.MessageresMes.Type = message.RegisterResMesTypevar registerResMes message.RegisterResMeserr = model.MyUserDao.Register(®isterMes.User)if err != nil {if err == model.ERROR_USER_EXISTS {registerResMes.Code = 505registerResMes.Error = err.Error()} else {registerResMes.Code = 506registerResMes.Error = "注册发生未知错误"}} else {registerResMes.Code = 200fmt.Println("用户注册成功")}data, err := json.Marshal(registerResMes)if err != nil {fmt.Println("json.Marshal err = ", err)return}resMes.Data = string(data)data, err = json.Marshal(resMes)if err != nil {fmt.Println("json.Marshal err = ", err)return}// 发送data,将其封装到writePkg函数//因为使用分层模式(mvc)需要先创建一个Transfer实例,然后读取tf := &utils.Transfer{Conn: this.Conn,}err = tf.WritePkg(data)return
}
3.修改main/processor.go
func (this *Processor) ServerProcessMes(mes *message.Message) (err error) {switch mes.Type {case message.LoginMesType://处理登录//创建UserPorcess实例up := &process2.UserProcess{Conn: this.Conn,}err = up.ServerProcessLogin(mes)case message.RegisterMesType:up := &process2.UserProcess{Conn: this.Conn,}err = up.ServerProcessRegister(mes)default:fmt.Println("消息类型不存在,无法处理...")}return
}
2.实现功能-完成登录时能返回当前在线用户
1.在服务器端维护一个onlineUsers map[int] *UserProcess
2.创建一个新的文件userMgr.go,完成功能对onlineUsers的增删改查
3.在LoginResMess增加一个字段Users []int //保存在线用户id
4.当用户登录后可以显示当前在线用户列表
代码实现
新增server/process/userMgr.go
package processimport "fmt"// 因为UserMgr实例在服务器端有且仅有一个,在很多机房会用到
// 因此将其定义为全局变量
var (userMgr *UserMgr
)type UserMgr struct {onlineUsers map[int]*UserProcess
}// 完成对UserMgr初始化工作
func init() {userMgr = &UserMgr{onlineUsers: make(map[int]*UserProcess, 1024),}
}// 完成对onlineUsers添加
func (this *UserMgr) AddOnlineUser(up *UserProcess) {this.onlineUsers[up.UserId] = up
}// 删除
func (this *UserMgr) DelOnlineUser(userId int) {delete(this.onlineUsers, userId)
}// 返回当前所有在线用户
func (this *UserMgr) GetAllOnlineUser() map[int]*UserProcess {return this.onlineUsers
}// 根据id返回对应的值
func (this *UserMgr) GetOnlineUserById(userId int) (up *UserProcess, err error) {//从map取出一个值,带检测方式up, ok := this.onlineUsers[userId]if !ok { //说明,要找的用户当前不在线err = fmt.Errorf("用户%d 不在线", userId)return}return
}
修改server/process/userProcess.go
type UserProcess struct {Conn net.Conn//增加一个字段,表示该Conn是哪个用户UserId int
}
} else {loginResMes.Code = 200//将登录成功的用户的userId赋给thisthis.UserId = loginMes.UserId//将登录成功的用户放入userMgr中userMgr.AddOnlineUser(this)//将当前在线用户的id放到loginResMes.UserIds中for id, _ := range userMgr.onlineUsers {loginResMes.UserIds = append(loginResMes.UserIds, id)}fmt.Println(user.UserName, "账户登录成功")
修改message.go
type LoginResMes struct {Code int `json:"code"` //返回状态码 500 表示该用户未注册 200表示登录成功UserIds []int `json:"userIds"` //增加字段保存userid的切片Error string `json:"error"` //返回错误信息
}
修改client/process/userProcess.go
if loginResMes.Code == 200 {//可以显示当前在线用户列表fmt.Println("当前在线用户列表如下:")for _, v := range loginResMes.UserIds {//不显示自己if v == userId {continue}fmt.Println("用户id:\t", v)}fmt.Print("\n\n")
优化:当一个新的用户上线后,其他已经登录的用户也能获取最新在线用户列表
思路:
- 当用户A上线,服务器九八A用户的上线信息推给所有在线的用户
- 客户端也需要维护一个map,map中记录了他的好友(目前就是所有人)map[int]User
- 客户端和服务器的通讯通道,要依赖serverProcessMes协程
代码实现
在message.go中增加
const (LoginMesType = "LoginMes"LoginResMesType = "LoginResMes"RegisterMesType = "RegisterMes"RegisterResMesType = "RegisterResMes"NotifyUserStatusMesType = "NotifyUserStatusMes"
)// 定义几个用户状态常量
const (UserOnline = iotaUserOfflineUserBusyStatus
)// 为了配合服务器端推送用户状态变化的消息
type NotifyUserStatusMes struct {UserId int `json:"userId"` //用户idStatus int `json:"status"` //用户状态
}
修改user.go
// 定义一个用户的结构体
type User struct {//确定字段信息//为了序列化和反序列化成功,需保证用户信息的json字符串的key 和结构体的字段对应的tag名字一致UserId int `json:"userId"`UserPwd string `json:"userPwd"`UserName string `json:"userName"`UserStatus int `json:"userStatus"` //用户在线状态
}
修改server/process/userProcess.go
} else {loginResMes.Code = 200//将登录成功的用户的userId赋给thisthis.UserId = loginMes.UserId//将登录成功的用户放入userMgr中userMgr.AddOnlineUser(this)//通知其他在线用户this.NotifyOtherOnlineUser(this.UserId)//将当前在线用户的id放到loginResMes.UserIds中for id, _ := range userMgr.onlineUsers {loginResMes.UserIds = append(loginResMes.UserIds, id)}fmt.Println(user.UserName, "账户登录成功")}
在server/process/userProcess.go中增加
// 编写通知所有在线的用户的方法
func (this *UserProcess) NotifyOtherOnlineUser(userId int) {//遍历onlineUsers 然后一个个发送NotifyUserStatusMesfor id, up := range userMgr.onlineUsers {//过滤自己if id == userId {continue}up.NotifyMeOnline(userId)}
}func (this *UserProcess) NotifyMeOnline(userId int) {//组装我们的NotifyUserStatusMesvar mes message.Messagemes.Type = message.NotifyUserStatusMesTypevar notifyUserStatusMes message.NotifyUserStatusMesnotifyUserStatusMes.UserId = userIdnotifyUserStatusMes.Status = message.UserOnline//将notifyUserStatusMes序列化data, err := json.Marshal(notifyUserStatusMes)if err != nil {fmt.Println("json.Marshal err = ", err)return}//将序列化后的notifyUserStatusMes复制给mes.Datames.Data = string(data)//对mes再次序列化,准备发送data, err = json.Marshal(mes)if err != nil {fmt.Println("json.Marshal err = ", err)return}//发送,Transfer实例tf := &utils.Transfer{Conn: this.Conn,}err = tf.WritePkg(data)if err != nil {fmt.Println("NotifyMeOnline err = ", err)return}
}
修改client/process/server.go
case 1:fmt.Println("显示在线用户列表")outpuOnlineUser()
// 和服务器保持通讯
func serverProcessMes(Conn net.Conn) {//创建一个Transfer实例,不停地读取服务器发送的消息tf := &utils.Transfer{Conn: Conn,}for {fmt.Println("客户端正在等待读取服务器发送的消息")mes, err := tf.ReadPkg()if err != nil {fmt.Println("tf.ReadPkg err = ", err)return}//如果读到消息,进入下一步处理逻辑switch mes.Type {case message.NotifyUserStatusMesType: //有人上线//处理//1. 取出NotifyUserStatusMesvar notifyUserStatusMes message.NotifyUserStatusMesjson.Unmarshal([]byte(mes.Data), ¬ifyUserStatusMes)//2. 把这个用户信息,状态保存到客户map[int]User中updateUserStatus(¬ifyUserStatusMes)default:fmt.Println("服务器端返回了未知的消息类型")}//fmt.Printf("mes = %v\n", mes)}
}
新增client/process/userMgt.go
package processimport ("fmt""project/common/message"
)// 客户端维护的map
var onlineUsers map[int]*message.User = make(map[int]*message.User, 10)// 在客户端显示当前在线的用户
func outpuOnlineUser() {//遍历onlilneUsersfmt.Println("当前在线用户列表:")for id, _ := range onlineUsers {fmt.Println("用户id:\t", id)}
}// 编写一个方法,处理返回的NotifyUserStatusMes
func updateUserStatus(notifyUserStatusMes *message.NotifyUserStatusMes) {user, ok := onlineUsers[notifyUserStatusMes.UserId]if !ok {user = &message.User{UserId: notifyUserStatusMes.UserId,}}user.UserStatus = notifyUserStatusMes.StatusonlineUsers[notifyUserStatusMes.UserId] = useroutpuOnlineUser()
}
修改client/process/userProcess.go
if loginResMes.Code == 200 {//可以显示当前在线用户列表fmt.Println("当前在线用户列表如下:")for _, v := range loginResMes.UserIds {//不显示自己if v == userId {continue}fmt.Println("用户id:\t", v)//完成客户端的onlineUsers初始化user := &message.User{UserId: v,UserStatus: message.UserOnline,}onlineUsers[v] = user}fmt.Print("\n\n")
3.实现功能-完成登录用户群聊
3.1 完成客户端发送消息
思路
1.新增一个消息结构体smsMes…
2.新增一个model/CurUser
3.在smsProcess.go增加相应的方法SendGroupMes发送一个群聊消息
代码实现
在message中新增
const (LoginMesType = "LoginMes"LoginResMesType = "LoginResMes"RegisterMesType = "RegisterMes"RegisterResMesType = "RegisterResMes"NotifyUserStatusMesType = "NotifyUserStatusMes"SmsMesType = "SmsMes"
)// 增加一个SmsMes发送消息
type SmsMes struct {Content string `json:"content"` //消息内容User //匿名结构体,集继承
}
新增client/model/curUser.go
package modelimport ("net""project/common/message"
)// 在客户端很多地方要用到,需声明为全局
type CurUser struct {Conn net.Connmessage.User
}
在client/process/userMgr.go中新增
var CurUser model.CurUser //在用户登录成功后,完成对CurUser初始化
在client/process/userProcess.go修改
if loginResMes.Code == 200 {//初始化CurUserCurUser.Conn = connCurUser.UserId = userIdCurUser.UserStatus = message.UserOnline
在client/process/smsProcess.go新增
package processimport ("encoding/json""fmt""project/common/message""project/common/utils"
)type SmsProcess struct {
}// 发送群聊消息
func (this *SmsProcess) SendGroupMes(content string) (err error) {//1.创建一个Mesvar mes message.Messagemes.Type = message.SmsMesType//2.创建一个SmsMes实例var smsMes message.SmsMessmsMes.Content = contentsmsMes.UserId = CurUser.UserIdsmsMes.UserStatus = CurUser.UserStatus//3.序列化smsMesdata, err := json.Marshal(smsMes)if err != nil {fmt.Println("SendGroupMes json.Marshal err = ", err.Error())return}mes.Data = string(data)//4.对mes再次序列化data, err = json.Marshal(mes)if err != nil {fmt.Println("SendGroupMes json.Marshal err = ", err.Error())return}//5.将mes发送给服务器tf := &utils.Transfer{Conn: CurUser.Conn,}//6.发送err = tf.WritePkg(data)if err != nil {fmt.Println("sendGroupMes err = ", err.Error())return}return
}
修改client/process/server.go
var key intvar content string//用到SmsProcess实例较为频繁,因此定义在外部smsProcess := &SmsProcess{}fmt.Scanf("%d\n", &key)switch key {case 1:fmt.Println("显示在线用户列表")outpuOnlineUser()case 2:fmt.Println("你想对大家说什么:")fmt.Scanf("%s\n", &content)smsProcess.SendGroupMes(content)
3.2 服务器接收群发消息,并发送消息(发送者除外)
思路
1.在服务器端接收到SmsMes消息
2.在server/process/smsProcess.go文件增加群发消息的方法
3.在客户端还要增加去处理服务器转发的群发消息
代码实现
在server/process/smsProcess.go中添加
package processimport ("encoding/json""fmt""net""project/common/message""project/common/utils"
)type SmsProcess struct {
}func (this *SmsProcess) SendGroupMes(mes *message.Message) {var smsMes message.SmsMeserr := json.Unmarshal([]byte(mes.Data), &smsMes)if err != nil {fmt.Println("json.Unmarshal err = ", err)return}data, err := json.Marshal(mes)if err != nil {fmt.Println("json.Marshal err = ", err)return}for id, up := range userMgr.onlineUsers {//过滤自己if id == smsMes.UserId {continue}this.SendMesToEachOnlineUser(data, up.Conn)}}func (this *SmsProcess) SendMesToEachOnlineUser(data []byte, conn net.Conn) {tf := &utils.Transfer{Conn: conn,}err := tf.WritePkg(data)if err != nil {fmt.Println("群发消息失败")return}
}
修改server/main/processor.go
func (this *Processor) ServerProcessMes(mes *message.Message) (err error) {switch mes.Type {case message.LoginMesType://处理登录//创建UserPorcess实例up := &process2.UserProcess{Conn: this.Conn,}err = up.ServerProcessLogin(mes)case message.RegisterMesType:up := &process2.UserProcess{Conn: this.Conn,}err = up.ServerProcessRegister(mes)case message.SmsMesType:smsProcess := &process2.SmsProcess{}smsProcess.SendGroupMes(mes)default:fmt.Println("消息类型不存在,无法处理...")}return
}
新增client/process/smsMgr.go
package processimport ("encoding/json""fmt""project/common/message"
)func outputGroupMes(mes *message.Message) {var smsMes message.SmsMeserr := json.Unmarshal([]byte(mes.Data), &smsMes)if err != nil {fmt.Println("json.Unmarshal err = ", err.Error())return}//显示信息info := fmt.Sprintf("用户id:\t%d 对大家说:\t%s", smsMes.UserId, smsMes.Content)fmt.Println(info)fmt.Println()
}
修改client/process/server.go
//如果读到消息,进入下一步处理逻辑switch mes.Type {case message.NotifyUserStatusMesType: //有人上线//处理//1. 取出NotifyUserStatusMesvar notifyUserStatusMes message.NotifyUserStatusMesjson.Unmarshal([]byte(mes.Data), ¬ifyUserStatusMes)//2. 把这个用户信息,状态保存到客户map[int]User中updateUserStatus(¬ifyUserStatusMes)case message.SmsMesType: //有人群发消息outputGroupMes(&mes)default:fmt.Println("服务器端返回了未知的消息类型")}
相关文章:
2.经典项目-海量用户即使通讯系统
1.实现功能-完成注册用户 完成用户注册的步骤(客户端) 1.将User移动到common/message文件夹下 2.在message中新增注册用户的结构体 const (LoginMesType "LoginMes"LoginResMesType "LoginResMes"RegisterMesType "RegisterMes"…...
基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的交通标志识别系统详解(深度学习模型+UI界面代码+训练数据集)
摘要:本篇博客详细介绍了利用深度学习构建交通标志识别系统的过程,并提供了完整的实现代码。该系统采用了先进的YOLOv8算法,并与YOLOv7、YOLOv6、YOLOv5等早期版本进行了性能评估对比,分析了性能指标如mAP、F1 Score等。文章深入探…...
VMware下创建虚拟机
Centos7是比较常用的一个Linux发行版本,在国内的使用比例比较高 安装完VMware一定要检查虚拟网卡有没有安装成功,如果没有VMnet1和VMnet8 虚拟机是无法上网的,就需要卸载重启电脑重新安装 控制面板—网络和Internet—网络连接 快捷方式打开&a…...
基于Ambari搭建大数据分析平台
一、部署工具简介 1. Hadoop生态系统 Hadoop big data ecosystem in Apache stack 2. Hadoop的发行版本 Hadoop的发行版除了Apache的开源版本之外,国外比较流行的还有:Cloudera发行版(CDH)、Hortonworks发行版(HDP)、MapR等&am…...
Vue template到render过程,以及render的调用时机
Vue template到render过程 vue的模版编译过程主要如下:template -> ast -> render函数(1)调用parse方法将template转化为ast(抽象语法树)(2)对静态节点做优化(3)生…...
阿里云服务器Ngnix配置SSL证书开启HTTPS访问
文章目录 前言一、SSL证书是什么?二、如何获取免费SSL证书三、Ngnix配置SSL证书总结 前言 很多童鞋的网站默认访问都是通过80端口的Http服务进行访问,往往都会提示不安全,很多人以为Https有多么高大上,实际不然,他只是…...
12 list的使用
文档介绍 文档介绍 1.list是可以在常数范围内的任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代 2.list的底层是带头双向链表循环结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指针指向其前一个元素和…...
控件交互与视图交互的区别
在实际应用中,控件交互和视图交互的区别主要体现在以下几个方面: (1)关注的对象不同:控件交互更关注于界面中的单个控件如何响应用户的操作,例如按钮的点击、列表项的滑动等。而视图交互则更关注于整个界面的布局、导航和交互设计…...
打包 加載AB包 webGl TextMeshPro 變紫色的原因
1.打包 加載AB包 webGl TextMeshPro 變紫色的原因 編輯器命令行https://docs.unity3d.com/cn/2019.4/Manual/CommandLineArguments.html 1.UnityHub 切換命令行參數 -force-gles 2.-force-gles(仅限 Windows)| 使 Editor 使用 OpenGL for Embedded Sys…...
美易官方:去年全球企业派息1.66万亿美元创新高
去年全球企业派息总额达到了1.66万亿美元,创下了历史新高。这一数字不仅彰显了全球企业的盈利能力和财务稳健性,也反映了它们对股东的责任感和对未来发展的信心。在这一背景下,微软和苹果这两家科技巨头在派息方面的表现尤为引人注目。 微软是…...
基于Springboot的面向智慧教育的实习实践系统设计与实现(有报告)。Javaee项目,springboot项目。
演示视频: 基于Springboot的面向智慧教育的实习实践系统设计与实现(有报告)。Javaee项目,springboot项目。 项目介绍: 采用M(model)V(view)C(controller&…...
【数据库-黑马笔记】基础-SQL
本文参考b站黑马数据库视频,总结详细全面的笔记 ,可结合视频观看1~26集 MYSQL 的基础知识框架如下 目录 一、MYSQL概述 1、数据库相关概念 2、MYSQL的安装及启动 二、SQL 1、DDL【Data Defination】 2、DML【Data Manipulation】 ①、插入 ②、更新和删除 3、 DQL【Data…...
MySQL性能分析:性能模式和慢查询日志的使用
目录 一、性能模式 步骤1. 启用性能模式 步骤2. 查询性能数据 步骤3. 分析性能数据 步骤4. 优化与调整 注意事项 二、慢查询日志 步骤1. 启用慢查询日志...
【哈希表算法题记录】15. 三数之和,18. 四数之和——双指针法
题目链接 15. 三数之和 思路 这题虽然放在哈希表的分类里面,但是用双指针法会更高效。 之前的双指针我们要么是一头left一尾right,要么是快fast慢slow指针。这里是要计算三个数的和,我们首先对数组进行从小到大的排序,先固定一…...
代码随想录算法训练营Day44 ||leetCode 完全背包 || 518. 零钱兑换 II || 377. 组合总和 Ⅳ
完全背包 518. 零钱兑换 II 遍历硬币和金额,累加所有可能 class Solution { public:int change(int amount, vector<int>& coins) {vector<int> dp(amount1,0);dp[0]1;for (int i 0; i < coins.size();i){for(int j coins[i]; j < amount;…...
RabbitMQ发布确认高级版
1.前言 在生产环境中由于一些不明原因,导致 RabbitMQ 重启,在 RabbitMQ 重启期间生产者消息投递失败, 导致消息丢失,需要手动处理和恢复。于是,我们开始思考,如何才能进行 RabbitMQ 的消息可靠投递呢&…...
【阿里云系列】-基于云效构建部署Springboot项目到ACK
介绍 为了提高项目迭代的速度加速交付产品给客户,我们通常会选择CICD工具来减少人力投入产生的成本,开源的工具比如有成熟的Jenkins,但是本文讲的是阿里云提高的解决方案云效平台,通过配置流水线的形式实现项目的快速部署到服务器…...
PyTorch搭建LeNet训练集详细实现
一、下载训练集 导包 import torch import torchvision import torch.nn as nn from model import LeNet import torch.optim as optim import torchvision.transforms as transforms import matplotlib.pyplot as plt import numpy as npToTensor()函数: 把图像…...
R语言复现:中国Charls数据库一篇现况调查论文的缺失数据填补方法
编者 在临床研究中,数据缺失是不可避免的,甚至没有缺失,数据的真实性都会受到质疑。 那我们该如何应对缺失的数据?放着不管?还是重新开始?不妨试着对缺失值进行填补,简单又高效。毕竟对于统计师来说&#…...
解决Git:Author identity unknown Please tell me who you are.
报错信息: 意思: 作者身份未知 ***请告诉我你是谁。 解决办法: git config --global user.name "你的名字"git config --global user.email "你的邮箱"...
shell脚本--常见案例
1、自动备份文件或目录 2、批量重命名文件 3、查找并删除指定名称的文件: 4、批量删除文件 5、查找并替换文件内容 6、批量创建文件 7、创建文件夹并移动文件 8、在文件夹中查找文件...
前端导出带有合并单元格的列表
// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...
汽车生产虚拟实训中的技能提升与生产优化
在制造业蓬勃发展的大背景下,虚拟教学实训宛如一颗璀璨的新星,正发挥着不可或缺且日益凸显的关键作用,源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例,汽车生产线上各类…...
Rust 异步编程
Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...
JavaScript 数据类型详解
JavaScript 数据类型详解 JavaScript 数据类型分为 原始类型(Primitive) 和 对象类型(Object) 两大类,共 8 种(ES11): 一、原始类型(7种) 1. undefined 定…...
Golang——6、指针和结构体
指针和结构体 1、指针1.1、指针地址和指针类型1.2、指针取值1.3、new和make 2、结构体2.1、type关键字的使用2.2、结构体的定义和初始化2.3、结构体方法和接收者2.4、给任意类型添加方法2.5、结构体的匿名字段2.6、嵌套结构体2.7、嵌套匿名结构体2.8、结构体的继承 3、结构体与…...
适应性Java用于现代 API:REST、GraphQL 和事件驱动
在快速发展的软件开发领域,REST、GraphQL 和事件驱动架构等新的 API 标准对于构建可扩展、高效的系统至关重要。Java 在现代 API 方面以其在企业应用中的稳定性而闻名,不断适应这些现代范式的需求。随着不断发展的生态系统,Java 在现代 API 方…...
DAY 26 函数专题1
函数定义与参数知识点回顾:1. 函数的定义2. 变量作用域:局部变量和全局变量3. 函数的参数类型:位置参数、默认参数、不定参数4. 传递参数的手段:关键词参数5 题目1:计算圆的面积 任务: 编写一…...
车载诊断架构 --- ZEVonUDS(J1979-3)简介第一篇
我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 做到欲望极简,了解自己的真实欲望,不受外在潮流的影响,不盲从,不跟风。把自己的精力全部用在自己。一是去掉多余,凡事找规律,基础是诚信;二是…...
轻量级Docker管理工具Docker Switchboard
简介 什么是 Docker Switchboard ? Docker Switchboard 是一个轻量级的 Web 应用程序,用于管理 Docker 容器。它提供了一个干净、用户友好的界面来启动、停止和监控主机上运行的容器,使其成为本地开发、家庭实验室或小型服务器设置的理想选择…...
