用 Go 打造 sysinfo 工具:从 /proc 采集系统信息的实战指南
简介面向Go语言开发者与Linux运维人员的开源资源聚焦系统信息采集场景。通过sysinfo库的封装可便捷获取CPU使用率、内存状态、磁盘I/O、网络流量及文件系统容量等关键指标适用于监控工具开发、性能分析、运维自动化脚本等任务。包内共240个文件以48个Go源码文件为核心覆盖CPU、内存、磁盘、网络等模块的调用与数据解析示例其余为大量proc目录下的真实或模拟系统文件样本例如stat、meminfo、diskstats、netstat、mounts等便于读者对照源码理解数据来源和字段含义。整体压缩包约210KB结构清晰便于按需查阅。目前已有4311人学习下载受到开发者社区认可。借助这些代码与样本读者可以直接复用采集逻辑或在此基础上扩展自定义监控项快速掌握Linux系统编程中从内核文件到结构化数据的转换方法减少底层调试时间。1. sysinfo 是什么一条命令读透 Linux 系统信息的实战价值在 Linux 服务器上排查性能问题第一反应往往是“CPU 是不是满了内存还剩多少磁盘有没有写爆”这些信息散落在 /proc、/sys 和一堆命令里手工敲 top、free、df 虽然能看但没法直接喂给自己的监控系统。用 Go 写一个 sysinfo 小工具把系统信息采集逻辑沉淀成结构体几段代码就能在本地跑通再挂到 HTTP 接口上变成监控数据源。这个方向最适合后端工程师和运维开发不依赖额外 agent单二进制扔到服务器就能跑交叉编译也省心。下文我会从数据源选型、代码实现到常见坑位完整拆一遍。2. 先搞清信息从哪来Linux 系统信息的数据源与 Go 的三种取数方式写 sysinfo 之前先要回答一个问题Linux 的系统信息到底藏在哪里答案直接影响代码量、依赖和可移植性。我常用的取数路径有三条各有取舍下面展开说。2.1 /proc 文件系统最朴素也最可靠的信息来源Linux 内核把运行时的系统状态通过 /proc 伪文件系统暴露出来读文件就是读内核数据。CPU 信息在 /proc/stat内存信息在 /proc/meminfo磁盘分区在 /proc/partitions磁盘 I/O 在 /proc/diskstats网络流量在 /proc/net/dev。这些都是纯文本格式在不同内核版本间大体稳定解析起来没有黑匣子。读 /proc 的好处是零依赖、权限要求低普通用户也能读大部分文件。坏处是文本解析容易出错字段位置可能随内核版本调整。比如 /proc/meminfo 里 MemAvailable 这个字段是在内核 3.14 之后才加入的老系统上没有解析时就要做兜底。Go 标准库的 os 包直接能读文件所以我一般会先用简单的方式读 /proc再考虑 syscall。如果只是做基础监控读 /proc 足够覆盖 90% 的场景。2.2 syscall 直接向内核要数据避开文本解析的第二种路径Go 的 syscall 包提供了直接调用内核接口的能力比如 syscall.Sysinfo 能拿 load average、总内存、可用内存syscall.Statfs 能拿文件系统的块大小和空余块数。这种方式返回的是结构体不用自己 split 字符串代码更干净性能也更好。但 syscall.Sysinfo 的字段数量和精度有限内存只给总量和空闲量没有 cache、buffer 这些明细load average 倒是很全。磁盘信息它只管单个文件系统不管整机所有分区。所以我的做法是能用 syscall 的用小接口拿需要明细字段时再回去读 /proc。两者不冲突可以混用。取数方式优点缺点适用场景读 /proc信息全、零依赖、易调试文本解析易错、格式依赖内核监控明细指标syscall结构体返回、性能好、代码简单字段少、部分平台不一致快速拿基础指标cgo C 库兼容传统 C 程序习惯交叉编译复杂、部署易出问题很少推荐2.3 cgo C 库能不用就别用的方案有些人在 Go 里通过 cgo 调用 C 的 sysinfo() 或 getloadavg()觉得稳定。但 cgo 会引入 C 工具链依赖交叉编译时要单独处理静态链接也可能变复杂。一个本来能直接扔到 ARM 板子上的二进制加上 cgo 后可能就得折腾半天。我更愿意把采集逻辑控制在 Go 标准库和少数 x/sys 扩展包内这样编译出的二进制是纯静态的部署时不用管 glibc 版本。除非目标系统特别古老、/proc 接口缺失严重否则我不会碰 cgo。3. 用 sysinfo 采集 CPU 与内存信息核心结构体与第一段可运行代码数据源确定后下一步就是把文本变成结构体。这一章我会从定义结构体开始逐步写完 CPU 和内存的采集函数并给出一个能直接编译运行的最小例子。3.1 定义系统信息结构体把杂乱的文本变成整齐的字段我习惯把采集结果组织成嵌套结构体方便后续序列化成 JSON。以下是一个精简的 SysInfo 定义// SysInfo 是系统信息的顶层结构体 type SysInfo struct { Hostname string json:hostname CPU CPUInfo json:cpu Memory MemoryInfo json:memory Uptime uint64 json:uptime } // CPUInfo 包含 CPU 核心数、型号和使用率 type CPUInfo struct { Cores int json:cores ModelName string json:model_name UsagePercent float64 json:usage_percent } // MemoryInfo 包含内存总量、可用量和使用率 type MemoryInfo struct { Total uint64 json:total Available uint64 json:available UsedPercent float64 json:used_percent }这段代码把最终要输出的维度固定下来。字段上用 json tag后面要暴露 HTTP 接口时直接 json.Marshal 就能用。这里的 Cores 我通常指逻辑核心数不是物理封装数物理和逻辑的区别在容器环境下尤其重要后续避坑章节会再提。3.2 读 /proc/stat 计算 CPU 使用率两次采样的差值才是关键CPU 使用率不能直接读一个“当前值”因为 /proc/stat 给的是累计 ticks。真正要算的是两次采样之间的增量。func readCPUStat() (idle, total uint64) { data, err : os.ReadFile(/proc/stat) if err ! nil { return 0, 0 } // 找以 cpu 开头的行注意后面有个空格防止匹配到 cpu0 lines : strings.Split(string(data), \n) for _, line : range lines { if !strings.HasPrefix(line, cpu ) { continue } fields : strings.Fields(line) // fields[0] 是 cpu后面依次是 user, nice, system, idle, iowait, irq, softirq, steal, guest, guest_nice if len(fields) 5 { return 0, 0 } var t uint64 for _, f : range fields[1:] { v, _ : strconv.ParseUint(f, 10, 64) t v } // idle 字段是 fields[4] idle, _ strconv.ParseUint(fields[4], 10, 64) return idle, t } return 0, 0 }注意第 7 行判断HasPrefix(line, cpu )如果用HasPrefix(line, cpu)会把 cpu0、cpu1 这些行也读进来。字段中 user、nice、system、idle、iowait、irq、softirq、steal 等加起来才是总时间。idle 单独提取方便计算空闲率。使用率计算函数如下// getCPUUsage 两次调用 readCPUStat用增量计算使用率 // interval 是两次采样之间的时间间隔单位毫秒 func getCPUUsage(intervalMs int) float64 { idle1, total1 : readCPUStat() time.Sleep(time.Duration(intervalMs) * time.Millisecond) idle2, total2 : readCPUStat() if total2 total1 { return 0 } idleDelta : idle2 - idle1 totalDelta : total2 - total1 return (1 - float64(idleDelta)/float64(totalDelta)) * 100 }这里参数intervalMs很关键一般取 200 到 1000 毫秒。间隔太短数值抖动厉害太长监控延迟高。我第一次实现时只读了一次 /proc/stat算出来的“使用率”其实是开机以来的平均使用率根本不是当前值这是典型的坑。3.3 读 /proc/meminfo 获取内存指标注意单位换算内存信息相对简单/proc/meminfo 里直接有 MemTotal、MemAvailable 等字段单位是 kB。需要自己换算成字节或 GB。func readMemoryInfo() MemoryInfo { data, err : os.ReadFile(/proc/meminfo) if err ! nil { return MemoryInfo{} } var mem MemoryInfo lines : strings.Split(string(data), \n) for _, line : range lines { fields : strings.Fields(line) if len(fields) 2 { continue } key : strings.TrimSuffix(fields[0], :) value, _ : strconv.ParseUint(fields[1], 10, 64) // 内核给的是 kB统一转成字节方便上层使用 switch key { case MemTotal: mem.Total value * 1024 case MemAvailable: mem.Available value * 1024 } } if mem.Total 0 { return mem } mem.UsedPercent (1 - float64(mem.Available)/float64(mem.Total)) * 100 return mem }strings.TrimSuffix(fields[0], :)是为了去掉行首的冒号。老内核没有 MemAvailable 时Available 会保持零值计算使用率就会变成 100%所以读取端要处理“字段缺失”和“字段值为 0”两种情况。我一般会判断如果 Available 为 0就退回用 MemFree 加 Buffers 加 Cached 估算可用内存。3.4 最小可运行代码把信息打印出来把上面的函数组装成一个 main.go就能在终端看到输出。package main import ( fmt os strings strconv time ) // 这里省略 3.1–3.3 中定义的结构体和函数 func main() { hostname, _ : os.Hostname() cpuUsage : getCPUUsage(500) // 采样间隔 500ms mem : readMemoryInfo() info : SysInfo{ Hostname: hostname, CPU: CPUInfo{ Cores: runtime.NumCPU(), ModelName: readCPUModel(), UsagePercent: cpuUsage, }, Memory: mem, } // 简单打印后续可以换成 json.Marshal fmt.Printf(Host: %s\n, info.Hostname) fmt.Printf(CPU cores: %d, usage: %.2f%%\n, info.CPU.Cores, info.CPU.UsagePercent) fmt.Printf(Memory total: %.2f GB, available: %.2f GB, usage: %.2f%%\n, float64(info.Memory.Total)/1024/1024/1024, float64(info.Memory.Available)/1024/1024/1024, info.Memory.UsedPercent) }注意这里runtime.NumCPU()返回的是 Go 进程可见的 CPU 数量在容器里可能不是宿主机物理核数如果你想统计宿主机需要读 /proc/cpuinfo 里的 processor 数量。readCPUModel()也是从 /proc/cpuinfo 里按行搜 model name 字段。为了篇幅这里不再贴全但思路是逐行 scan 后用 HasPrefix 匹配。这个最小例子已经能跑但只能看 CPU 和内存。接下来补齐磁盘和网络。4. 磁盘与网络信息采集把 sysinfo 从 Demo 变成可用工具只有 CPU 和内存的 sysinfo 还不能解决磁盘告警和流量监控的问题。这一章我继续补全磁盘分区、磁盘 I/O、网络接口的采集代码并把它们聚合到一个输出结构里。4.1 磁盘分区信息解析 /proc/partitions 与 statfs 结合/proc/partitions 列出了块设备名称和块数但没直接给挂载点和文件系统使用率。要算“C 盘满了”这种问题还得让 sysinfo 遍历挂载点对每个挂载点调用 statfs。func getDiskUsage() ([]DiskInfo, error) { // 先读 /proc/mounts 拿到所有挂载点 data, err : os.ReadFile(/proc/mounts) if err ! nil { return nil, err } var disks []DiskInfo seen : map[string]bool{} lines : strings.Split(string(data), \n) for _, line : range lines { fields : strings.Fields(line) if len(fields) 3 { continue } mountPoint : fields[1] fsType : fields[2] // 跳过虚拟文件系统 if strings.HasPrefix(fsType, proc) || strings.HasPrefix(fsType, sysfs) || strings.HasPrefix(fsType, cgroup) || fsType tmpfs { continue } // 同一个挂载点可能重复出现用 map 去重 if seen[mountPoint] { continue } seen[mountPoint] true var stat syscall.Statfs_t if err : syscall.Statfs(mountPoint, stat); err ! nil { continue } // 块大小乘以块数才是字节数 total : stat.Blocks * uint64(stat.Bsize) free : stat.Bavail * uint64(stat.Bsize) used : total - free disks append(disks, DiskInfo{ MountPoint: mountPoint, FsType: fsType, Total: total, Used: used, UsedPercent: float64(used) / float64(total) * 100, }) } return disks, nil }注意 /proc/mounts 里会有很多重复挂载比如同一个设备被 bind 到多个目录我只取第一次出现。stat.Bavail是无特权用户可用的块数比stat.Bfree更接近真实剩余空间很多命令如 df 也是用 Bavail。跳过 tmpfs 是避免把 /tmp 这种内存文件系统也算成磁盘真实磁盘告警时这些虚拟文件系统会误导人。4.2 磁盘 I/O 指标从 /proc/diskstats 读取读写速率分区使用率解决了容量问题但 IO 饱和是另一回事。/proc/diskstats 里字段很多我一般只取读完成次数、读扇区数、写完成次数、写扇区数这四项。扇区大小通常是 512 字节。type DiskIO struct { Device string json:device ReadBytes uint64 json:read_bytes WriteBytes uint64 json:write_bytes ReadIOPS float64 json:read_iops WriteIOPS float64 json:write_iops } func readDiskStats() map[string][4]uint64 { // 返回 device - [读次数, 读扇区, 写次数, 写扇区] data, err : os.ReadFile(/proc/diskstats) if err ! nil { return nil } result : map[string][4]uint64{} lines : strings.Split(string(data), \n) for _, line : range lines { fields : strings.Fields(line) // 主设备号、次设备号、设备名、读完成、读合并、读扇区、读耗时、写完成... if len(fields) 8 { continue } device : fields[2] // 只保留物理磁盘跳过 ram、loop、dm 等虚拟设备 if strings.HasPrefix(device, ram) || strings.HasPrefix(device, loop) || strings.HasPrefix(device, dm-) { continue } readCount, _ : strconv.ParseUint(fields[3], 10, 64) readSectors, _ : strconv.ParseUint(fields[5], 10, 64) writeCount, _ : strconv.ParseUint(fields[7], 10, 64) writeSectors, _ : strconv.ParseUint(fields[9], 10, 64) result[device] [4]uint64{readCount, readSectors, writeCount, writeSectors} } return result }要算速率和 IOPS同样需要两次采样。比如 1 秒内读扇区增加了 1000 个乘以 512 就是每秒读 512KB。IOPS 用读写完成次数差值除以间隔秒数。我在实现时发现 /proc/diskstats 的设备名有的带分区号sda1有的不带如果你要统计整块盘的 I/O需要在设备名上做过滤只保留以 sda、nvme0n1 等整盘结尾的设备。4.3 网络接口流量从 /proc/net/dev 读累计字节网络流量和磁盘 I/O 的思路一模一样/proc/net/dev 给出每个接口的累计收发包字节数差值除以时间就是速率。func readNetDev() map[string][2]uint64 { // 返回 interface - [收字节, 发字节] data, err : os.ReadFile(/proc/net/dev) if err ! nil { return nil } result : map[string][2]uint64{} lines : strings.Split(string(data), \n) // 前两行是表头跳过 for _, line : range lines[2:] { fields : strings.Fields(line) if len(fields) 10 { continue } // 接口名带冒号去掉 iface : strings.TrimSuffix(fields[0], :) recvBytes, _ : strconv.ParseUint(fields[1], 10, 64) sendBytes, _ : strconv.ParseUint(fields[9], 10, 64) result[iface] [2]uint64{recvBytes, sendBytes} } return result }这里的坑是网卡别名和虚拟接口。eth0 和 bond0 可能重复计数docker0、veth 这些虚拟接口会出现在 /proc/net/dev 里。所以我习惯在采集时用配置过滤掉虚拟接口或者只统计用户显式指定的网卡。否则监控图上会出现一堆从零开始跳动的小 veth 接口干扰判断。4.4 组装完整的 sysinfo 命令把磁盘和网络的采集函数汇总到一个结构体里main 函数输出 JSON就是一个能用的 sysinfo 工具。// SysInfo 扩展结构体增加磁盘和网络 type SysInfo struct { Hostname string json:hostname CPU CPUInfo json:cpu Memory MemoryInfo json:memory Disks []DiskInfo json:disks NetIO NetIOInfo json:netio // 包含采样差值后的速率 }main 函数里先采样一次磁盘 I/O 和网络流量睡一秒再采样一次算出每秒速率然后输出。为了不阻塞主流程我通常会把这些采样函数放进 goroutine用 channel 返回结果但初版代码直接同步调用更清晰。5. 避坑指南sysinfo 开发中常见的 5 个坑与排查路径写 sysinfo 的过程里我踩过的坑不少挑 5 个最有代表性的记录在这里每条都按“现象 → 原因 → 解决”来写方便按图索骥。5.1 CPU 使用率第一次输出 100%现象程序启动后第一次采集CPU 使用率直接显示 99% 或 100%之后又恢复正常。原因没有用两次采样做差值直接把开机以来的 total 和 idle 算了一次平均。开机时间越长这个值越接近“历史平均使用率”而不是当前使用率。解决强制要求采样必须有一次 sleep 间隔。我习惯暴露一个intervalMs参数默认 500ms并在代码注释里提醒调用方第一次返回值没有意义至少等第二次采样才能看。如果监控平台需要“瞬时值”就把采集间隔缩短到 100ms而不是去掉差值逻辑。5.2 内存 Available 字段在旧内核上缺失现象同样的二进制在 CentOS 7 上跑得好好的换到老内核的嵌入式设备上内存使用率变成 100%。原因/proc/meminfo 在没到 3.14 的内核上没有 MemAvailable代码里 Available 保持零值后面算使用率就直接 100%。解决解析的时候加兜底逻辑。如果 MemAvailable 不存在就用 MemFree Buffers Cached 估算可用内存。注意 Cached 字段里包含 tmpfs 占用的部分需要减掉 Shmem。大致写法case MemFree: mem.free value * 1024 case Buffers: mem.buffers value * 1024 case Cached: mem.cached value * 1024 case Shmem: mem.shmem value * 1024 } if mem.Available 0 { mem.Available mem.free mem.buffers mem.cached - mem.shmem }5.3 磁盘使用率把分区和整块盘混在一起现象磁盘监控图上同一块盘的 sda、sda1、sda2 都有数据告警阈值形同虚设。原因/proc/partitions 和 /proc/diskstats 会同时出现整盘和分区设备直接全部采集就会造成重复。解决在过滤逻辑里显式排除数字结尾的设备名只保留整块盘。另外挂载点采集statfs天然只统计已挂载的分区所以容量使用率和 I/O 速率要分开看容量看挂载点I/O 看整块盘或具体分区不要混在一起做告警。5.4 容器里看到的是宿主机还是容器自己的信息现象在 Docker 容器内跑 sysinfoCPU 核心数和内存总量和宿主机对不上有时拿到的是 cgroup 限制值有时拿到的是宿主机的全局值。原因/proc/stat、/proc/meminfo 读取的是内核全局视角而容器内 /proc 是宿主机的 proc 挂载未隔离但 cgroup 限制了容器可用资源。所以直接读 /proc 得到的是宿主机数据不代表容器实际可用。解决明确采集目标。如果是容器内监控需要读 /sys/fs/cgroup 的 cpu.max 和 memory.max如果是宿主机监控则直接读 /proc。在代码注释里写清楚这一点避免使用者误判。我一般会在 SysInfo 结构体里加一个Scope字段标记当前是在容器内还是宿主机上。5.5 长期运行时文件句柄泄漏现象sysinfo 作为常驻服务跑了几天内存正常但开 PDF 的句柄数一直涨最后报 too many open files。原因读取 /proc 下的文件时用了 os.ReadFile它内部是打开、读完、关闭正常情况下没有泄漏。但我在某次实现里为了解析大文件用了 bufio.Scanner却忘了在循环结束后调用 file.Close()导致句柄累积。解决所有打开文件的地方统一用 defer file.Close()并且在 for 循环里不要用 defer要显式在循环体末尾关闭。这个坑在流量采集里最常见因为 /proc/net/dev 文件小、读得快句柄泄漏被隐藏了好几天。6. 更进一步把 sysinfo 变成常驻服务与监控数据源到这里sysinfo 已经能采集 CPU、内存、磁盘、网络四类核心指标。再往前一步就是让它变成一个常驻守护进程定时采集并通过 HTTP 输出 JSON对接 Prometheus 或其他监控系统。这里有一个很实用的技巧不要每次请求都去重新读 /proc而是用后台 goroutine 定时刷新全局快照HTTP 接口只读快照。var ( mu sync.RWMutex snap SysInfo ) func collectLoop(interval time.Duration) { for { info : collect() mu.Lock() snap info mu.Unlock() time.Sleep(interval) } } func handler(w http.ResponseWriter, r *http.Request) { mu.RLock() defer mu.RUnlock() w.Header().Set(Content-Type, application/json) json.NewEncoder(w).Encode(snap) }这样设计的好处是采集频率可控接口响应快不会因为多个监控请求同时触发 /proc 读取造成系统压力。间隔建议设置成 5 秒到 15 秒太短没意义太长告警不敏感。我接手过一个内部监控项目最初是每次请求都现读 /proc监控平台每 10 秒拉一次服务器一多/proc 读压力直接反映在 sys 时间上。改成快照模式后系统负载肉眼可见地降下来。这个教训我一直记得sysinfo 这类工具核心不是“能读”而是“读的时机可预期”。如果你想让数据更容易集成可以在 handler 里再加一个format参数支持 text 或 json。text 格式给命令行直接 curl 看json 格式给监控系统解析。再往下就是加配置项、信号处理、日志库这些我就不展开了希望帮到你。本文还有配套的精品资源点击获取

