欢迎呀! 👋

Go1.25值得关注的三点

更新到go1.25 只需这三行命令即可 1wget https://dl.google.com/go/go1.25.0.linux-amd64.tar.gz 2rm -rf /usr/local/go 3tar -C /usr/local -xzf go1.25.0.linux-amd64.tar.gz sync.WaitGroup 1func (wg *WaitGroup) Go(f func()) { 2 wg.Add(1) 3 go func() { 4 defer wg.Done() 5 f() 6 }() 7} 新增了一个Go方法,简单封装了原来略显麻烦的使用方式。 synctest 全新的专用于测试并发代码的包。 GOMAXPROCS 现在,GOMAXPROCS会优先根据 cgroup CPU 设置的带宽限制设置数量。

August 13, 2025

零成本搭建个人LLM路由网关

简单总结一下我是如何使用各家的大语言模型api的,之前很长一段时间使用newapi聚合各家免费的api。但是现在,主流厂商基本都已经支持openai格式调用,而且对于个人来讲,newapi很多功能都是冗余的,所以想自己写一个api负载均衡满足日常使用。 llmio 我将这个项目命名为llmio,后端由go语言实现,前端由qwen3-code + vibe coding实现,只支持openai格式。项目十分简单,通过单独设置model与provider,一个model对应n个provider。 每次接收到请求根据不同provider的权重随机选择一个,替换请求体中的原始model字段为provider设置的model,并使用go标准库的io.TeeReader(body, pw)将响应body流同时转发给客户端与日志记录。 最高效实现负载均衡代理的同时,也方便开发者查看每次请求的各种数据。 部署 项目使用github action自动构建了docker镜像,最新版为0.2.3,可以使用docker compose一键部署,数据使用sqllite保存在/app/db文件夹下的llmio.db文件中,方便一键迁移。内存占用在20m左右,十分轻量。 1services: 2 llmio: 3 image: atopos31/llmio:latest 4 ports: 5 - 7070:7070 6 volumes: 7 - ./db:/app/db 8 environment: 9 - GIN_MODE=release 10 - TOKEN=<YOUR_TOKEN> 当然,如果你没有云服务器,推荐使用sealos部署,注册就送10元额度,每天仅需0.08元。 注意,环境变量中的TOKEN同时负责api以及后台管理的鉴权。 ...

August 10, 2025

React Agent与MCP

2025年的今天,大语言模型的能力早已不再限于chatbot(只会聊天),各家模型都在文本预测的基础上扩展LLM的能力,例如Structured Outputs(结构化输出),Function calling(函数调用),MCP(模型上下文协议),同时,有人提出一种结合LLM思考与行动的协同机制-React。 React Agent 通过让LLM循环执行 推理(Reasoning)->行动(Action)->观察(Observation) 来完成任务。 本质上,可以用下面这段最小代码解释: 1for { 2 response := callLLM(context) 3 if response.ToolCalls { 4 context = executeTools(response.ToolCalls) 5 } 6 if response.Finished { return } 7} ReAct: Synergizing Reasoning and Acting in Language Models eino-React实现 Function calling LLM自身训练的结构化输出能力以及通过openai-api服务实现,让LLM能够按照指定格式输出json格式的数据,来表明自己需要去使用什么函数,参数是什么,同时支持流式生成。 例如: 之后你应该在输入的messages里面加入除user,assistant的另一个角色,名为tool,tool的content内容为函数调用结果,至于函数是如何调用,LLM和openai-api服务并不参与,由开发者执行。此时再次对话,LLM会根据上下文中函数调用结果生成回答。 openai-function-calling MCP MCP (Model Context Protocol)是一种开放协议,用于标准化应用程序如何向大型语言模型(LLMs)提供上下文。可以将 MCP 想象为 AI 应用的 typec 接口。正如 typec 提供了一种标准化的方式将您的设备连接到各种外设和配件,MCP 也提供了一种标准化的方式,将 AI 模型连接到不同的数据源和工具。 ...

July 22, 2025

关于Golang新增的迭代器