相关新闻

EPLAN Harness proD 2023:从图形驱动到数据驱动的线束设计范式革命

EPLAN Harness proD 2023:从图形驱动到数据驱动的线束设计范式革命

1. 这不是一次普通升级:EPLAN Harness proD 2023 的底层逻辑重写EPLAN Harness proD 2023 的发布,在电气线束工程圈子里没引发“哇哦”式的刷屏,反而让一批老用户在内部群聊里反复确认:“真不是补丁包?真重构了内核&am…

2026/10/13 16:59:52 阅读更多 →
Java聊天室开发实战:Socket多线程与群聊私聊完整实现

Java聊天室开发实战:Socket多线程与群聊私聊完整实现

简介:一款基于Java的实时聊天室项目,界面完整,提供群聊、私聊与在线用户列表功能,适合正在学习Java网络编程、多线程及GUI开发的初学者,也可作为课程设计与毕业设计的参考原型。压缩包内含42个文件,其中14个…

2026/10/13 16:59:52 阅读更多 →
哈特曼波前传感器标定:MATLAB仿真与响应矩阵构建指南

哈特曼波前传感器标定:MATLAB仿真与响应矩阵构建指南

简介:这是一份面向自适应光学与波前传感研究者的MATLAB仿真资源,围绕哈特曼波前传感器的标定与模式复原展开,核心解决Zernike多项式标定、Zernike模式复原过程以及DM(变形镜)响应函数广义逆求解等关键问题。资源共18个…

2026/10/13 16:59:52 阅读更多 →

最新新闻

fiji-win64 安装、宏脚本与插件管理:ImageJ 生物图像分析实战指南

fiji-win64 安装、宏脚本与插件管理:ImageJ 生物图像分析实战指南

简介:Fiji(ImageJ)是一个面向 Windows 六十四位系统的免安装图像处理软件,专门服务于科研和医学图像分析用户。解压后不需要安装即可运行,能够直接读取 Raw 格式原始数据,对八位以上的高动态范围图像支持良…

2026/10/13 17:32:45 阅读更多 →
DeepSeek V4.1 Flash:低延迟大模型推理引擎实战解析

DeepSeek V4.1 Flash:低延迟大模型推理引擎实战解析

1. 项目概述:这不是一次常规升级,而是一次“响应速度革命”最近在多个技术社区和开发者群聊里,几乎每天都能刷到类似这样的消息:“DeepSeek V4.1 Flash 内测开了”“Flash 版推理延迟压到 87ms”“实测比上一代 V4 Pro 在长文本场…

2026/10/13 17:32:45 阅读更多 →
SpringBoot多数据源读写分离实战:从配置到高可用路由

SpringBoot多数据源读写分离实战:从配置到高可用路由

1. 为什么多数据源不是“加个配置就行”的事——从一次线上慢查询告警说起“SpringBoot配置多数据源”这个标题,听起来像教科书里的一个练习题:改几行yml,贴几段代码,跑通就完事。但我在某电商中台项目里连续踩了三个月的坑之后才…