在Go1.18版本时,Go新增了泛型支持,开发者可以不限于内置数据类型(map slice chanel string),来自定义泛型数据类型。 但在Go1.22之前,range关键字只能用来遍历map slice chanel string,直到Go1.22版本支持了int类型。 在Go1.23版本更新后,range加入了三种函数类型的支持,分别为 1func(yield func() bool) 2func(yield func(K) bool) 3func(yield func(K, V) bool) 其中两种已经被定义在标准库iter中。 range现在可以遍历这三种函数类型,这三种函数分别接收一个0-2个参数并返回bool的函数类型参数,与之对应的range形式为 1for range func(yield func() bool) { _ = yield } { 2 //do something 3} 4for k := range func(yield func(k int) bool) { _ = yield } { 5 _ = k 6 //do something 7} 8for k, v := range func(yield func(k, v int) bool) { _ = yield } { 9 _ = k 10 _ = v 11 //do something 12} 上面的代码在Go1.23中可以顺利通过编译,你可能会很困惑,这样做有什么用? ...

July 17, 2025

为什么选择Golang?

假设你作为一个小白去论坛上问,我应该学习那门编程语言? 有人可能会说,你必须去学C语言!因为这个世界上所有软件底层都是C写的!不懂C语言的不是一个合格的程序员!还有人可能会说,来学Python吧,Python入门简单,可以很快让你感受到编程的乐趣,也有人会让你学习Java,然后什么跨平台啊,一次编写到处运行,面向对象哦,巴拉巴拉。。。 相信这是大多数人的回答,很多人说C/C++的性能好但是学起来难,Python语言简单易学但是性能差,js从前端客户端到后台,全是js实现,Java可以一次编写到处运行,但是同js一样拖着虚拟机,吃内存! 那么,有没有一种语言,既有高性能,又有简单的语法,还方便跨平台,并且不用拖着笨重的运行时/虚拟机吃内存呢? 有的兄弟,有的,不过像这么优秀的语言可没有9门,恰好呢本文的主角Golang满足了这些苛刻的要求。 在2025年的今天,Golang在TIOB排行第7名,并且仍保持上升的趋势,成为最流行的编程语言之一。 一门简单的语言 那有人要问,Golang它怎么就简单了?这里我要说,一门语言的简单应该体现在多个方面。 快速搭建开发环境 如果你学过c/c++,你就会发现搭建开发环境实在是很复杂,比如,gcc和clang?选哪个编译器?makefile是什么?我怎么代码补全?怎么有些ide还内置编译器啊?卧槽你用的什么C标准,我编译不过去! 如果是Golang,那你和我的go run说去吧,一键安装sdk,gopls现代化lsp帮你补全代码,版本随便升级,依旧编译成功! 语法简单易学 最安全的代码并非优美、巧妙或优雅的代码,而是枯燥乏味的代码。 – 《无聊胜过美丽》 Go 语言就奉行这种理念,故意去除了那些富有表现力或优雅的写法,只保留简洁和可读的写法。没有类型体操和各种魔法注解,即使是新手小白也可以读懂三方库源码。这使得代码易于审查、难于滥用,不容易发生安全漏洞。语言本身只有大约25个关键字,相比之下,C++有近百个关键字,Java也有50多个。 现代化,统一的包管理器 c/c++: 我想找个三方库,一会cmake一会xmake,不同系统还有不同的标准库! Python: conda? pip? uv? venv虚拟环境?怎么包都是c/c++写的啊,乱七八糟! Java: gradle? maven? 我的JDBC升级了怎么连接不上数据库? js: npm? yarn? node?浏览器?我的npm包又冲突了! Golang的包管理是去中心化的,你不必上传到由任何组织管理的中央仓库,只需要一个公开的git仓库,用git tag控制版本,任何人都可以直接通过go get引用你的代码。同时,Golang官方提供缓存,不必担心git仓库删库跑路。 跨平台兼容 也许你听说Java所谓的一次编写,到处运行,但是这真的是跨平台吗?依我看来,Java这种语言是伪跨平台,你的目标平台必须拥有jre,依赖于运行时才可以到处运行。 那Golang的跨平台呢,相比于Java,Golang是纯正的编译性语言,它没有字节码这种中间产物,但是golang做到了世界上最强的交叉编译能力(标准库完全使用纯golang实现,可以不依赖libc),go build一键生成不同平台的可执行文件,命令go tool dist list可以查看golang支持的平台,几乎可以实现一次编写,随处编译!。 协程与网络IO友好 golang标准库内置的net包非常适合网络IO开发,无论是TCP/UDP还是应用层的HTTP,仅使用标准库就可完全满足小型网络服务程序的开发,我们经常使用科学上网工具,比如clash,其内核均使用golang开发。同时,golang使用协程替代其他语言中的线程模型,非常适合IO密集型的并发任务,天生高性能。

June 4, 2025

Powershell美化

使用vscode打开配置文件 1code $PROFILE 编写Prompt函数 该函数返回值即为powersehll显示效果。 1function Prompt { 2 $dir = $PWD.Path 3 $branch = "" 4 if (Test-Path "${dir}/.git/HEAD") { 5 $head = Get-Content "${dir}/.git/HEAD" 6 $branch = $head -replace 'ref: refs/heads/', '' 7 $branch = " git:($branch)" 8 } 9 10 $currentTime = Get-Date -Format " HH:mm:ss" 11 12 # 获取当前路径的最后一级文件夹 13 $currentDir = Split-Path (Get-Location) -Leaf 14 if ($dir -eq $env:userprofile) { 15 $currentDir = "~" 16 } 17 18 19 $batteryInfo = Get-CimInstance -ClassName Win32_Battery 20 $battery = "" 21 if ($batteryInfo.BatteryStatus -eq 2) { 22 $battery = " ⚡" + $batteryInfo.EstimatedChargeRemaining + "%" 23 } else { 24 $battery = " 🔋" + $batteryInfo.EstimatedChargeRemaining + "%" 25 } 26 27 $promptString = "➜ " + $currentDir 28 29 "`e[1;32m" + $promptString +"`e[1;33m" + $battery + "`e[1;36m" + $currentTime + "`e[1;34m" + $branch + "`e[m " 30} 效果 ...

May 22, 2025

记录参加第五届CCPC辽宁省赛

很荣幸参加了这次大连理工大学举办的CCPC辽宁省赛,虽然没有获奖,但是能体验一次线下xcpc比赛的经历我已经很满足了。

November 4, 2024

Linux系统程序设计实验记录

学校里开设的稍微有点用的一节课,所有代码均在ubuntu20.04下测试成功。 文件操作 1、利用creat()、open()和close()函数进行系统调用,实现创建、打开和关闭一个文件。 (1)以可读写方式新建并关闭一个文件“stu.txt”,如果成功则返回新建文件的文 件名,不成功则输出错误提示信息。 (2) 以可读写方式打开并关闭一个文件“file.txt”,如果成功则返回文件的文件名, 不成功则输出错误提示信息。 1#include <sys/stat.h> 2#include <fcntl.h> 3#include <unistd.h> 4#include <stdio.h> 5 6int main() 7{ 8 const char *stufilename = "stu.txt"; 9 int stufd = creat(stufilename, S_IRWXG); 10 if (stufd == -1) 11 { 12 printf("%s creat failed\n", stufilename); 13 } 14 close(stufd); 15 16 const char *filename = "file.txt"; 17 int filefd = open(filename, O_RDWR | O_CREAT | O_TRUNC, 0777); 18 if (filefd == -1) 19 { 20 printf("%s open failed!\n", filename); 21 } 22 23 return 0; 24} 2、编程实现一个简单的学生信息管理程序: (1)从键盘输入3个学生信息(学号、姓名、年龄),存放于结构体数组中,将结 构体写入文件“stu.txt”中。 (2)从键盘输入某个学生的学号,从“stu.txt”文件中读出指定学号的学生的全部 信息并显示。 (3) 实现人机交互操作:可以循环查询并显示查询结果,直到用户不再操作,结 束程序运行。 ...

September 26, 2024

使用Python在0.96oled上显示状态信息

查看引脚定义 依赖安装 1pip install psutil luma.core luma.oled 代码 1import subprocess 2import time 3import socket 4import psutil 5from luma.core.interface.serial import i2c, spi 6from luma.core.render import canvas 7from luma.oled.device import ssd1306, ssd1325, ssd1331, sh1106 8 9serial = i2c(port=2, address=0x3C) 10device = ssd1306(serial) 11 12def get_cpu_temperature(): 13 with open('/sys/class/thermal/thermal_zone0/temp', 'r') as file: 14 temperature = int(file.read()) / 1000.0 15 return temperature 16 17cmd = "hostname -I | cut -d\' \' -f1" 18IP = subprocess.check_output(cmd, shell=True).decode().strip() 19 20 # 将字节转换为 GB 21def bytes_to_gb(bytes): 22 return bytes / (1024 ** 3) 23 24# 将字节转换为合适的单位 25def convert_size(size): 26 # 定义单位列表 27 units = ['B', 'KB', 'MB', 'GB', 'TB'] 28 29 # 迭代转换单位直到小于1024 30 for unit in units: 31 if size < 1024: 32 return f"{size:.2f} {unit}" 33 size /= 1024 34 35 return f"{size:.2f} {units[-1]}" 36 37# 获取初始的输入输出流量 38net_io_start = psutil.net_io_counters() 39 40while True: 41 with canvas(device) as draw: 42 cmd = "hostname -I | cut -d\' \' -f1" 43 current_IP = subprocess.check_output(cmd, shell=True).decode().strip() 44 timestamp_start = time.time() 45 46 # 等待一秒钟 47 time.sleep(1) 48 49 cpu_usage = psutil.cpu_percent(interval=1) 50 cpu_temperature = get_cpu_temperature() 51 52 # 获取内存占用情况 53 memory = psutil.virtual_memory() 54 55 # 获取总内存大小(以 GB 为单位) 56 total_memory = bytes_to_gb(memory.total) 57 58 # 获取可用内存大小(以 GB 为单位) 59 available_memory = bytes_to_gb(memory.available) 60 61 # 获取已使用内存大小(以 GB 为单位) 62 used_memory = bytes_to_gb(memory.used) 63 64 # 获取内存使用率 65 memory_usage = memory.percent 66 67 disk = psutil.disk_usage('/') 68 total_disk = bytes_to_gb(disk.total) 69 free_disk = bytes_to_gb(disk.free) 70 71 # 获取当前的输入输出流量和时间戳 72 net_io_current = psutil.net_io_counters() 73 timestamp_current = time.time() 74 75 # 计算时间间隔 76 time_interval = timestamp_current - timestamp_start 77 78 # 计算上行和下行网速 79 upload_speed = (net_io_current.bytes_sent - net_io_start.bytes_sent) / time_interval 80 download_speed = (net_io_current.bytes_recv - net_io_start.bytes_recv) / time_interval 81 upload_speed = upload_speed / 2 82 83 # 切换单位 84 upload_speed = convert_size(upload_speed) 85 download_speed = convert_size(download_speed) 86 87 88 # 更新初始的输入输出流量 89 net_io_start = net_io_current 90 91 draw.rectangle(device.bounding_box, outline="white", fill="black") # 让屏幕周围显示一个框 92 draw.text((2,1),f"IP:{current_IP}",fill="white") 93 draw.text((2,11),f"CPU_use:{cpu_usage}%",fill="white") 94 draw.text((2,21),f"CPU_tem:{cpu_temperature:.2f}°C",fill="white") 95 draw.text((2,31),f"MEM:{memory_usage:.2f}%",fill="white") 96 draw.text((2,41), f"DISK:{free_disk:.2f}/{total_disk:.2f}GB", fill="white") 97 draw.text((2,51), f"NET:{upload_speed}/{download_speed}", fill="white") 运行 ...

December 26, 2023

Miio操作米家台灯

python-miio 是一个由第三方实现的开源 miIO / MIoT 协议库,兼容大多数小米IoT智能家居设备,python-miio 还附带提供了基于命令行的调试工具 miiocli,供感兴趣的终端用户直接进行调用,本文将作为重点进行讲解。 先决条件 局域网内一台安装python环境的主机。 下面是我的配置 主机:nanopc-t4 系统:unbuntu18.04 Python版本:3.6.8 安装python-miio库 1sudo pip3 install python-miio 如果没有pip3工具请先安装python-pip3 1sudo apt-get install python-pip3 安装完成后,输入miiocli,如图所示即可。 获取设备信息 点击下载token_extractor 按照命令行提示输入你的账号密码以及国家即可。 开始操作 米家台灯属于wifi直连的米家设备,可以通过plug指令进行控制,目前我只尝试过三种指令,获取设备状态,开灯,关灯。 根据miio plug --help的提示信息,plug类型设备支持下列操作: 1Commands: 2 info Get miIO protocol information from the device. 3 off Power off. 4 on Power on. 5 raw_command Send a raw command to the device. 6 set_wifi_led Set the wifi led on/off. 7 status Retrieve properties. 8 usb_off Power off. 9 usb_on Power on. 更新 针对于米家的灯系列–yeelight,其实有更详细的的操作 miiocli yeelight ...

May 23, 2023