2026/10/13 17:32:45 阅读更多 →
DeepSeek V4.1 Flash工程解析:低延迟、省显存、长上下文稳态落地

DeepSeek V4.1 Flash工程解析:低延迟、省显存、长上下文稳态落地

1. 项目概述:一场模型性能与工程落地的双重验证 “DeepSeek V4.1 Flash”这个名称一出现,我就立刻在几个主流AI模型评测平台翻了三遍日志——不是因为名字有多炫,而是它在OpenRouter实时排行榜上连续72小时稳居Top 1,且综合得分比…

2026/10/13 17:32:45 阅读更多 →
Django插画鲜花商城系统:从电商设计到全栈实现

Django插画鲜花商城系统:从电商设计到全栈实现

插画鲜花商城系统,听名字就能猜个大概——用户端是一个走插画视觉风格的花店商城,可以浏览花束、下单买花;管理端是常规的商品、订单、用户管理。这类项目在Django毕设里属于典型的"全栈电商平台"型题目,覆盖了用户认证…

2026/10/13 17:32:45 阅读更多 →
Spring Boot汽车销售服务管理系统:从数据库设计到前后端部署全解析

Spring Boot汽车销售服务管理系统:从数据库设计到前后端部署全解析

最近有不少同学在挑毕业设计题目,我的建议是别一上来就找那种花里胡哨的“人工智能区块链”标题,先问问自己:这系统我能不能完整讲清楚、能不能真正跑起来。汽车销售服务管理系统就是这么个经典选题——业务脉络清晰,技术栈主流&a…

2026/10/13 17:31:43 阅读更多 →

日新闻

物联网系统集成避坑指南:从选型到验收的关键要点

物联网系统集成避坑指南:从选型到验收的关键要点

做了这么多年物联网系统集成的项目,我最大的感受是,大部分坑不是出在技术前沿,而是出在一些看起来很平常的地方。设备选了便宜的、协议没问清楚、现场没摸透、验收标准写得含糊——这些细枝末节,最后都会变成延期、超支和扯皮的大…

2026/10/13 0:00:57 阅读更多 →
ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

如果你玩ESP32有一阵子了,很难不碰到舵机控制这道坎。做智能小车要转方向,做机械臂要抬关节,做云台要偏航俯仰,背后都是同一个东西在干活:舵机。而我见过太多人卡在“代码能编译、舵机就是不听话”这个阶段&#xff0c…

2026/10/13 0:00:57 阅读更多 →
CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

1. 为什么CAN总线至今仍是工业现场的“硬通货”?——从汽车底盘到智能温室的真实需求你有没有拆过一辆老款燃油车的中控台?或者调试过某高校实验室里那台跑着Modbus协议却频频丢帧的PLC控制柜?又或者,在某个农业物联网项目里&…

2026/10/13 0:00:57 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/13 2:54:56 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/13 16:22:04 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/13 1:58:08 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 21:05:09 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 14:57:39 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 18:11:17 阅读更多 →