<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Posts on 虫子樱桃</title>
    <link>https://czyt.tech/post/</link>
    <description>Recent content in Posts on 虫子樱桃</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>zh</language>
    <lastBuildDate>Sat, 09 May 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://czyt.tech/post/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>MacOS常用软件</title>
      <link>https://czyt.tech/post/macos-awesome-software/</link>
      <pubDate>Mon, 22 Jul 2024 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/macos-awesome-software/</guid>
      <description>聊天和社交 QQ - 80，90的青春。 微信 - 国内TOP1社交软件。brew install --cask wechat 钉钉 - 阿里巴巴出品协同办公软件。 企业微信 - 腾讯出品协同办公软件。 飞书 - 字节跳动出品协同办公软件。 Telegram - 地下社交软件，通信加密。 X（原twitter） - 地下社交软件，了解国内外大事。 XDeck 𝕏桌面客户端 Franz 多合一聊天工具 邮箱工具 Spark 输入法及键盘扩展 AutoSwitchinput 当你在Mac上打开不同的软件的时候，它可以自动帮你切换中文和英文输入法 Input Source Pro，推友开发的一个输入法自动切换工具 Tickeys 键盘打字风格模拟应用, 支持 Cherry轴等多种风格. keycue 快捷键辅助应用, 帮助记忆快捷键. KeyKey macOS 上优雅好用的键盘打字练习。 Karabiner-Elements 键盘映射工具 输入法 rime 可以下载鼠鬚管 Squirrel brew install squirrel-app 可以集成雾凇拼音更好用，具体的步骤如下：
1.打开 Terminal 进入 cd &amp;quot;$HOME/Library“ 2 .保留自带的配置目录 mv Rime Rime.old或者直接干掉这个目录
3.下载配置
git clone --depth=1 https://github.</description>
    </item>
    
    <item>
      <title>Arch Linux 常用软件</title>
      <link>https://czyt.tech/post/arch-awesome-software/</link>
      <pubDate>Wed, 23 Feb 2022 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/arch-awesome-software/</guid>
      <description>本文部内容理论上基于Arch的发行版都可以使用本文进行安装。推荐的发行版本
Manajro EndeavourOS CachyOS 如果您安装好了manajro但是又不想重装系统，可以试下这个脚本来将Manjaro自动转换为Arch。此外，DHH的omarchy (github)也值得一试~
Arch 安装后必装的软件 通过archinstall 安装以后，是没图形界面的。需要安装下面的一些软件和配置
安装时，声音后端的选择：
PulseAudio，历史悠久、最为常用； PipeWire，新生代，采用全新架构，整合多种音频后端（PulseAudio、ALSA和JACK），提供低延迟的音频体 连接无线网 iwctl # 进入交互式命令行 device list # 列出无线网卡设备名，比如无线网卡看到叫 wlan0 station wlan0 scan # 扫描网络 station wlan0 get-networks # 列出所有 wifi 网络 station wlan0 connect wifi-name # 进行连接，注意这里无法输入中文。回车后输入密码即可 exit # 连接成功后退出 启用网络 systemctl enable dhcpcd systemctl enable wpa_supplicant systemctl enable NetworkManager 蓝牙 sudo systemctl enable --now bluetooth 如果没这个服务，可能需要通过 paru -S bluetooth进行安装。
如果需要启用蓝牙音频支持，请安装 paru -S pulseaudio-bluetooth
蓝牙高级管理工具 paru -S blueman</description>
    </item>
    
    <item>
      <title>懒猫微服 Go-SDK 使用指南</title>
      <link>https://czyt.tech/post/lazycat-go-sdk-usage-guide/</link>
      <pubDate>Sun, 01 Feb 2026 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/lazycat-go-sdk-usage-guide/</guid>
      <description>本文基于 apps-scheduler 和 cat-led 两个实际项目，介绍懒猫微服 Go-SDK 的使用方法。
SDK 简介 懒猫微服 Go-SDK（gitee.com/linakesi/lzc-sdk）是懒猫微服平台提供的 Go 语言 SDK，允许应用通过 gRPC 与懒猫微服系统交互。SDK 封装了以下核心能力：
应用管理（PkgManager）：查询、启动、暂停应用 用户管理（Users）：查询用户信息 设备管理（Box）：查询设备信息、控制 LED、关机/重启 项目结构 使用 Go-SDK 开发的懒猫应用推荐采用如下项目结构：
your-app/ ├── cmd/ │ └── your-app/ │ └── main.go # 应用入口 ├── internal/ │ ├── web/ │ │ └── server.go # Web 服务器配置与路由 │ ├── handlers/ │ │ ├── app.go # SDK 调用相关 handler │ │ └── userinfo.go # 用户信息 handler │ ├── biz/ │ │ └── usecase.</description>
    </item>
    
    <item>
      <title>go-kratos使用备忘</title>
      <link>https://czyt.tech/post/go-kratos-usage-memo/</link>
      <pubDate>Fri, 12 Aug 2022 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/go-kratos-usage-memo/</guid>
      <description>我搭建的一个kratos项目模板，欢迎使用，仓库地址
需要特别注意的一些建议 API路由覆盖的问题 比如有两个接口 A get /v1/user/{user_id}和 B get /v1/user/profile如果A定义在B之前，那么B可能会被A覆盖路由。需要将A放到B之前。
JWT使用的建议 摘自极客时间课程《高并发系统实战课》
通讯过程必须使用 HTTPS 协议，这样才可以降低被拦截的可能。 要注意限制 token 的更换次数，并定期刷新 token，比如用户的 access_token 每天只能更换 50 次，超过了就要求用户重新登陆，同时 token 每隔 15 分钟更换一次。这样可以降低 token 被盗取后给用户带来的影响。 Web 用户的 token 保存在 cookie 中时，建议加上 httponly、SameSite=Strict 限制，以防止 cookie 被一些特殊脚本偷走。 配置文件 配置文件校验 配合buf的validate可以方便地进行配置文件的校验，在程序启动之前就对配置文件进行一次校验。下面是一个简单的proto配置定义
syntax = &amp;#34;proto3&amp;#34;; package conf; import &amp;#34;buf/validate/validate.proto&amp;#34;; import &amp;#34;google/protobuf/duration.proto&amp;#34;; option go_package = &amp;#34;github.com/tpl-x/kratos/internal/conf;conf&amp;#34;; message Bootstrap { Server server = 1; Data data = 2; Log log = 3; } message Server { message HTTP { string network = 1; string addr = 2; google.</description>
    </item>
    
    <item>
      <title>Mutagen使用技巧</title>
      <link>https://czyt.tech/post/mutagen-usage-tips/</link>
      <pubDate>Sat, 09 May 2026 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/mutagen-usage-tips/</guid>
      <description>Mutagen 是一个高性能文件同步 + 网络转发工具。和 rsync、scp 不同，它的同步是持久的、双向的、实时的，网络断开会自动重连，不需要人工干预。本文面向开发者和 Docker 用户，覆盖三种传输层的实际使用技巧。整理 By claude
核心概念：两个能力，三种传输 Mutagen 做两件事：
文件同步（mutagen sync）：在两个端点之间实时同步目录，支持双向、单向多种模式，算法基于 rsync 的差异传输，只传变化的部分。
网络转发（mutagen forward）：在两个端点之间建立持久的网络隧道，支持 TCP、Unix socket、Windows Named Pipe。
这两件事都支持三种传输层，可以任意搭配：
传输层 适用场景 Local 本机两个路径之间，或本机作为某端 SSH 远程 Linux/Mac 服务器，复用 OpenSSH Docker 本地或远程的容器，复用 docker exec 两端可以是不同传输层的任意组合——比如左边是本地路径，右边是远程容器。
安装与启动 # macOS brew install mutagen-io/mutagen/mutagen # Linux / Windows # 下载二进制：https://github.com/mutagen-io/mutagen/releases # aur 使用 pacman -S mutagen.io-bin # 启动守护进程（后台常驻，重启后自动恢复会话） mutagen daemon start 一、Local 传输 Local 是最简单的传输层，直接用本地文件路径和网络地址。虽然看起来平淡，但有几个实用场景不容忽视。
URL 格式 同步用本地路径（绝对或相对都行），转发用网络端点：
# 同步 .</description>
    </item>
    
    <item>
      <title>go-libp2p简明教程</title>
      <link>https://czyt.tech/post/go-libp2p-quick-guide/</link>
      <pubDate>Thu, 09 Apr 2026 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/go-libp2p-quick-guide/</guid>
      <description>从零开始，手把手带你构建 P2P 网络应用,本文由claude code编写
1. 核心概念扫盲 在写代码之前，先花 5 分钟理解几个关键词。这些概念会贯穿整个教程。
PeerID —— 节点的&amp;quot;身份证&amp;quot; 每个 libp2p 节点在启动时都会生成（或加载）一对密钥（默认是 Ed25519）。PeerID 就是公钥的哈希值，是全网唯一的节点标识。
QmYyQSo1c1Ym7orWxLYvCrM2EmxFTANf8wXmmE7DWjhx5N Multiaddr —— 节点的&amp;quot;地址簿&amp;quot; 传统 TCP 地址长这样：192.168.1.1:4001。libp2p 的多地址（Multiaddr）更丰富，包含了协议栈信息：
/ip4/192.168.1.1/tcp/4001/p2p/QmYyQSo1c1Ym7orWxLYvCrM2EmxFTANf8wXmmE7DWjhx5N └─────────────┘ └────────┘ └─────────────────────────────────────────────────────┘ IP 地址 TCP 端口 PeerID 也可以是：
/ip4/0.0.0.0/tcp/0 —— 随机端口的 TCP /ip4/0.0.0.0/udp/0/quic-v1 —— QUIC 协议 /dns4/example.com/tcp/443/wss —— WebSocket over TLS Host —— 你的节点实例 host.Host 是 libp2p 的核心对象，可以理解为&amp;quot;这台机器在 P2P 网络中的代理&amp;quot;。所有操作都从它出发：监听连接、发起连接、注册协议处理器等。
Stream —— 连接上的&amp;quot;通道&amp;quot; 两个节点建立连接后，可以在同一条底层连接上开多条流（Stream），每条流对应一个协议（类似 HTTP/2 的多路复用）。
Protocol ID —— 协议的&amp;quot;频道号&amp;quot; 每条流都有一个协议 ID，是一个字符串，用于标识通信双方在&amp;quot;聊什么话题&amp;quot;：</description>
    </item>
    
    <item>
      <title>vanguard-go简明教程 by Claude</title>
      <link>https://czyt.tech/post/vanguard-go-quick-guide-by-claude/</link>
      <pubDate>Thu, 09 Apr 2026 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/vanguard-go-quick-guide-by-claude/</guid>
      <description>用一个 Go 服务器同时支持 REST、gRPC、gRPC-Web 和 Connect 客户端。本文使用claude code编写
什么是 vanguard-go？ vanguard-go 是 ConnectRPC 团队开发的一个 Go 中间件库，核心功能是协议转码（Transcoding）：它能让你只写一套 RPC 服务实现，就同时支持多种客户端协议：
客户端协议 是否支持 Connect Protocol ✅ gRPC ✅ gRPC-Web ✅ REST + JSON（HTTP 转码） ✅ 与 gRPC-Gateway 不同，vanguard 直接作为 net/http 中间件运行，无需额外的代理进程，性能更高，集成更简单。
核心概念 理解这三个概念就掌握了 vanguard 的精髓：
Service（服务）：对一个 Protobuf RPC 服务的配置包装，包含服务的 schema（用于协议转换）和实际的 HTTP 处理器。
Transcoder（转码器）：将一组 Service 包装成 http.Handler，自动处理所有协议转换逻辑，也充当路由器。
HTTP Transcoding Annotations（HTTP 转码注解）：在 .proto 文件里用 google.api.http 注解将 RPC 方法映射到 RESTful 路径，这是支持 REST 客户端的关键。
快速开始 1. 安装依赖 go get connectrpc.</description>
    </item>
    
    <item>
      <title>Codex快速实践</title>
      <link>https://czyt.tech/post/codex-quick-practice/</link>
      <pubDate>Mon, 06 Apr 2026 11:36:50 +0800</pubDate>
      
      <guid>https://czyt.tech/post/codex-quick-practice/</guid>
      <description>必备插件 super powers oh-my-codex 提高主动性 Codex使用的问题在于一直确认，试过goalx等工具，效果不好。直到看到张汉东老师的这个AGENTS.md的gist 英文版
放到 ~/.codex下面或者项目根目录，文件名AGENTS.md
## 工作哲学 你是这个项目的工程协作者，不是待命的助手。参考以下风格： - **John Carmack 的 .plan 文件风格**：做完事情之后报告你做了什么、 为什么这么做、遇到了什么权衡。不问&amp;#34;要不要我做&amp;#34;——你已经做了。 - **BurntSushi 在 GitHub 上的 PR 风格**：一次交付是一个完整的、 自洽的、可以被评审的单位。不是&amp;#34;我先试一个你看看&amp;#34;，而是 &amp;#34;这是我的方案，理由如下，欢迎指出问题&amp;#34;。 - **Unix 哲学**：做一件事，做完，然后闭嘴。过程中的汇报不是礼貌， 是噪音；结果时的汇报才是工程。 ## 你要服从的对象 按优先级： 1. **任务的完成标准** —— 代码能编译、测试能通过、类型能检查、 功能真的工作 2. **项目的既有风格和模式** —— 通过读现有代码建立 3. **用户的明确、无歧义指令** 这三样高于&amp;#34;让用户感到被尊重地征询了意见&amp;#34;的心理需要。 你对任务的正确性有承诺，这个承诺**高于**对用户情绪的讨好。 两个工程师可以就实现细节争论，因为他们都在服从代码的正确性； 一个工程师对另一个工程师每一步都说&amp;#34;要不要我做 X&amp;#34;不是尊重， 是把自己的工程判断卸载给对方。 ## 关于停下来询问 停下来问用户只有一种合法情况： **存在真正的歧义，继续工作会产出与用户意图相反的成果**。 不合法的情况： - 询问可逆的实现细节（你可以直接做，做错了就改） - 询问&amp;#34;下一步要不要&amp;#34;——如果下一步是任务的一部分，就去做 - 把可以自己判断的风格选择包装成&amp;#34;给用户的选项&amp;#34; - 工作完成后续问&amp;#34;要不要我再做 X、Y、Z&amp;#34;——这些是事后确认， 用户可以说&amp;#34;不用&amp;#34;，但默认是做 实测，codex的主动性更强。
omx的魔力 安装</description>
    </item>
    
    <item>
      <title>在无头机器上设置vibe coding环境</title>
      <link>https://czyt.tech/post/setup-vibe-coding-on-headless-machine/</link>
      <pubDate>Fri, 03 Apr 2026 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/setup-vibe-coding-on-headless-machine/</guid>
      <description>最近我在好几台无桌面环境的机器上设置了vibe coding环境，作为记录。操作环境都是基于arch linux的服务器，没有图形界面，完全通过命令行操作。
安装mise 通过 paru -S mise 或者 yay -S mise 安装mise。 官方文档 https://mise.jdx.dev/getting-started.html
Shell配置 如果你使用的是zsh或者fish，需要参考官方文档进行相关的设置
fish 一键配置
curl https://mise.run/fish | sh # Installs mise and adds activation to ~/.config/fish/config.fish 或者手动在你的fish配置加入
# ~/.config/fish/config.fish if status is-interactive mise activate fish | source else mise activate fish --shims | source end zsh 一键配置
curl https://mise.run/zsh | sh # Installs mise and adds activation to ~/.zshrc 手动配置
# ~/.zprofile or ~/.zshrc eval &amp;#34;$(mise activate zsh --shims)&amp;#34; bash 一键配置</description>
    </item>
    
    <item>
      <title>我的 AI 采纳之旅【译】</title>
      <link>https://czyt.tech/post/my-ai-adoption-journey/</link>
      <pubDate>Thu, 05 Mar 2026 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/my-ai-adoption-journey/</guid>
      <description>本文原文地址,使用claude进行了翻译，作者是HashiCorp的创始人Mitchell Hashimoto。
作者：Mitchell Hashimoto　|　原文日期：2026年2月5日
我在采纳任何一款有价值的工具时，通常都会经历三个阶段：（1）低效期、（2）适应期，最终才到达（3）彻底改变工作流程乃至生活方式的顿悟期。
大多数情况下，我必须强迫自己熬过第一阶段和第二阶段——因为我通常已经有一套令自己满意且顺手的工作流程。引入新工具意味着额外的付出，我实在不想花这份力气，但出于对所在领域的全面性追求，我通常还是会去尝试。
这篇文章记录了我如何在 AI 工具链中找到真正价值的历程，以及我正在探索的下一步方向。在一片夸大其词、充斥炒作的声浪中，我希望这篇文章能呈现一种更细腻、更审慎的视角，如实反映我对 AI 的看法是如何随着时间推移而演变的。
本文完全由我亲手写就，字字出自本人之口。这句话放在这里本不必要，但鉴于文章的主题特殊，我想明确声明。
第一步：放弃聊天机器人 立即停止通过聊天机器人（如 ChatGPT、Gemini 网页版等）完成有实质意义的工作。聊天机器人确实有其价值，也是我日常 AI 工作流程的一部分，但在编程场景下，其效用极为有限——因为你基本上是寄希望于模型凭借预训练知识碰巧给出正确答案，而纠错则需要人工（即你本人）反复告知它哪里错了，效率极低。
我认为，几乎所有人与 AI 的第一次接触都是聊天界面。同样，几乎所有人第一次尝试用 AI 辅助编程，也都是向聊天界面输入需求、让它生成代码。
在我还是个坚定的 AI 怀疑论者时，我第一次发出&amp;quot;哇哦&amp;quot;的感叹，是将 Zed 命令面板的截图粘贴给 Gemini，让它用 SwiftUI 复现出来——它的表现之出色令我真正震惊。如今 Ghostty macOS 版中内置的命令面板，正是在 Gemini 几秒内为我生成的代码基础上，仅做了极少量改动后发布的。
但当我试图将这种成功经验复制到其他任务时，却屡屡失望。在存量代码库（brownfield project）的上下文中，聊天界面产出的结果往往很差，我发现自己在代码和命令输出的复制粘贴上来回折腾，效率明显低于亲自动手。
要真正发掘价值，你必须使用智能体（Agent）。智能体是业界公认的术语，指能够在对话循环中调用外部能力的大型语言模型（LLM）1。至少，该智能体必须具备以下能力：读取文件、执行程序，以及发起 HTTP 请求。
第二步：用智能体重现自己的工作 在探索历程的下一阶段，我尝试了 Claude Code。直说吧：最初我并不买账。每次会话产出的结果都不尽如人意，几乎每次都需要大量的后期修改，这比自己动手还要耗时。我读了不少博客文章、看了不少视频，但依然兴趣寥寥。
没有放弃，我强迫自己用智能体重做所有原本手动完成的提交（commit）。我字面意义上把每件事做了两遍：先手动完成，再与智能体较量，迫使它在质量与功能上达到相同水准（当然，不让它看到我的手动方案）。
这个过程极其痛苦，因为它妨碍了&amp;quot;把事情做完&amp;quot;这一最直接的目标。但我与非 AI 工具打交道的经验足够丰富，深知摩擦阻力是一种自然现象，不把精力耗尽就无法得出坚实可靠的结论。
然而，专业认知在磨砺中逐渐成形。我从第一性原理出发，很快就亲身验证了别人已有的发现——而正因为是自己发现的，底层理解也更为深刻：
将会话拆分为若干清晰、可执行的独立任务，切勿试图在一次超长会话中&amp;quot;一步画完猫头鹰&amp;quot;。 对于模糊的需求，应将工作分拆为独立的规划会话与执行会话，分步推进。 若为智能体提供校验其工作成果的手段，它在大多数情况下能够自主纠错，并有效防止功能退化（regression）。 更宏观地看，我也摸清了当时智能体的能力边界——它们擅长什么、不擅长什么，以及对于它们擅长的任务，如何获得满意的输出。
这一切带来了显著的效率提升——我开始自然而然地使用智能体，感觉不比自己亲手做更慢（尽管也没感觉更快，因为我大部分时间仍在充当&amp;quot;监工&amp;quot;）。
这里有一个值得反复强调的&amp;quot;负空间&amp;quot;：效率提升的一部分，恰恰来自于清楚地知道何时不该使用智能体。让智能体去尝试它很可能失败的任务，显然是巨大的时间浪费；而掌握这种判断力、主动规避，本身就是一种节省2。
第三步：下班前的智能体任务 为了进一步挖掘效率空间，我开始尝试一种新的工作模式：每天预留最后 30 分钟，用于启动一个或多个智能体任务。我的假设是：如果智能体能够在我无法工作的时间里取得实质进展，或许就能在时间之外创造时间。也就是说：与其在现有的工作时间内多做事，不如在原本&amp;quot;空置&amp;quot;的时间里多做事。
和之前一样，起初我觉得这既无效又令人烦躁。但我很快又梳理出了几类真正奏效的工作：
深度研究型会话：让智能体梳理某个领域，例如找出某种语言中采用特定许可证的所有库，并为每个库生成多页摘要，涵盖优缺点、开发活跃度、社区口碑等维度。 并行探索模糊构想：同时启动多个智能体，分别尝试我还没时间着手的不同想法。我并不指望它们产出可上线的成果，但希望它们能帮我在第二天真正着手时，提前发现一些&amp;quot;未知的未知&amp;quot;。 Issue 与 PR 的分类梳理：智能体善用 gh（GitHub CLI），我编写了一个简单脚本来并行启动多个智能体做 Issue 分类。我不允许智能体直接回复，只需要隔天早上看到报告，帮助我识别高价值或低难度的任务。 需要说明的是，我没有像某些人那样，让智能体整夜不停地循环运行。大多数情况下，任务在半小时内就会完成。但工作日下午的后半段，我通常已经精力耗尽、离开心流状态，个人效率大打折扣——将这段精力转移到启动智能体任务上，让我第二天早上能够&amp;quot;热启动&amp;quot;，比以往更快进入工作状态。</description>
    </item>
    
    <item>
      <title>掌控 LLM 输出：API 层的干预手段</title>
      <link>https://czyt.tech/post/llm-api-intervention-in-go/</link>
      <pubDate>Sat, 28 Feb 2026 18:32:07 +0800</pubDate>
      
      <guid>https://czyt.tech/post/llm-api-intervention-in-go/</guid>
      <description>你买不到模型的权重，但你可以在 API 层实施&amp;quot;外科手术式&amp;quot;控制。本文用 OpenAI Go SDK 演示每种干预手段在真实业务中的完整用法。
前置准备 go get github.com/openai/openai-go // client.go — 全文共用的客户端 package main import ( &amp;#34;github.com/openai/openai-go&amp;#34; &amp;#34;github.com/openai/openai-go/option&amp;#34; ) func newClient() *openai.Client { return openai.NewClient( option.WithAPIKey(&amp;#34;sk-...&amp;#34;), // 或读取 os.Getenv(&amp;#34;OPENAI_API_KEY&amp;#34;) ) } 1. System Message — 给模型装&amp;quot;人格芯片&amp;quot; 原理 System Message 是发给模型的&amp;quot;宪法&amp;quot;，在对话开始前设定角色、禁忌和回答格式。它不会被用户消息覆盖（模型会优先遵从）。
业务场景：客服机器人只允许回答产品相关问题 package main import ( &amp;#34;context&amp;#34; &amp;#34;fmt&amp;#34; &amp;#34;github.com/openai/openai-go&amp;#34; ) func customerServiceBot(userQuestion string) (string, error) { client := newClient() resp, err := client.Chat.Completions.New(context.Background(), openai.ChatCompletionNewParams{ Model: openai.F(openai.ChatModelGPT4o), Messages: openai.</description>
    </item>
    
    <item>
      <title>Bun ORM 全面指南：Go 语言高性能数据库操作利器</title>
      <link>https://czyt.tech/post/bun-orm-comprehensive-guide/</link>
      <pubDate>Mon, 02 Feb 2026 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/bun-orm-comprehensive-guide/</guid>
      <description>（本文内容基于 Bun ORM 官方文档 翻译整理）
1. 简介：什么是 Bun ORM？ Bun 是一个 SQL 优先的 Go 语言 ORM（对象关系映射）框架，支持 PostgreSQL、MySQL、MSSQL 和 SQLite。它旨在提供一种简单高效的方式来操作数据库，同时利用 Go 的类型安全特性并减少样板代码。
核心特性 基于标准库构建：构建在 Go 标准 database/sql 包之上 类型安全：提供类型安全的查询构建器，性能卓越 复杂关系支持：支持复杂的关系和连接操作 迁移支持：提供迁移和架构管理功能 强大的扫描能力：全面的数据扫描功能 钩子和中间件：支持钩子和中间件 生产就绪：经过广泛测试，可用于生产环境 为什么选择 Bun？ Bun 通过 SQL 优先 的理念区别于其他 Go ORM，不试图对开发者隐藏 SQL。这种方法具有以下优势：
可预测的查询：你确切知道生成的 SQL 是什么 高性能：对原始 SQL 的开销最小 渐进式采用：易于集成到现有代码库 灵活性：需要时可降级到原始 SQL 类型安全：大多数操作的编译时检查 2. 安装与配置 安装 Bun 要安装 Bun 和所需的数据库驱动：
# 核心 Bun 包 go get github.com/uptrace/bun@latest # 数据库驱动（选择一个或多个） go get github.</description>
    </item>
    
    <item>
      <title>在Dokploy中通过Cloudflare Tunnel发布应用</title>
      <link>https://czyt.tech/post/dokploy-behind-cloudflared/</link>
      <pubDate>Fri, 23 Jan 2026 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/dokploy-behind-cloudflared/</guid>
      <description>通过 Cloudflare Tunnel，你可以不需要公网 IP、不需要在路由器/防火墙开启 80 或 443 端口，就能安全地将 Dokploy 上的应用发布到互联网。
核心流程图 用户 -&amp;gt; Cloudflare 域名 (HTTPS) -&amp;gt; Cloudflare 隧道 -&amp;gt; Docker 内部网络 (HTTP) -&amp;gt; 你的应用容器
第一步：在 Cloudflare 创建隧道 (Tunnel) 登录 Cloudflare Zero Trust。 进入 Networks -&amp;gt; Tunnels -&amp;gt; Create a Tunnel。 选择 Cloudflared，起个名字（如 my-server）。 在安装页面，找到 Connector Token（那一长串字符串），复制备用。 第二步：在 Dokploy 中部署隧道服务 在 Dokploy 中新建一个 Compose 服务（建议命名为 cloudflare-tunnel），使用以下配置：
services: cloudflared: image: &amp;#39;docker.1ms.run/cloudflare/cloudflared:latest&amp;#39; environment: - &amp;#39;TUNNEL_TOKEN=你的TOKEN&amp;#39; # 建议在 Environment 变量中设置 networks: - dokploy-network # 必须加入此网络 restart: unless-stopped command: [&amp;#34;tunnel&amp;#34;, &amp;#34;--no-autoupdate&amp;#34;, &amp;#34;run&amp;#34;] networks: dokploy-network: external: true 第三步：部署应用 (以 Excalidraw 为例) 部署应用时，务必确保它与隧道在同一个 Docker 网络中，以便隧道能通过“服务名”找到它。</description>
    </item>
    
    <item>
      <title>Git Filer Repo快速指南</title>
      <link>https://czyt.tech/post/git-filer-repo-quick-start/</link>
      <pubDate>Tue, 13 Jan 2026 20:50:57 +0800</pubDate>
      
      <guid>https://czyt.tech/post/git-filer-repo-quick-start/</guid>
      <description>本文使用claude code编写，旨在提供一个详尽的 git-filter-repo 使用指南，涵盖安装、基础概念、路径和内容过滤、实用场景、高级功能、安全机制、完整工作流示例、故障排除、性能优化、常见错误与陷阱、与其他工具配合以及最佳实践总结等方面的内容。
什么是 git-filter-repo? git-filter-repo 是一个快速、功能强大的 Git 历史重写工具,是 git filter-branch 的官方推荐替代品。它由 Git 项目贡献者 Elijah Newren 开发,速度比 filter-branch 快 10-100 倍以上。
核心原理:
git fast-export &amp;lt;options&amp;gt; | filter | git fast-import &amp;lt;options&amp;gt; git-filter-repo 同时扮演管道编排者和中间过滤器的角色,基于 fast-export 和 fast-import 实现高效的历史重写。
为什么选择 git-filter-repo? vs git filter-branch 特性 git filter-branch git-filter-repo 速度 极慢(大型仓库几乎不可用) 快 10-100 倍 安全性 易出错,可能静默损坏数据 内置多重安全检查 易用性 复杂的 shell 语法 简洁的命令行参数 跨平台 依赖 shell,跨平台问题多 纯 Python,跨平台一致 官方态度 已废弃,不推荐使用 Git 官方推荐 Git 官方警告: filter-branch 的问题无法向后兼容地修复,强烈建议停止使用。</description>
    </item>
    
    <item>
      <title>Calude Code编写的Ent ORM 完整指南</title>
      <link>https://czyt.tech/post/ent-orm-guide-by-claude/</link>
      <pubDate>Fri, 12 Dec 2025 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/ent-orm-guide-by-claude/</guid>
      <description>本文由claude code生成。作为备忘录和分享，欢迎指正和补充。
一、Ent简介 Ent是一个简单但功能强大的实体框架，用于Go语言，使构建和维护具有大型数据模型的应用程序变得容易。 Ent是由Meta（Facebook）开源团队构建的ORM框架，提供了一个API，用于将任何数据库模式建模为Go对象。
核心特性 Ent的主要特性包括：
Schema As Code：将任何数据库模式建模为Go对象 轻松遍历任何图结构：运行查询、聚合并轻松遍历任何图结构 静态类型和显式API：100%静态类型和显式API，通过代码生成实现 多存储驱动支持：支持MySQL、PostgreSQL、SQLite和Gremlin 易于扩展：使用Go模板简单扩展和自定义 Ent是一个相当新的ORM，使用代码优先的方法，在Go代码中定义模式。Ent之所以流行，是因为它能够优雅地处理复杂的数据模型和关系。
二、快速开始 2.1 安装Ent # 初始化Go模块 go mod init myapp # 安装ent CLI工具 go install entgo.io/ent/cmd/ent@latest # 或者使用go get go get entgo.io/ent/cmd/ent 2.2 创建第一个Schema # 创建User实体 ent new User 这会在 ent/schema/ 目录下生成一个基础的schema文件：
package schema import ( &amp;#34;entgo.io/ent&amp;#34; &amp;#34;entgo.io/ent/schema/field&amp;#34; ) // User holds the schema definition for the User entity. type User struct { ent.Schema } // Fields of the User.</description>
    </item>
    
    <item>
      <title>在Go里面实现Google和Apple OAuth登录</title>
      <link>https://czyt.tech/post/google-and-apple-oauth-login-in-go/</link>
      <pubDate>Fri, 12 Dec 2025 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/google-and-apple-oauth-login-in-go/</guid>
      <description>本文由claude code编写，仅供参考。 在现代应用开发中，提供第三方登录已经成为标配功能。本文将详细介绍如何在Go语言中实现Google和Apple的OAuth登录，以及如何处理iOS和Android的原生登录。
一、OAuth 2.0 基础概念 OAuth 2.0是一个授权框架，允许应用在用户授权的情况下访问用户在第三方服务上的资源，而无需获取用户的密码。主要流程包括：
授权请求：引导用户到OAuth提供商的授权页面 授权确认：用户同意授权 获取授权码：重定向回应用并携带授权码 交换令牌：使用授权码换取访问令牌 访问资源：使用访问令牌获取用户信息 二、Google OAuth登录实现 2.1 前期准备 首先需要在Google Cloud Console创建项目并配置OAuth 2.0凭据：
访问 Google Cloud Console 创建新项目或选择现有项目 启用Google+ API或Google Identity服务 创建OAuth 2.0客户端ID（Web应用、iOS、Android分别创建） 配置授权重定向URI 2.2 安装依赖 go get golang.org/x/oauth2 go get golang.org/x/oauth2/google go get google.golang.org/api/oauth2/v2 2.3 Web端Google登录实现 package main import ( &amp;#34;context&amp;#34; &amp;#34;encoding/json&amp;#34; &amp;#34;fmt&amp;#34; &amp;#34;log&amp;#34; &amp;#34;net/http&amp;#34; &amp;#34;os&amp;#34; &amp;#34;golang.org/x/oauth2&amp;#34; &amp;#34;golang.org/x/oauth2/google&amp;#34; oauth2api &amp;#34;google.golang.org/api/oauth2/v2&amp;#34; &amp;#34;google.golang.org/api/option&amp;#34; ) var googleOauthConfig *oauth2.Config func init() { googleOauthConfig = &amp;amp;oauth2.</description>
    </item>
    
    <item>
      <title>Homebrew Tap 仓库简明指南</title>
      <link>https://czyt.tech/post/homebrew-repo-simple-guide/</link>
      <pubDate>Fri, 21 Nov 2025 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/homebrew-repo-simple-guide/</guid>
      <description>本文为Claude整理编写。
什么是 Homebrew Tap Homebrew Tap 是第三方的 Homebrew 软件包仓库。通过创建自己的 Tap，你可以发布和分发自己的软件包，而不需要将它们提交到官方的 Homebrew 仓库。
Tap 的命名规则： homebrew-&amp;lt;tapname&amp;gt;
用户使用时的格式：username/tapname/软件名
Formula vs Casks：核心概念 这是 Homebrew 中最重要的区别，理解这一点对于正确组织你的 Tap 至关重要。
Formula（公式） 用途： 安装命令行工具、从源代码编译的软件、开发库和服务
特点：
可以从源代码编译或安装预编译二进制 安装到 /usr/local/bin（Intel）或 /opt/homebrew/bin（Apple Silicon） 在终端中运行 文件放在 Formula/ 目录 安装命令：
brew install git brew install python brew install myapp 适用场景：
✅ 命令行工具（git, wget, curl） ✅ 编程语言（python, node, ruby） ✅ 开发库（openssl, libpq） ✅ 后台服务（redis, nginx, postgresql） ✅ 系统工具和实用程序 Casks（桶） 用途： 安装 macOS 原生应用程序、字体、驱动等</description>
    </item>
    
    <item>
      <title>Hertz使用笔记</title>
      <link>https://czyt.tech/post/hertz-usage-memo/</link>
      <pubDate>Thu, 30 Oct 2025 18:36:50 +0800</pubDate>
      
      <guid>https://czyt.tech/post/hertz-usage-memo/</guid>
      <description>Hertz的优缺点 优点 中文社区维护 稳定，字节产品，有相关的开源项目参考，比如coze和coze studio hz的模板支持，使得代码生成更加灵活 缺点 工程体验上，不如go-kratos等项目。比如不能很好得支持buf等第三方生态。代码生成的使用场景，如多service模式下体验不好。 Template 模板 之所以将模板放在第一，是因为Hertz里面模板是过不去的坎。😄官方的一个mvc的template 或者 cwgo内置的模板
自动生成路由注册 新建一个template/package.yaml
layouts: # 覆盖默认 router.go 模板 # 关键：将 Register 函数名改为包含服务名的唯一名称 - path: router.go delims: [&amp;#39;{{&amp;#39;, &amp;#39;}}&amp;#39;] body: |- // Code generated by hertz generator. DO NOT EDIT. package {{$.PackageName}} import ( &amp;#34;github.com/cloudwego/hertz/pkg/app/server&amp;#34; {{- range $k, $v := .HandlerPackages}} {{$k}} &amp;#34;{{$v}}&amp;#34; {{- end}} ) /* This file will register all the routes of the services in the master idl.</description>
    </item>
    
    <item>
      <title>Omarchy 使用笔记</title>
      <link>https://czyt.tech/post/omarchy-usage-notes/</link>
      <pubDate>Thu, 18 Sep 2025 16:32:07 +0800</pubDate>
      
      <guid>https://czyt.tech/post/omarchy-usage-notes/</guid>
      <description>omarchy是DHH发布的一款Arch内核的Linux发行版。最近安装了下，稍作记录
特色功能 命令行 可以使用 eza替换ls 快捷键 导航快捷键 Super + Space：应用启动器 Super + Alt + Space：Omarchy 控制菜单 Super + Escape：锁定、暂停、重启、关机 Super + Ctrl + L：锁定计算机 Super + W：关闭窗口 Ctrl + Alt + Del：关闭所有窗口 Super + T：切换窗口的平铺/浮动模式 Super + O：切换窗口为粘性浮动模式 Super + F：全屏显示 Super + Alt + F：全宽度显示 工作区快捷键 Super + 1/2/3/4：跳转到指定工作区 Super + Tab：跳转到下一个工作区 Super + Shift + Tab：跳转到上一个工作区 Super + Ctrl + Tab：跳转到之前的工作区 Super + Shift + 1/2/3/4：移动窗口到指定工作区 Super + Shift + Alt + 方向键：将工作区移动到指定显示器 窗口管理快捷键 Super + 方向键：将焦点移动到指定方向的窗口 Super + Shift + 方向键：与指定方向的窗口交换位置 Super + Equal：向左扩展窗口 Super + Minus：向右扩展窗口 Super + Shift + Equal：向下扩展窗口 Super + Shift + Minus：向上扩展窗口 Super + G：切换窗口分组 Super + Alt + G：将窗口移出分组 Super + Alt + Tab：在分组中的窗口间循环切换 Super + Alt + 1/2/3/4：跳转到分组中的指定窗口 Super + Alt + 方向键：将窗口移动到指定方向的分组中 Super + Ctrl + 方向键：在平铺分组中的窗口间移动 Super + S：显示便签工作区覆盖层 Super + Alt + S：将窗口移动到便签工作区 系统控制快捷键 Super + Ctrl + A：音频控制（wiremix） Super + Ctrl + B：蓝牙控制（bluetui） Super + Ctrl + W：WiFi 控制（impala） Super + Ctrl + S：共享菜单（通过 LocalSend） Super + Ctrl + T：活动监视器（btop） 应用启动快捷键 Super + Return：终端 Super + Shift + B：浏览器 Super + Shift + Alt + B：浏览器（隐私/无痕模式） Super + Shift + F：文件管理器 Super + Shift + M：音乐（Spotify） Super + Shift + /：密码管理器（1password） Super + Shift + N：Neovim Super + Shift + C：日历（HEY） Super + Shift + E：邮件（HEY） Super + Shift + A：AI（ChatGPT） Super + Shift + G：消息（Signal） Super + Shift + Alt + G：消息（WhatsApp） Super + Shift + Ctrl + G：消息（Google） Super + Shift + D：Docker（LazyDocker） Super + Shift + O：Obsidian Super + Shift + X：X 通用剪贴板快捷键（统一系统） Super + C：复制 Super + X：剪切（终端中不可用） Super + V：粘贴 Super + Ctrl + V：剪贴板管理器 注意：在 Linux 上，通常需要在终端中使用 Ctrl + Shift + C/V 进行复制粘贴，而在其他地方使用 Ctrl + C/V。Omarchy 的统一剪贴板快捷键在所有地方都有效（文件管理器除外）。</description>
    </item>
    
    <item>
      <title>Arch NVIDIA 驱动故障排查与修复指南</title>
      <link>https://czyt.tech/post/nvidia-driver-issue-fix-in-arch/</link>
      <pubDate>Thu, 11 Sep 2025 10:03:26 +0800</pubDate>
      
      <guid>https://czyt.tech/post/nvidia-driver-issue-fix-in-arch/</guid>
      <description>本文基于warp Terminal的修复操作使用deepseek进行复盘
问题描述 在EndeavourOS系统更新后，显示器因NVIDIA驱动问题停止工作，主要症状如下：
nvidia-smi 命令报错： NVIDIA-SMI 失败：无法与NVIDIA驱动通信 检测不到显示设备： xrandr --listproviders 提供方数量：0 内核模块缺失： modprobe: 致命错误：在/lib/modules/6.16.6-arch1-1中找不到nvidia模块 问题根源 版本不匹配 nvidia=580.82.07-2 与 nvidia-utils=580.82.07-1 版本不一致 内核兼容性问题 预编译的nvidia驱动不支持新内核(6.16.6-arch1-1) 驱动类型限制 标准nvidia软件包无法自动重建内核模块 完整解决方案 1. 排除问题包进行系统更新 paru -Syyu --ignore nvidia,nvidia-utils,nvidia-settings --noconfirm 2. 卸载问题驱动并安装DKMS版本 paru -R nvidia --noconfirm # 移除问题驱动包 paru -S nvidia-dkms --noconfirm # 安装DKMS版本 3. 加载NVIDIA模块并验证 sudo modprobe nvidia # 强制加载驱动模块 nvidia-smi # 验证驱动状态 预期输出示例：
+-----------------------------------------------------------------------------+ | NVIDIA-SMI 580.82.07 驱动版本: 580.82.07 CUDA版本: 12.1 | |-------------------------------+----------------------+----------------------+ | GPU 名称 持久性| Bus-Id 显存使用 | 易失性非校正ECC | | 风扇 温度 性能 功耗上限 | 显存使用率 | GPU利用率 计算模式 | |===============================+======================+======================| | 0 NVIDIA RTX 3050 关闭 | 00000000:01:00.</description>
    </item>
    
    <item>
      <title>一些适合小朋友的电影合辑</title>
      <link>https://czyt.tech/post/some-movies-suit-for-children/</link>
      <pubDate>Wed, 03 Sep 2025 21:07:21 +0800</pubDate>
      
      <guid>https://czyt.tech/post/some-movies-suit-for-children/</guid>
      <description> 资源整理来自网络，如有侵权，请联系我删除.
因为小朋友看不懂字幕，所以优先收集的是带多音轨的版本资源。
外国 蜘蛛侠 magnet:?xt=urn:btih:DF16B7D9B96E46D78DCC3241ECDBFA456C15CF90&amp;amp;dn=蜘蛛侠全家桶&amp;amp;tr=udp://tracker.openbittorrent.com:80/announce&amp;amp;tr=udp://tracker.opentrackr.org:1337/announce 哈利波特 magnet:?xt=urn:btih:BC9997161B52E3472156BBF5D51541E793BA8233&amp;amp;dn=[y5y4.com]哈利波特1-8合集.多语音轨字幕.珍藏版.Harry.Potter.Collection.2001-2011.BluRay.1080p.x265.10bit.DuoAudio-AIU 驯龙高手 magnet:?xt=urn:btih:53330826EE05220B5E79DDD3B734D6178DE69467&amp;amp;dn=【首发于高清影视之家 www.BBQDDQ.com】驯龙高手2[国粤英多音轨+简繁英双语字幕].How.to.Train.Your.Dragon.2.2014.UHD.BluRay.2160p.MultiAudio.DTS-X.MA.7.1.x265.10bit.HDR-ALT magnet:?xt=urn:btih:5E89BC62EA3443A7A28D4366A00CFA78959A0E32&amp;amp;dn=【首发于高清影视之家 www.BBQDDQ.com】驯龙高手3[国粤英多音轨+简繁英字幕].How.to.Train.Your.Dragon.The.Hidden.World.2019.UHD.BluRay.2160p.MultiAudio.TrueHD(Atmos).7.1.x265.10bit.HDR-ALT magnet:?xt=urn:btih:6F417913B9C669C5CBCC3C6FE1ABEE9D2F7BE953&amp;amp;dn=【首发于高清影视之家 www.BBQDDQ.com】驯龙高手[国粤英多音轨+简繁英字幕].How.To.Train.Your.Dragon.2010.UHD.BluRay.2160p.MultiAudio.DTS-X.MA.7.1.x265.10bit.HDR-ALT 漫威十年十八部大作中英双语 magnet:?xt=urn:btih:BE8EBED29654C90DDC59B2552E7A7FF5F4BB068B </description>
    </item>
    
    <item>
      <title>在并发Go应用中保持顺序【译】</title>
      <link>https://czyt.tech/post/preserving-order-in-concurrent-go-cn/</link>
      <pubDate>Tue, 02 Sep 2025 08:53:04 +0800</pubDate>
      
      <guid>https://czyt.tech/post/preserving-order-in-concurrent-go-cn/</guid>
      <description>原文链接 https://destel.dev/blog/preserving-order-in-concurrent-go
并发是 Go 语言的一大优势，但它带来一个根本性的权衡：当多个 goroutine 同时处理数据时，自然顺序会被打乱。大多数情况下，这并无大碍——无序处理已足够，且更快速、更简单。
但有时，顺序至关重要。
当顺序至关重要 以下是三个需要保持顺序至关重要的实际场景：
实时日志增强 ：您正在处理高流量的日志流，通过数据库或外部 API 为每个条目添加用户元数据。顺序处理无法跟上输入速率，但并发处理会打乱顺序，使得增强后的日志对依赖时间顺序的下游消费者变得不可用。
在文件列表中查找首个匹配项 ：您需要从云存储下载文件列表，并找到包含特定字符串的第一个文件。并发下载速度更快，但完成顺序是乱序的——第 50 个文件可能比第 5 个文件先完成，因此您不能简单地返回找到的第一个匹配项，因为无法确定更早的文件是否也包含该字符串。
时间序列数据处理 ：这个场景激发了我的原始实现。我需要下载 90 天的交易日志（每个约 600MB），提取部分数据，然后比较连续日期的数据以进行趋势分析。顺序下载需要数小时；并发下载可实现数量级的速度提升，但会破坏我进行比较所需的时间关联性。
挑战很明确：我们需要在不牺牲结果顺序可预测性的前提下获得并发处理的速度优势。这不仅是理论问题——更是影响实际大规模系统的现实约束。
本文将探讨我在生产级 Go 应用中开发并采用的三种方法。我们将构建一个并发的 OrderedMap 函数，它能在保持顺序的同时将输入通道转换为输出通道，并支持具有背压机制的无限流处理。通过对每种方法进行基准测试，我们将理解其权衡取舍，并在此过程中发现令人惊讶的性能洞见。
问题：为何并发会破坏顺序 让我们快速回顾一下为什么并发会打乱顺序。原因之一是各个 goroutine 处理任务的速度不同。另一个常见原因——我们无法预测 Go 运行时如何精确调度 goroutine。
例如，goroutine #2 可能在 goroutine #1 完成第 10 项之前就处理完了第 50 项，导致结果顺序错乱。这是并发处理的自然行为。
若想查看实际效果，这里有一个在 Go Playground 上的快速演示 。
设计理念：背压与缓冲的权衡 传统的顺序并发方法采用某种重排序缓冲区或队列。当工作线程计算出结果但尚不能写入输出时，该结果会被暂存于缓冲区中，直至能够按正确顺序写入。
在这种设计中，缓冲区通常可以无限制地增长。这种情况发生在：
输入存在倾斜 – 早期项目的处理时间比后续项目更长 下游消费者处理速度较慢 另一种常见方法是将所有结果暂存于内存中（切片/映射等）再进行排序。但我们今天的目标是构建一个流式解决方案，它能够：
最小化延迟 – 结果一旦准备就绪立即输出 处理无限输入流 – 支持任意大甚至无限的输入（例如从标准输入或网络流读取） 保持内存受限 – 避免不必要地在内存中累积结果 话虽如此，下面介绍的算法是背压优先的。如果工作协程还无法将结果写入输出通道，它就会阻塞。这种设计受内存限制，并保持了开发者对 Go 通道行为的预期。</description>
    </item>
    
    <item>
      <title>Zsh自动完成文件的一个例子</title>
      <link>https://czyt.tech/post/zsh-completions-define-with-example/</link>
      <pubDate>Wed, 16 Jul 2025 09:41:40 +0800</pubDate>
      
      <guid>https://czyt.tech/post/zsh-completions-define-with-example/</guid>
      <description>亚马逊发布了kiro ,基于Claude，于是下载安装文件，发现在它的安装文件里面有那么一个文件。
文件内容如下
#compdef kiro local arguments arguments=( &amp;#39;(-d --diff)&amp;#39;{-d,--diff}&amp;#39;[compare two files with each other]:file to compare:_files:file to compare with:_files&amp;#39; \*&amp;#39;--folder-uri[open a window with given folder uri(s)]:folder uri: &amp;#39; \*{-a,--add}&amp;#39;[add folder(s) to the last active window]:directory:_directories&amp;#39; &amp;#39;(-g --goto)&amp;#39;{-g,--goto}&amp;#39;[open a file at the path on the specified line and column position]:file\:line[\:column]:_files -r \:&amp;#39; &amp;#39;(-n --new-window -r --reuse-window)&amp;#39;{-n,--new-window}&amp;#39;[force to open a new window]&amp;#39; &amp;#39;(-n --new-window -r --reuse-window)&amp;#39;{-r,--reuse-window}&amp;#39;[force to open a file or folder in an already opened window]&amp;#39; &amp;#39;(-w --wait)&amp;#39;{-w,--wait}&amp;#39;[wait for the files to be closed before returning]&amp;#39; &amp;#39;--locale=[the locale to use (e.</description>
    </item>
    
    <item>
      <title>使用go编写一个简单的人脸识别服务</title>
      <link>https://czyt.tech/post/write-a-simple-face-recognizer-service-in-go/</link>
      <pubDate>Tue, 24 Jun 2025 15:26:06 +0800</pubDate>
      
      <guid>https://czyt.tech/post/write-a-simple-face-recognizer-service-in-go/</guid>
      <description>需要下载相关的模型 https://github.com/Kagami/go-face-testdata 下面的models
代码实现 代码如下
package main import ( &amp;#34;encoding/base64&amp;#34; &amp;#34;encoding/json&amp;#34; &amp;#34;errors&amp;#34; &amp;#34;fmt&amp;#34; &amp;#34;io&amp;#34; &amp;#34;log&amp;#34; &amp;#34;math&amp;#34; &amp;#34;net/http&amp;#34; &amp;#34;os&amp;#34; &amp;#34;path/filepath&amp;#34; &amp;#34;strconv&amp;#34; &amp;#34;sync&amp;#34; &amp;#34;time&amp;#34; &amp;#34;unsafe&amp;#34; &amp;#34;github.com/Kagami/go-face&amp;#34; &amp;#34;github.com/gorilla/mux&amp;#34; ) // Config 配置结构 type Config struct { Port string `json:&amp;#34;port&amp;#34;` ModelsDir string `json:&amp;#34;models_dir&amp;#34;` UploadsDir string `json:&amp;#34;uploads_dir&amp;#34;` TempDir string `json:&amp;#34;temp_dir&amp;#34;` DataFile string `json:&amp;#34;data_file&amp;#34;` MaxFileSize int64 `json:&amp;#34;max_file_size&amp;#34;` DefaultThreshold float32 `json:&amp;#34;default_threshold&amp;#34;` LogLevel string `json:&amp;#34;log_level&amp;#34;` } // Person 人员结构（支持多样本） type Person struct { ID int `json:&amp;#34;id&amp;#34;` Name string `json:&amp;#34;name&amp;#34;` Samples []FaceSample `json:&amp;#34;samples&amp;#34;` Created time.</description>
    </item>
    
    <item>
      <title>通过比较两个 Go pprof文件来发现性能问题【译】</title>
      <link>https://czyt.tech/post/go-pprof-diffing/</link>
      <pubDate>Sat, 21 Jun 2025 19:53:21 +0800</pubDate>
      
      <guid>https://czyt.tech/post/go-pprof-diffing/</guid>
      <description>原文链接 https://www.dolthub.com/blog/2025-06-20-go-pprof-diffing/
我们正在努力进行兼容性工作 Doltgres，世界上首个且唯一的版本控制兼容 Postgres 的 SQL 数据库。这意味着它能够开箱即用地与 Postgres 兼容的每一款库和工具协同工作。近来我们投入了大量精力在 SQLAlchemy 上，这是一款流行的 Python ORM。他们的 MySQL 集成与 Dolt 配合完美无缺，但他们的 Postgres 版本显然完全不同，严重依赖 pg_catalog 表。一位客户尝试使用后发现存在许多空白 ，因为 Doltgres 未将系统表（例如 dolt_log）包含在 pg_catalog 表中。所以我修复了这个问题，但这导致我们其中一个测试套件出现了神秘的性能退化，速度慢了 3 倍。
费了相当大的心思才弄清楚为什么这样一个看似无害的更改会导致性能出现如此巨大的差异。最终，最有帮助的是一个令人惊叹的 Go 工具链工具：使用 -base 选项来可视化两个性能分析之间的差异。 pprof
使用 pprof 对两个 profile 进行差异比较 Go 自带了一个强大的性能分析工具，pprof。与某些其他语言不同，您必须在代码中显式启用它才能获取性能分析结果；您不能事后进行或使用命令行标志。这很简单，但您必须编写代码来实现它。在我们的案例中，我将它直接放置在被分析的性能测试方法中。
func TestRegressionTests(t *testing.T) { // We&amp;#39;ll only run this on GitHub Actions, so set this environment variable to run locally if _, ok := os.LookupEnv(&amp;#34;REGRESSION_TESTING&amp;#34;); !ok { // t.</description>
    </item>
    
    <item>
      <title>Git Submodule Update 命令备忘笔记</title>
      <link>https://czyt.tech/post/git-submodule-update-notes/</link>
      <pubDate>Tue, 17 Jun 2025 16:06:11 +0800</pubDate>
      
      <guid>https://czyt.tech/post/git-submodule-update-notes/</guid>
      <description>核心命令差异分析 git submodule update 行为：将子模块检出到父仓库记录的特定提交（commit hash） 特点：保持与父仓库 .gitmodules 和索引中记录的版本一致 适用场景：需要精确重现项目某个时间点的状态 局限性：不会拉取远程最新提交，只同步到父仓库索引中记录的版本 git submodule update --remote --recursive 行为：将子模块更新到远程分支的最新提交 特点：忽略父仓库记录的提交，直接拉取远程最新版本 适用场景：需要获取子模块的最新开发进度 常见困惑：为什么普通 update 拉取不到最新版本？ 问题现象 许多开发者会遇到这种情况：
# 执行普通更新，发现子模块没有更新到最新版本 git submodule update # 但是使用 --remote 参数却能拉取到最新版本 git submodule update --remote --recursive 根本原因分析 这个现象的核心在于 Git 子模块的版本绑定机制：
父仓库记录的是具体提交：当你添加子模块时，父仓库会在其索引中记录子模块的具体 commit hash 普通 update 遵循绑定版本：git submodule update 只会将子模块检出到父仓库记录的那个具体提交 &amp;ndash;remote 忽略绑定版本：git submodule update --remote 会直接从远程仓库拉取最新提交 实际演示场景 # 查看当前子模块状态 git submodule status # 输出示例：-a1b2c3d4 path/to/submodule (v1.0-5-ga1b2c3d) # 父仓库记录的是 a1b2c3d4 这个提交 # 即使远程仓库已经有新的提交 e5f6g7h8 # 使用普通 update git submodule update # 子模块仍然停留在 a1b2c3d4 # 使用 --remote 参数 git submodule update --remote # 子模块更新到最新的 e5f6g7h8 详细参数说明 --remote 参数 # 更新到远程分支最新版本 git submodule update --remote # 指定远程分支 git submodule update --remote --branch main --recursive 参数 # 递归更新嵌套的子模块 git submodule update --recursive # 组合使用 git submodule update --remote --recursive 其他常用参数 # 强制更新（丢弃本地修改） git submodule update --force # 初始化并更新 git submodule update --init --recursive # 并行更新（提高速度） git submodule update --jobs 4 配置选项管理 局部配置（仅当前仓库） 设置子模块默认更新行为 # 设置特定子模块跟踪远程分支 git config -f .</description>
    </item>
    
    <item>
      <title>Claude Code使用笔记</title>
      <link>https://czyt.tech/post/claude-code-usage-notes/</link>
      <pubDate>Thu, 12 Jun 2025 15:36:50 +0800</pubDate>
      
      <guid>https://czyt.tech/post/claude-code-usage-notes/</guid>
      <description>来自https://x.com/shao__meng/status/1950196917595754662的ClaudeCode技巧
安装 你需要有nodejs这样的环境，bun没进行测试.需要安装npm或者pnpm包管理器
安装 Claude Code Homebrew brew install --cask claude-code Winget winget install Anthropics.ClaudeCode macOS, Linux, WSL curl -fsSL https://claude.ai/install.sh | bash Windows PowerShell irm https://claude.ai/install.ps1 | iex Windows CMD curl -fsSL https://claude.ai/install.cmd -o install.cmd &amp;amp;&amp;amp; install.cmd &amp;amp;&amp;amp; del install.cmd deno环境 安装Deno
curl -fsSL https://deno.land/install.sh | sh 全局按照Claude code
deno install --global -A npm:@anthropic-ai/claude-code 将 ~/.deno/bin 添加到PATH
claude --version 1.0.65 (Claude Code) Claude Code Router使用 虽说Claude Code很好用，但是国内很难稳定直连Claude，手上的硅基余额还有上百块，于是突发奇想，如何把手上的硅基DeepSeek用到Claude Code上。找了下，发现Claude Code Router 这个项目。安装方法：</description>
    </item>
    
    <item>
      <title>Go语言中的指数加权移动平均</title>
      <link>https://czyt.tech/post/ewma-practice-in-go/</link>
      <pubDate>Fri, 06 Jun 2025 16:07:37 +0800</pubDate>
      
      <guid>https://czyt.tech/post/ewma-practice-in-go/</guid>
      <description>Tailscale中有很多实用的代码，下面是EWMA的一个实现，源码
// Copyright (c) Tailscale Inc &amp;amp; AUTHORS // SPDX-License-Identifier: BSD-3-Clause // Package maths contains additional mathematical functions or structures not // found in the standard library. package maths import ( &amp;#34;math&amp;#34; &amp;#34;time&amp;#34; ) // EWMA is an exponentially weighted moving average supporting updates at // irregular intervals with at most nanosecond resolution. // The zero value will compute a half-life of 1 second. // It is not safe for concurrent use.</description>
    </item>
    
    <item>
      <title>在go中使用Semaphoregroup</title>
      <link>https://czyt.tech/post/use-semaphoregroup-in-go/</link>
      <pubDate>Thu, 05 Jun 2025 10:36:15 +0800</pubDate>
      
      <guid>https://czyt.tech/post/use-semaphoregroup-in-go/</guid>
      <description>在netbird中看到一个semaphore-group函数
package semaphoregroup import ( &amp;#34;context&amp;#34; &amp;#34;sync&amp;#34; ) // SemaphoreGroup is a custom type that combines sync.WaitGroup and a semaphore. type SemaphoreGroup struct { waitGroup sync.WaitGroup semaphore chan struct{} } // NewSemaphoreGroup creates a new SemaphoreGroup with the specified semaphore limit. func NewSemaphoreGroup(limit int) *SemaphoreGroup { return &amp;amp;SemaphoreGroup{ semaphore: make(chan struct{}, limit), } } // Add increments the internal WaitGroup counter and acquires a semaphore slot. func (sg *SemaphoreGroup) Add(ctx context.</description>
    </item>
    
    <item>
      <title>在 Go 中构建可扩展的多租户应用程序【译】</title>
      <link>https://czyt.tech/post/scalable-multi-tenant-apps-in-go/</link>
      <pubDate>Fri, 30 May 2025 14:50:27 +0800</pubDate>
      
      <guid>https://czyt.tech/post/scalable-multi-tenant-apps-in-go/</guid>
      <description>原文链接 https://atlasgo.io/blog/2025/05/26/gophercon-scalable-multi-tenant-apps-in-go
为 GopherCon Israel 2025 准备并呈现。
引言 在本篇博客中，我们将基于我们在构建 Atlas Cloud 后端（作为我们商业产品的一部分）的经验，探讨在 Go 中构建可扩展多租户应用程序的不同策略。
但首先，让我们明确一下我们所说的多租户应用是什么。
多租户是一个系统的特性，即单个实例为多个客户（租户）提供服务。
作为一家商业企业，你的目标当然是有很多客户！但你想要服务许多客户，他们期望有一个流畅无缝的体验，就好像只有他们在使用你的服务一样。
你向客户隐含做出的两个重要承诺是：
数据隔离：每个租户的数据都是隔离和安全的，确保一个租户无法访问另一个租户的数据。 性能：无论租户数量如何，应用程序都应表现良好，确保一个租户的使用不会降低其他租户的体验。 让我们探讨一些可能实现这些承诺的方法。
物理隔离 确保数据和性能隔离最直接的方法是为每个租户运行一个独立的应用实例。这种方法通常被称为“物理隔离”或“专用实例”。
为每个租户运行独立实例，可以确保：
每个租户的数据存储在独立的数据库中，从而保证完全隔离。如有需要，租户可以在不同的 VPC 中运行，甚至可以在不同的云账户中运行。 租户独立消费资源，因此一个租户的使用不会影响其他租户，从而消除了“吵闹邻居”问题。 然而，大多数公司不会选择这条路，原因有几点：
运营开销：将应用程序部署到数百或数千个生产环境，每个环境都有自己的数据库和配置，管理起来可能非常复杂。 成本：如果您的公司需要为每个租户的资源支付云服务提供商的费用，成本可能会迅速变得难以承受。 可扩展性：如果添加新租户需要部署新实例，那么扩展应用程序以支持许多租户可能会成为瓶颈。 可见性：跨多个实例监控和调试问题可能具有挑战性，因为您需要从所有实例中聚合日志和指标。 逻辑隔离 另一种方法是运行单个应用程序实例来服务多个租户，通常称为“逻辑隔离”。在此模型中，租户共享相同的应用程序代码和数据库，但它们的数据在逻辑上是隔离的。逻辑隔离可以总结为：
共享基础设施，作用域请求
让我们看看在 Go 应用程序中实际如何使用这个示例，从一个简单的 GORM 示例开始：
package main type Tenant struct { ID uint `gorm:&amp;#34;primaryKey&amp;#34; json:&amp;#34;id&amp;#34;` Name string `json:&amp;#34;name&amp;#34;` } type Customer struct { ID uint `gorm:&amp;#34;primaryKey&amp;#34; json:&amp;#34;id&amp;#34;` Name string `json:&amp;#34;name&amp;#34;` TenantID uint `json:&amp;#34;tenant_id&amp;#34;` } 在这个示例中，我们有两个模型： Tenant 和 Customer 。每个 Customer 属于一个 Tenant ， Customer 模型中的 TenantID 字段用于将每个客户与特定的租户关联起来。</description>
    </item>
    
    <item>
      <title>TIL：Bash 脚本中的超时【译】</title>
      <link>https://czyt.tech/post/ttl-in-bash-script/</link>
      <pubDate>Fri, 30 May 2025 08:55:18 +0800</pubDate>
      
      <guid>https://czyt.tech/post/ttl-in-bash-script/</guid>
      <description>原文链接 https://heitorpb.github.io/bla/timeout/
前几天在工作中，我们有一个 Bash 脚本，用于设置一个 Web 服务器，并等待它启动后再继续执行后续操作。这个脚本运行正常，我们也没有遇到任何问题，直到出现了一个无限循环。
我们使用 Bash 内置的 until 来检查 Web 服务器是否正常：
until curl --silent --fail-with-body 10.0.0.1:8080/health; do sleep 1 done 这很好用。除非我们的 Web 服务器在启动过程中崩溃，并且我们 sleep 1 永远等待。
这里有一个实用的工具：timeout。顾名思义，这个命令可以为其他命令添加超时功能。您指定想要等待命令的时间限制，如果该时间已过，timeout 会发送一个信号来终止它，并以非零状态退出。默认情况下，timeout 发送的是 SIGTERM 信号，但您可以通过 --signal 标志来更改它，例如 timeout --signal=SIGKILL 1s foo 。
例如，timeout 1s sleep 5 将向 sleep 发送 SIGTERM 信号 1秒后：
$ time timeout 1s sleep 4 real 0m1,004s user 0m0,000s sys 0m0,005s $ echo $? 124 那么接下来应该将 timeout 和 until 结合起来：</description>
    </item>
    
    <item>
      <title>Sherpa Go语言实战</title>
      <link>https://czyt.tech/post/sherpa-action-in-golang/</link>
      <pubDate>Thu, 20 Mar 2025 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/sherpa-action-in-golang/</guid>
      <description>简介 sherpa 是 Next-gen Kaldi 项目的部署框架。
使用 VAD 语音活动检测（Voice Activity Detection，简称VAD）是一种技术，用于检测音频信号中是否存在语音或其他声音活动。它在语音处理、语音识别、音频压缩等领域有广泛的应用。
VAD的主要功能 语音识别系统：通过VAD，系统可以在检测到语音时启动识别过程，提高效率。 音频压缩：在语音通信中，VAD可以帮助压缩算法仅对有效语音信号进行压缩，减少传输数据量。 噪声抑制系统：通过检测语音活动，系统可以在静默时段增强噪声抑制效果。 在GO中使用 todo
KWS 关键词唤醒（Keyword Spotting，简称KWS）是一种技术，用于检测音频信号中特定的关键词或短语。它广泛应用于语音助手、智能家居设备、车载系统等领域，通过识别特定关键词来激活设备或执行特定命令。
主要功能 关键词检测：识别音频信号中是否包含预定义的关键词或短语。 唤醒设备：当检测到关键词时，激活设备或应用程序。 提高用户体验：通过语音命令简化操作流程，增强用户体验。 自定义keywords 通过官方的工具sherpa-onnx-cli，可以实现自定义关键字，下面是简单的介绍 原文
# Note: You need to run pip install sherpa-onnx to get the commandline tool: sherpa-onnx-cli sherpa-onnx-cli text2token --help Usage: sherpa-onnx-cli text2token [OPTIONS] INPUT OUTPUT Options: --text TEXT Path to the input texts. Each line in the texts contains the original phrase, it might also contain some extra items, for example, the boosting score (startting with :), the triggering threshold (startting with #, only used in keyword spotting task) and the original phrase (startting with @).</description>
    </item>
    
    <item>
      <title>在Go程序中使用Vosk进行语音识别STT</title>
      <link>https://czyt.tech/post/use-vosk-stt-in-your-go-applcation/</link>
      <pubDate>Mon, 17 Mar 2025 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/use-vosk-stt-in-your-go-applcation/</guid>
      <description>Vosk 介绍 Vosk是一款基于深度学习的开源语音识别工具，能够在没有云连接的情况下进行高效的离线语音识别。它通过对语音信号进行预处理、特征提取和模型推断，将语音转换成文本。Vosk不仅支持多种主流编程语言，还覆盖了20多种语言和方言，包括英语、中文、法语、德语等，为跨语言应用提供了强大的支持。
工作原理 Vosk的语音识别过程可以分为以下几个关键步骤：
语音信号预处理：对输入的语音信号进行去噪、增强等处理，以提高识别准确性。 特征提取：从处理后的语音信号中提取出能够表征语音特性的关键特征。 模型推断：利用预训练的深度学习模型对提取的特征进行识别，输出对应的文本。 优势解析 隐私保护：Vosk的离线特性意味着用户的语音数据不会离开设备，有效保护了用户的隐私。
实时性：在设备端进行语音识别，减少了网络传输时间和延迟，使得识别过程更加实时。
跨平台：支持Windows、Linux、macOS以及嵌入式设备等多种平台，便于在不同场景下的应用。
可扩展性：作为开源项目，Vosk允许开发者根据自己的需求进行定制和优化，以适应不同的应用场景。
多语言支持：提供对多种语言和方言的识别能力，为跨国应用提供了便利。
官方 https://alphacephei.com/vosk/
模型下载 https://alphacephei.com/vosk/models
GO项目搭建 本文基于Linux，Windows请参考官方仓库的说明
创建go程序 创建go程序内容如下：
package main import ( &amp;#34;encoding/json&amp;#34; &amp;#34;flag&amp;#34; &amp;#34;fmt&amp;#34; &amp;#34;io&amp;#34; &amp;#34;log&amp;#34; &amp;#34;os&amp;#34; vosk &amp;#34;github.com/alphacep/vosk-api/go&amp;#34; ) func main() { var filename string flag.StringVar(&amp;amp;filename, &amp;#34;f&amp;#34;, &amp;#34;&amp;#34;, &amp;#34;file to transcribe&amp;#34;) flag.Parse() model, err := vosk.NewModel(&amp;#34;model&amp;#34;) if err != nil { log.Fatal(err) } // we can check if word is in the vocabulary // fmt.</description>
    </item>
    
    <item>
      <title>AUFS简要笔记</title>
      <link>https://czyt.tech/post/aufs-quick-note/</link>
      <pubDate>Tue, 25 Feb 2025 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/aufs-quick-note/</guid>
      <description>文章内容为Claude生成，留作备忘
什么是 AUFS？ AUFS 是一种联合文件系统（Union File System），最初是为 Linux 系统开发的。它的主要功能是将多个目录（称为分支或层）的内容虚拟地合并成一个统一的视图。这种技术在容器化技术（如早期的 Docker）中得到了广泛应用。
AUFS 的基本原理 联合挂载机制 AUFS 核心原理是联合挂载（Union Mount）技术，其工作原理如下：
多层结构：AUFS 允许将多个目录层叠在一起，形成一个统一的视图 读写分离：通常配置为一个可写层和多个只读层 写时复制（Copy-on-Write，CoW）：当需要修改只读层中的文件时，AUFS 会将文件复制到可写层进行修改，保持底层文件不变 分支优先级 在 AUFS 中，每个分支都有优先级设置：
较高优先级的分支中的文件会覆盖低优先级分支中的同名文件 当访问一个文件时，AUFS 会从最高优先级的分支开始查找 AUFS 的主要特性 1. 写时复制（CoW） 当用户试图修改只读层中的文件时：
┌─────────────┐│ 可写层 │ ← 修改后的文件被存储在这里├─────────────┤│ 只读层 1 │ ← 原始文件位置├─────────────┤│ 只读层 2 │└─────────────┘ 2. 删除处理 当删除一个文件时，AUFS 会在可写层创建一个特殊的删除标记（whiteout 文件），以表示该文件已被删除。
3. 分支管理 AUFS 提供了动态添加、删除和重新排序分支的能力，使文件系统结构可以灵活调整。
AUFS 在容器技术中的应用 在容器技术早期发展中，AUFS 扮演了重要角色：
镜像分层：容器镜像由多个只读层组成，每层代表构建过程中的一步 容器实例：运行容器时，会在镜像上添加一个可写层 资源共享：多个容器可以共享基础镜像层，节省存储空间 AUFS 的优缺点 优点 高效的存储利用率（通过共享基础层） 快速的容器启动时间 成熟稳定的实现 缺点 较复杂的实现导致维护挑战 性能开销（尤其是在深层目录结构中） 在现代 Linux 内核中已被其他联合文件系统（如 OverlayFS）逐渐替代 实际应用场景 1.</description>
    </item>
    
    <item>
      <title>iter.Seq实践【译】</title>
      <link>https://czyt.tech/post/iter-seq-in-practice/</link>
      <pubDate>Wed, 19 Feb 2025 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/iter-seq-in-practice/</guid>
      <description>一些 iter.Seq、iter.Seq2 及其 iter.Pull 的真实场景例子，他们让编码变得更轻松</description>
    </item>
    
    <item>
      <title>懒猫微服开发简明教程</title>
      <link>https://czyt.tech/post/simple-guide-for-developing-for-lazycat-nas/</link>
      <pubDate>Fri, 07 Feb 2025 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/simple-guide-for-developing-for-lazycat-nas/</guid>
      <description>最近入手了懒猫微服，简单记录下开发相关的内容。
环境配置 先决条件 你必须有一台懒猫微服，购买地址 安装基本环境lzc-cli，请参考官方说明地址 如果你要发布程序，必须要申请成为懒猫微服开发者,申请地址 设备上必须安装懒猫开发者工具应用。这个应用主要用来通过lzc-cli进入devshell容器的开发以及将本地的测试镜像推送到盒子进行测试。 开发机器上安装懒猫微服客户端,这和懒猫微服的网络机制有关,参考官方文档。开启客户端并且设备需要联网开机。 如果上面的条件都已经满足，那么我们进入下一步。
不同类型应用的注意事项 Docker应用 对于公网的docker应用如果要使用，需要先进行copy-image来利用懒猫官方提供的镜像源，参考官方说明。下面是我的一个执行例子：
我在没copy操作之前lzc-cli project devshell
cmd: install --uid czyt --pkgId cloud.lazycat.app.gokapi Error: rpc error: code = Unknown desc = &amp;#34;time=\&amp;#34;2025-02-08T00:18:51+08:00\&amp;#34; level=warning msg=\&amp;#34;The \\\&amp;#34;LAZYCAT_APP_ID\\\&amp;#34; variable is not set. Defaulting to a blank string.\&amp;#34;\ntime=\&amp;#34;2025-02-08T00:18:51+08:00\&amp;#34; level=warning msg=\&amp;#34;The \\\&amp;#34;LAZYCAT_APP_DEPLOY_UID\\\&amp;#34; variable is not set. Defaulting to a blank string.\&amp;#34;\ntime=\&amp;#34;2025-02-08T00:18:51+08:00\&amp;#34; level=warning msg=\&amp;#34;The \\\&amp;#34;LAZYCAT_APP_DEPLOY_UID\\\&amp;#34; variable is not set. Defaulting to a blank string.\&amp;#34;\ntime=\&amp;#34;2025-02-08T00:18:51+08:00\&amp;#34; level=warning msg=\&amp;#34;The \\\&amp;#34;LAZYCAT_APP_DOMAIN\\\&amp;#34; variable is not set.</description>
    </item>
    
    <item>
      <title>Slint相关资源</title>
      <link>https://czyt.tech/post/slint-rust-related-resources/</link>
      <pubDate>Thu, 16 Jan 2025 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/slint-rust-related-resources/</guid>
      <description>视频 SurrealismUI Slint Easy Slint Advanced Slint With Rust 在线教程 Slint Learn 官方教程 UI 库 SurrealismUI JUI </description>
    </item>
    
    <item>
      <title>Go程序自动升级的方案探究</title>
      <link>https://czyt.tech/post/ways-to-self-upgrade-in-go/</link>
      <pubDate>Tue, 31 Dec 2024 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/ways-to-self-upgrade-in-go/</guid>
      <description>前导 2024年的最后一天看见v站的这个帖子,故整理下，备忘。
常用的库 cloudflare tableflip 仓库为 https://github.com/cloudflare/tableflip
官方示例
package tableflip_test import ( &amp;#34;context&amp;#34; &amp;#34;flag&amp;#34; &amp;#34;fmt&amp;#34; &amp;#34;log&amp;#34; &amp;#34;net/http&amp;#34; &amp;#34;os&amp;#34; &amp;#34;os/signal&amp;#34; &amp;#34;syscall&amp;#34; &amp;#34;time&amp;#34; &amp;#34;github.com/cloudflare/tableflip&amp;#34; ) // This shows how to use the upgrader // with the graceful shutdown facilities of net/http. func Example_httpShutdown() { var ( listenAddr = flag.String(&amp;#34;listen&amp;#34;, &amp;#34;localhost:8080&amp;#34;, &amp;#34;`Address` to listen on&amp;#34;) pidFile = flag.String(&amp;#34;pid-file&amp;#34;, &amp;#34;&amp;#34;, &amp;#34;`Path` to pid file&amp;#34;) ) flag.Parse() log.SetPrefix(fmt.Sprintf(&amp;#34;%d &amp;#34;, os.Getpid())) upg, err := tableflip.New(tableflip.Options{ PIDFile: *pidFile, }) if err !</description>
    </item>
    
    <item>
      <title>Ble Sniffer相关资料参考</title>
      <link>https://czyt.tech/post/ble-sniffer-quick-ref/</link>
      <pubDate>Wed, 11 Dec 2024 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/ble-sniffer-quick-ref/</guid>
      <description>硬件 nrf52840 sniffer 我只买了这个硬件，所以只加这部分。
E104-BT5040U 硬件说明书 E104-BT5040UA 硬件说明书 nRF Sniffer for Bluetooth LE 软件 bettercap </description>
    </item>
    
    <item>
      <title>对称和反向gRPC连接【译】</title>
      <link>https://czyt.tech/post/symmetric-and-reverse-grpc-connections-in-go/</link>
      <pubDate>Tue, 10 Dec 2024 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/symmetric-and-reverse-grpc-connections-in-go/</guid>
      <description>原文链接为 https://tilde.town/~hut8/post/grpc-connections/ 使用kimi进行翻译
背景
gRPC是一项出色的现代技术，用于远程过程调用。它允许你在客户端创建一个“存根”对象，该对象的目的是调用服务器上的方法。它是许多情况下REST或GraphQL的绝佳替代品，通常值得学习这项技术。更多信息可以在官方文档中找到。
网络
概念上，我们对客户端和服务器有两种不同的想法。
TCP服务器和客户端 - gRPC在HTTP/2之上运行，HTTP/2在TCP之上运行，所以我将讨论TCP中“服务器”和“客户端”的含义。在TCP连接中，客户端是连接的发起者，服务器是连接的接收者。然而，一旦建立了连接，连接就是对称的；客户端和服务器都可以发送和接收消息，直到一方通过shutdown(2)关闭，或通过close(2)关闭连接。
gRPC服务器和客户端 - gRPC客户端通过存根调用在服务器上运行的方法。这不是对称的。服务器不能在客户端上调用方法。
服务器/客户端类型耦合问题
如果你有一个gRPC客户端，它也是TCP客户端（它调用connect(2)）。如果你有一个gRPC服务器，它也是TCP服务器（它调用listen(2)和accept(2)）。
因此，如果你想让两台机器可以相互调用gRPC，那么每台机器都是客户端和服务器（在TCP和gRPC两种意义上），现在你有了两个与彼此无关的TCP连接。在有两朵云实例的场景中，这种架构通常并不复杂。但TCP通常很混乱。防火墙、NAT和动态分配的IP地址可能会使客户端到服务器的单向连接变得复杂。
这里有一个这样的情况的例子：假设你的“服务器”是一个在家庭路由器后面的笔记本电脑上运行的程序，它必须接收命令（例如，远程控制）来自“客户端”（例如，云计算实例）。根据gRPC，客户端必须是云计算实例（这很容易被称为“服务器”），因为那是创建远程过程调用的一方。服务器是笔记本电脑，因为那是实际发生过程调用的地方。
当你在客户端（即云计算实例）上创建一个“存根”时，你必须创建一个TCP连接并连接到服务器（即笔记本电脑）。现在你遇到了几个可能的问题：
你不知道笔记本电脑的IP地址，所以你现在需要一个反向服务，让笔记本电脑告诉云它的IP地址。 笔记本电脑可能在NAT后面，所以一旦你找到了IP地址，笔记本电脑将不得不配置端口转发。这在企业环境中很可能是不可能的。 笔记本电脑可能在防火墙后面，这将禁止传入连接。这可能是本地机器上的，也可能是在网关路由器上的。
这些问题中的一些可能是无法解决的，所以我们需要另一种方法。
gRPC独有的解决方案
服务器不能在客户端gRPC上调用方法。也许你可以让客户端在服务器上调用一个方法，其唯一目的是接收描述服务器希望客户端运行的方法的消息。这可以通过流式响应来完成。但这很复杂，需要大量的代码来绕过gRPC的设计。我在其他地方看到过这个建议，但我认为这是一个丑陋的临时解决方案，它制造的问题比它解决的还要多。考虑一下，你将如何在静态类型的方式中实际调用这些“客户端方法”。
基于隧道的解决方案
将TCP客户端/服务器从gRPC客户端/服务器中解耦的一个好方法是实现某种隧道。在上面的例子中，笔记本电脑可以向云计算实例发起一个TCP连接，然后通过实现特定于语言的接口，“拨号”操作让云计算实例（gRPC客户端）连接到笔记本电脑（gRPC服务器）可以简单地使用现有的TCP连接。
SSH是一个不可思议的协议，它的用途比大多数用户知道的还要多。在我们的情况下，它是将我们的TCP连接从gRPC连接中解耦的完美方式。它还有其他好处：尽管gRPC提供认证和加密，但如果更方便，你可以使用SSH提供的。
这些例子是Go语言特有的，但你可以在任何语言中做类似的事情。gRPC服务器不需要监听端口；你可以传入任何实现了Go的net.Listener的类型。所以我们可以做一个net.Listener，它将接受SSH连接，任何时候请求我们的自定义类型的新SSH通道，我们将接受它并返回一个新的net.Conn，这是我们将实现的另一个类型，它只是通过我们的隧道传输数据。
让我们从SSHDataTunnel开始，它是我们的net.Conn。
import ( &amp;#34;net&amp;#34; &amp;#34;time&amp;#34; &amp;#34;golang.org/x/crypto/ssh&amp;#34; ) // SSHDataTunnel实现了net.Conn type SSHDataTunnel struct { Chan ssh.Channel Conn net.Conn } func NewSSHDataTunnel(sshChan ssh.Channel, carrier net.Conn) *SSHDataTunnel { return &amp;amp;SSHDataTunnel{ Chan: sshChan, Conn: carrier, } } func (c *SSHDataTunnel) Read(b []byte) (n int, err error) { return c.</description>
    </item>
    
    <item>
      <title>在Go语言中使用Arrow、Flight和Duckdb</title>
      <link>https://czyt.tech/post/arrow-flight-and-duckdb-in-go/</link>
      <pubDate>Thu, 05 Dec 2024 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/arrow-flight-and-duckdb-in-go/</guid>
      <description>从duckdb开始 DuckDB 是一个嵌入式分析型数据库，专为 OLAP（在线分析处理）工作负载设计。本文将基于 go-duckdb 项目的示例，详细介绍 DuckDB 在 Go 语言中的各种使用场景。
基础使用 简单查询 package main import ( &amp;#34;database/sql&amp;#34; _ &amp;#34;github.com/marcboeker/go-duckdb&amp;#34; ) func main() { db, err := sql.Open(&amp;#34;duckdb&amp;#34;, &amp;#34;:memory:&amp;#34;) if err != nil { panic(err) } defer db.Close() // 执行查询 rows, err := db.Query(&amp;#34;SELECT 42&amp;#34;) if err != nil { panic(err) } defer rows.Close() } 高级特性 Copy COPY 函数可以用于导入导出数据：
package main import ( &amp;#34;database/sql&amp;#34; &amp;#34;fmt&amp;#34; _ &amp;#34;github.com/marcboeker/go-duckdb&amp;#34; ) func main() { db, err := sql.</description>
    </item>
    
    <item>
      <title>在Go语言中处理带BOM的json数据</title>
      <link>https://czyt.tech/post/handle-json-file-with-bom-in-go/</link>
      <pubDate>Tue, 03 Dec 2024 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/handle-json-file-with-bom-in-go/</guid>
      <description>缘起 今天开发的时候遇到一个奇怪的问题，一个JSON文件，使用文本编辑器打开复制，并使用strings.NewReader来decode，是正常的，但是通过文件打开同样调用的方法来decode，却是失败的。后面通过打开IDE，发现文件前面有一些空白的内容。是一些bom信息。
关于BOM BOM (Byte Order Mark) 的历史原因和用途主要与字符编码和跨平台兼容性有关：
历史原因 Unicode 出现前： ASCII 只用 1 字节，没有字节序问题 各国有自己的编码标准(GB2312、Shift-JIS等) Unicode 引入后： UTF-16 使用 2 字节表示字符 不同CPU架构的字节序不同： Big Endian (大端序): 高位字节在前 Little Endian (小端序): 低位字节在前 跨平台问题： Intel x86 使用小端序 Motorola 68k 使用大端序 同一文件在不同平台解析可能出错 BOM 的作用 UTF-16 的字节序标记： FE FF: Big Endian FF FE: Little Endian UTF-8 的编码标识： EF BB BF: 表明这是 UTF-8 编码 UTF-8 实际不需要 BOM（字节序无关） Windows 添加 BOM 主要为了兼容性 实际例子 // 字符 &amp;#34;中&amp;#34; 在不同编码下的表示 text := &amp;#34;中&amp;#34; // UTF-8: E4 B8 AD // UTF-16BE: 4E 2D // UTF-16LE: 2D 4E // 示例代码 func showEncoding() { text := &amp;#34;中&amp;#34; utf8Bytes := []byte(text) // UTF-8 utf16beBytes := utf16.</description>
    </item>
    
    <item>
      <title>Rust正则表达式实践</title>
      <link>https://czyt.tech/post/rust-regexp-in-action/</link>
      <pubDate>Tue, 26 Nov 2024 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/rust-regexp-in-action/</guid>
      <description>正则表达式是一种强大的文本处理工具。在 Rust 中，我们主要通过 regex crate 来使用正则表达式。让我们通过实际案例来学习。
1. 基础匹配 use regex::Regex; fn main() { // 创建正则表达式对象 let re = Regex::new(r&amp;#34;\d+&amp;#34;).unwrap(); // 测试匹配 let text = &amp;#34;The year is 2024&amp;#34;; if re.is_match(text) { println!(&amp;#34;Found a number!&amp;#34;); } // 提取匹配内容 if let Some(matched) = re.find(text) { println!(&amp;#34;Found number: {}&amp;#34;, matched.as_str()); } } 2. 处理重复单词 根据文章中提到的一个常见问题 - 查找重复单词：
use regex::Regex; fn remove_duplicate_words(text: &amp;amp;str) -&amp;gt; String { // (\w+) 捕获一个单词，\s+匹配空白字符，\1 回引用前面捕获的单词 let re = Regex::new(r&amp;#34;(\w+)\s+\1&amp;#34;).unwrap(); re.</description>
    </item>
    
    <item>
      <title>一些任天堂switch资源</title>
      <link>https://czyt.tech/post/some-ns-switch-hack-resouces/</link>
      <pubDate>Wed, 20 Nov 2024 21:45:19 +0800</pubDate>
      
      <guid>https://czyt.tech/post/some-ns-switch-hack-resouces/</guid>
      <description>最近整了个硬破的Switch，整理了下相关资源方便查找。
固件和系统 软破 新版本都是硬破了
TegraRCM: https://github.com/eliboa/TegraRcmGUI/releases
大气层 设备需要硬破
大气层系统 https://github.com/Atmosphere-NX/Atmosphere ak大气层整合包 https://github.com/AK478BB/AK-Atmosphere/releases 大气层集成sys-patch插件破解包 https://github.com/laila509/Atmosphere-syspatch Hekate引导: https://github.com/CTCaer/hekate/releases Switch固件 模拟器固件和key https://prodkeys.net/ Ryujinx 模拟器 Retroarch Switch官方固件分享下载 https://github.com/THZoria/NX_Firmware/ 其他 Check If Your Switch Is Patched: https://ismyswitchpatched.com/ Sig Patches: https://sigmapatches.su https://rentry.org/EristaEmuNAND Sig Patches： https://gbatemp.net/threads/sigpatches-for-atmosphere-hekate-fss0-fusee-package3.571543/ EaseUs Partition: https://www.easeus.com/partition-manager/epm-free.html switch主题 https://themezer.net 游戏下载 网盘资源 switch游戏下载 https://www.123pan.com/s/sl82jv-6JVV3.html
网站或论坛 悠游任天堂 2cyshare Switch520 rutracker的switch板块 上游世界 nsw2u Game中文网 switch主题 相关文章及博客 Switch 软破、硬破总结
字节智造
其他 BYRUTOR steam游戏破解下载 skidrowreloaded steamunlocked Online Fix koyso </description>
    </item>
    
    <item>
      <title>Connect Rpc快速上手</title>
      <link>https://czyt.tech/post/connect-rpc-quick-start/</link>
      <pubDate>Wed, 06 Nov 2024 16:04:38 +0800</pubDate>
      
      <guid>https://czyt.tech/post/connect-rpc-quick-start/</guid>
      <description>入门 Connect RPC 是一个轻量级的 HTTP API 构建库，支持浏览器和 gRPC 兼容的 API。它通过 Protocol Buffer 定义服务，并生成类型安全的服务器和客户端代码。
压缩和序列化 Connect 支持多种压缩和序列化选项，默认情况下，Connect 处理程序支持在默认压缩级别使用标准库的 compress/gzip 进行 gzip 压缩。Connect 客户端默认发送未压缩的请求并请求 gzip 压缩的响应。如果您知道服务器支持 gzip，则还可以在客户端构建期间使用 WithSendGzip 选项来压缩请求。
// 服务端不需要进行什么选项设置 参考https://github.com/connectrpc/connect-go/issues/773 handler := greetv1connect.NewGreetServiceHandler( &amp;amp;GreetServer{}, ) // 客户端配置压缩，默认 client := greetv1connect.NewGreetServiceClient( http.DefaultClient, &amp;#34;http://localhost:8080&amp;#34;, connect.WithSendGzip(), ) 自定义压缩实现：
type CustomCompressor struct{} func (c *CustomCompressor) Name() string { return &amp;#34;custom&amp;#34; } func (c *CustomCompressor) Compress(w io.Writer) (io.WriteCloser, error) func (c *CustomCompressor) Decompress(r io.Reader) (io.Reader, error) connect的brotli压缩</description>
    </item>
    
    <item>
      <title>Go Ble开发实战</title>
      <link>https://czyt.tech/post/go-ble-in-action/</link>
      <pubDate>Sat, 02 Nov 2024 07:20:04 +0800</pubDate>
      
      <guid>https://czyt.tech/post/go-ble-in-action/</guid>
      <description>⚠️代码仅最后部分进行了测试,前面的暂未测试
1. 简介 BLE (Bluetooth Low Energy) 是一种低功耗蓝牙技术。Go-BLE 是 Go 语言的 BLE 库，提供了简单易用的 API 来开发 BLE 应用。本文将通过一个完整的示例来展示如何使用 Go-BLE 创建一个蓝牙服务器。
Go-BLE 主要支持 Linux 和 macOS 平台(1)，但需要注意 macOS 部分目前并未被积极维护。
2. 环境准备 2.1 安装依赖 # 安装 go-ble go get -u github.com/go-ble/ble # 安装设备支持库 go get -u github.com/go-ble/ble/examples/lib/dev # Linux系统需要设置权限 sudo setcap &amp;#39;cap_net_raw,cap_net_admin+eip&amp;#39; ./your_program 3. BLE基础概念 3.1 核心概念 Peripheral (外围设备)：提供服务的设备 Central (中心设备)：连接外围设备的设备（如手机） Service (服务)：功能的集合 Characteristic (特征)：具体的数据点 Descriptor (描述符)：特征的元数据 3.2 常见的 UUID 标准服务 UUID： 电池服务：0x180F设备信息服务：0x180A心率务：0x180D 标准特征 UUID： 电池电量：0x2A19设备名称：0x2A00制造商名称：0x2A29型号名称：0x2A24序列号：0x2A25固件版本：0x2A26信号强度：0x2A1C 自定义 UUID 生成： // 使用在线工具生成 UUID v4 svcUUID := ble.</description>
    </item>
    
    <item>
      <title>使用 Suture在Go中实现可靠的监督树</title>
      <link>https://czyt.tech/post/use-suture-in-your-go-app/</link>
      <pubDate>Fri, 25 Oct 2024 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/use-suture-in-your-go-app/</guid>
      <description>Suture 为 Go 提供了 Erlang 风格的管理树。 “Supervisor trees” -&amp;gt; “sutree” -&amp;gt; “suture” -&amp;gt; 在代码试图死亡时将其保持在一起。</description>
    </item>
    
    <item>
      <title>rust中map_error的用法</title>
      <link>https://czyt.tech/post/map-error-in-rust/</link>
      <pubDate>Tue, 10 Sep 2024 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/map-error-in-rust/</guid>
      <description>Rust中的map_err方法是Result类型的一个方法，用于转换错误类型。它允许你在保持Ok值不变的情况下，修改Err值。这在错误处理和类型转换中非常有用。
以下是map_err的详细用法和一些例子：
基本用法 fn main() -&amp;gt; Result&amp;lt;(), String&amp;gt; { let result: Result&amp;lt;i32, &amp;amp;str&amp;gt; = Err(&amp;#34;原始错误&amp;#34;); let mapped = result.map_err(|e| e.to_string()); mapped } 在这个例子中，我们将&amp;amp;str类型的错误转换为String类型。
链式调用 use std::num::ParseIntError; fn parse_and_multiply(s: &amp;amp;str) -&amp;gt; Result&amp;lt;i32, String&amp;gt; { s.parse::&amp;lt;i32&amp;gt;() .map_err(|e: ParseIntError| e.to_string()) .map(|n| n * 2) } fn main() { match parse_and_multiply(&amp;#34;10&amp;#34;) { Ok(n) =&amp;gt; println!(&amp;#34;结果: {}&amp;#34;, n), Err(e) =&amp;gt; println!(&amp;#34;错误: {}&amp;#34;, e), } match parse_and_multiply(&amp;#34;abc&amp;#34;) { Ok(n) =&amp;gt; println!(&amp;#34;结果: {}&amp;#34;, n), Err(e) =&amp;gt; println!(&amp;#34;错误: {}&amp;#34;, e), } } 这个例子展示了如何在解析字符串并进行计算的过程中使用map_err转换错误类型。</description>
    </item>
    
    <item>
      <title>Rust derive_builder快速使用参考</title>
      <link>https://czyt.tech/post/rust-derive-builder-usage-quick-reference/</link>
      <pubDate>Thu, 05 Sep 2024 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/rust-derive-builder-usage-quick-reference/</guid>
      <description>derive_builder是 简化Rust结构体构建的强大工具，本文使用claude 3.5 生成
1. 引言 在Rust编程中，创建复杂的结构体实例常常需要大量的样板代码。derive_builder 是一个强大的过程宏库，它可以自动为结构体生成 builder 模式的实现，大大简化了结构体的创建过程。本文将深入介绍 derive_builder 的使用方法、特性和最佳实践。
2. 基本用法 2.1 安装 首先，在你的 Cargo.toml 文件中添加 derive_builder 依赖：
[dependencies] derive_builder = &amp;#34;0.20.0&amp;#34; 2.2 简单示例 让我们从一个简单的例子开始：
use derive_builder::Builder; #[derive(Builder, Debug)] struct Server { host: String, port: u16, } fn main() { let server = ServerBuilder::default() .host(&amp;#34;localhost&amp;#34;.to_string()) .port(8080) .build() .unwrap(); println!(&amp;#34;{:?}&amp;#34;, server); } 在这个例子中，我们为 Server 结构体派生了 Builder 特征。这会自动生成一个 ServerBuilder 结构体，它提供了流畅的 API 来构建 Server 实例。
3. 字段属性 derive_builder 提供了多种属性来自定义字段的行为。</description>
    </item>
    
    <item>
      <title>Rust serde_with快速参考</title>
      <link>https://czyt.tech/post/rust-serde-with-quick-reference/</link>
      <pubDate>Sun, 01 Sep 2024 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/rust-serde-with-quick-reference/</guid>
      <description>serde_with 是 Rust 中 serde 序列化/反序列化库的一个扩展,提供了许多有用的自定义序列化和反序列化方法。以下是一些常用的功能和适用场景:
字符串格式化 use serde_with::rust::display_fromstr; #[derive(Serialize, Deserialize)] struct Foo { #[serde_with(as = &amp;#34;display_fromstr&amp;#34;)] bar: u32, } 适用于需要将数字类型序列化为字符串的场景。
时间格式化 use serde_with::chrono::datetime_utc_ts_seconds_from_any; #[derive(Serialize, Deserialize)] struct Foo { #[serde_with(as = &amp;#34;datetime_utc_ts_seconds_from_any&amp;#34;)] time: DateTime&amp;lt;Utc&amp;gt;, } 适用于需要自定义时间格式的场景。
枚举字符串表示 use serde_with::{serde_as, DisplayFromStr}; #[serde_as] #[derive(Serialize, Deserialize)] struct Foo { #[serde_as(as = &amp;#34;DisplayFromStr&amp;#34;)] bar: MyEnum, } 适用于将枚举序列化为字符串的场景。
跳过序列化默认值 use serde_with::skip_serializing_none; #[skip_serializing_none] #[derive(Serialize)] struct Foo { bar: Option&amp;lt;String&amp;gt;, } 适用于需要在序列化时忽略 None 值的场景。
自定义序列化/反序列化 use serde_with::{serde_as, FromInto}; #[serde_as] #[derive(Serialize, Deserialize)] struct Foo { #[serde_as(as = &amp;#34;FromInto&amp;lt;String&amp;gt;&amp;#34;)] bar: MyCustomType, } 适用于需要为自定义类型实现序列化/反序列化的场景。</description>
    </item>
    
    <item>
      <title>在rust中使用protobuf</title>
      <link>https://czyt.tech/post/use-protobuf-in-rust/</link>
      <pubDate>Thu, 29 Aug 2024 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/use-protobuf-in-rust/</guid>
      <description>常规方式 安装必要工具 # 安装 protoc # 在 macOS 上： brew install protobuf # 在 Ubuntu 上： sudo apt-get install protobuf-compiler # 安装 Rust protobuf 代码生成器 cargo install protobuf-codegen 示例 创建一个protobuf的文件：
message.proto
syntax = &amp;#34;proto3&amp;#34;; package mypackage; message Person { string name = 1; int32 age = 2; string email = 3; } 然后执行命令
protoc --rust_out=. message.proto 如果是在项目中，在你的 Rust 项目中，添加必要的依赖到 Cargo.toml：
[dependencies] protobuf = &amp;#34;2.27.1&amp;#34; 然后可以在代码中访问生成的内容
use protobuf::Message; mod message; // 引入生成的模块 use message::Person; fn main() { let mut person = Person::new(); person.</description>
    </item>
    
    <item>
      <title>在go中使用CoAP</title>
      <link>https://czyt.tech/post/use-coap-in-go/</link>
      <pubDate>Mon, 26 Aug 2024 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/use-coap-in-go/</guid>
      <description>CoAP协议 CoAP（Constrained Application Protocol）是一种专为物联网（IoT）和受限环境设计的网络协议。它的主要目标是为资源受限的设备（如传感器、执行器等）提供一种轻量级的通信方式。以下是 CoAP 协议的几个关键特点和功能：
1. 轻量级设计 小开销：CoAP 使用 UDP（用户数据报协议）作为传输层，相比于 TCP（传输控制协议），它具有更小的头部开销，适合带宽有限的环境。 简化的消息格式：CoAP 消息格式简单，适合资源受限的设备。 2. 请求/响应模型 类似 HTTP：CoAP 采用类似于 HTTP 的请求/响应模型，客户端可以发送请求（如 GET、POST、PUT、DELETE）来与服务器交互。 资源导向：CoAP 允许客户端访问和操作服务器上的资源，资源通过 URI（统一资源标识符）进行标识。 3. 可靠性 确认机制：虽然 CoAP 基于 UDP，但它实现了可靠性机制，包括重传和确认，以确保消息的可靠传输。 非确认和确认消息：CoAP 支持两种类型的消息：确认消息（需要确认）和非确认消息（不需要确认），以适应不同的应用需求。 4. 观察功能 资源观察：CoAP 支持观察功能，允许客户端订阅资源的变化，当资源状态发生变化时，服务器会主动通知客户端。这减少了轮询请求的需要。 5. 多播支持 多播通信：CoAP 原生支持多播，允许服务器向多个客户端同时发送消息，适合需要广播信息的场景。 6. 安全性 DTLS：CoAP 可以与 DTLS（Datagram Transport Layer Security）结合使用，以提供数据加密和安全性，保护数据在传输过程中的安全。 应用场景 物联网：CoAP 广泛应用于物联网设备的通信，如智能家居、环境监测、工业自动化等。 资源受限设备：适合用于低功耗、低带宽的设备和网络环境。 在go中使用coap echo服务 server:
package main import ( &amp;#34;fmt&amp;#34; &amp;#34;log&amp;#34; &amp;#34;github.com/plgd-dev/go-coap/v3&amp;#34; &amp;#34;github.com/plgd-dev/go-coap/v3/message&amp;#34; &amp;#34;github.com/plgd-dev/go-coap/v3/message/codes&amp;#34; &amp;#34;github.com/plgd-dev/go-coap/v3/mux&amp;#34; ) func main() { r := mux.</description>
    </item>
    
    <item>
      <title>一些docker和k8s的笔记</title>
      <link>https://czyt.tech/post/some-notes-about-docker-and-k8s/</link>
      <pubDate>Sat, 17 Aug 2024 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/some-notes-about-docker-and-k8s/</guid>
      <description>常见的项目Dockerfile golang项目 # 构建阶段 FROM golang:1.23 AS builder # 设置工作目录, WORKDIR /app # 复制go.mod和go.sum文件 COPY go.mod go.sum ./ # 设置goproxy RUN go env -w GOPROXY=&amp;#39;https://goproxy.io,https://goproxy.cn,direct&amp;#39; # 下载依赖 RUN go mod download # 复制源代码 COPY . . # 构建应用 RUN CGO_ENABLED=0 GOOS=linux go build -o server . # 运行阶段 FROM alpine:latest # 安装ca-certificates以支持HTTPS, RUN apk --no-cache add ca-certificates WORKDIR /root/ # 从构建阶段复制编译好的二进制文件 COPY --from=builder /app/server . # 暴露端口（如果您的应用监听某个端口） EXPOSE 8080 # 运行应用 CMD [&amp;#34;.</description>
    </item>
    
    <item>
      <title>在rust中使用duckdb的一些笔记</title>
      <link>https://czyt.tech/post/some-notes-about-use-duckdb-in-rust/</link>
      <pubDate>Fri, 12 Jul 2024 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/some-notes-about-use-duckdb-in-rust/</guid>
      <description>基本使用 添加cargo包 在cargo.toml中添加
[dependencies] duckdb = {version = &amp;#34;1&amp;#34;} 示例代码 use duckdb::{params, Connection, Result}; use duckdb::arrow::record_batch::RecordBatch; use duckdb::arrow::util::pretty::print_batches; #[derive(Debug)] struct Person { id: i32, name: String, data: Option&amp;lt;Vec&amp;lt;u8&amp;gt;&amp;gt;, } fn main() -&amp;gt; Result&amp;lt;()&amp;gt; { let conn = Connection::open_in_memory()?; conn.execute_batch( r&amp;#34;CREATE SEQUENCE seq; CREATE TABLE person ( id INTEGER PRIMARY KEY DEFAULT NEXTVAL(&amp;#39;seq&amp;#39;), name TEXT NOT NULL, data BLOB ); &amp;#34;)?; let me = Person { id: 0, name: &amp;#34;Steven&amp;#34;.to_string(), data: None, }; conn.</description>
    </item>
    
    <item>
      <title>跟AI学习Rust的Atomic</title>
      <link>https://czyt.tech/post/learn-rust-atomic-with-ai/</link>
      <pubDate>Tue, 09 Jul 2024 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/learn-rust-atomic-with-ai/</guid>
      <description>QA 如何理解rust的atomic，常见操作有哪些 Rust中的原子类型（atomic types）是一种用于并发编程的工具，它们提供了对共享内存的安全访问机制。以下是对Rust原子类型的理解和常见操作：
理解Rust的atomic：
原子操作是不可分割的操作，它们在多线程环境中能够保证数据的一致性。 Rust的原子类型位于std::sync::atomic模块中。 原子类型可以在多个线程间安全地共享，无需使用互斥锁。 它们通常用于实现无锁数据结构和同步原语。 常见的原子类型操作：
加载（load）：
let value = atomic.load(Ordering::SeqCst); 存储（store）：
atomic.store(new_value, Ordering::SeqCst); 比较并交换（compare_and_swap）：
let result = atomic.compare_and_swap(expected, new, Ordering::SeqCst); 获取并增加（fetch_add）：
let previous = atomic.fetch_add(1, Ordering::SeqCst); 获取并减少（fetch_sub）：
let previous = atomic.fetch_sub(1, Ordering::SeqCst); 获取并按位或（fetch_or）：
let previous = atomic.fetch_or(0b0001, Ordering::SeqCst); 获取并按位与（fetch_and）：
let previous = atomic.fetch_and(0b1110, Ordering::SeqCst); 获取并按位异或（fetch_xor）：
let previous = atomic.fetch_xor(0b1111, Ordering::SeqCst); 这些操作都需要指定内存顺序（memory ordering），如SeqCst（顺序一致性）、Relaxed（松散）等，以控制操作的同步级别。
需要注意的是，虽然原子操作提供了线程安全的访问，但它们的使用可能会影响性能。在实际应用中，应根据具体需求选择合适的同步机制。
Rust的atomic常见内存顺序有哪些，它们各自的应用场景有哪些 Rust中的内存顺序（Memory Ordering）是一个重要的概念，它定义了原子操作如何与其他内存操作交互。在std::sync::atomic::Ordering枚举中，Rust提供了以下几种内存顺序选项：
Ordering::Relaxed Ordering::Release Ordering::Acquire Ordering::AcqRel Ordering::SeqCst 这些选项的主要区别如下：
Ordering::Relaxed（松散顺序） 最宽松的内存顺序 只保证原子操作本身的原子性 不提供任何同步或顺序保证 性能最好，但最难推理</description>
    </item>
    
    <item>
      <title>GIT 别名的 10 个级别【机翻】</title>
      <link>https://czyt.tech/post/10-levels-of-git-aliases-cn/</link>
      <pubDate>Tue, 25 Jun 2024 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/10-levels-of-git-aliases-cn/</guid>
      <description>第一部分：初级到中级概念 原文 https://www.eficode.com/blog/10-levels-of-git-aliases-beginner-to-intermediate-concepts
您是否知道 Git 可以通过多种方式根据您的需求进行定制？ 在 Git 中创建别名是一项强大的功能，它允许您为更长的 Git 命令（以及更多命令）定义“快捷方式”。对于某些人来说，它只是一个让命令行 Git 使用变得可行的工具，但我将向您展示 Git 别名是如此强大，它们可以帮助使命令行成为使用 Git 的首选且最有效的方式。
创建 Git 别名的主要动机可能是以下一项或多项：
优化：为常用的 Git 命令创建快捷方式。 定制：让 Git 按照您想要的方式运行或支持团队商定的习惯。 记忆：易于记忆的复杂操作快捷键。 在我的博客系列的第 1 部分中，我将带您从非常简单的基础知识开始，介绍只需键入较长命令的 Git 别名，一直到甚至许多经验丰富的 Git 老手从未使用过的更高级功能。
第 2 部分将从这里继续，介绍更高级的概念，并尝试真正“外面”使用 Git 别名，包括一些彻头彻尾疯狂的示例，然后再讨论解决相同需求的替代方案。
学习和理解这些技术，无论是用于从别人那里窃取的别名还是自己冒险突破界限，都将使您成为更高效、更强大的 Git 用户，并有望让您使用 Git 的日常生活变得更加愉快。在此过程中，您可能还会学到一些提示和技巧，并探索您甚至不知道的 Git 角落。
什么是 Git 别名，我们如何设置它们？ Git 别名是 Git 子命令的替代，就像 Bash 别名是其他 Bash 命令或脚本的替代一样。 Git 只是允许您定义自己的 Git 命令来执行您想要的操作，并且可以与内置命令无缝地使用。
别名是在 Git 配置层次结构中定义的，但由于我们通常希望它们在我们计算机上的任何地方都可以工作，因此全局配置是它们的自然家园。
您可以通过直接编辑全局配置文件或使用git config命令来添加别名。
要创建您的第一个简单别名，只需尝试：
$ git config --global alias.</description>
    </item>
    
    <item>
      <title>在局域网多台设备上执行ssh脚本</title>
      <link>https://czyt.tech/post/execute-ssh-scripts-on-muti-machines-in-lan/</link>
      <pubDate>Fri, 21 Jun 2024 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/execute-ssh-scripts-on-muti-machines-in-lan/</guid>
      <description>需要的软件包 需要安装sshpass和nmap
代码示例 run_on_lan_machines.sh
#!/usr/bin/env bash USERNAME=&amp;#34;czyt&amp;#34; PASSWORD=&amp;#34;upwd&amp;#34; SUDO_PASSWORD=&amp;#34;supwd&amp;#34; SCRIPT=&amp;#34;install_test.sh&amp;#34; REMOTE_SCRIPT_PATH=&amp;#34;/tmp/$SCRIPT&amp;#34; IP_RANGE=&amp;#34;172.168.1.0/24&amp;#34; # 扫描在线主机 echo &amp;#34;Scanning for hosts with open SSH ports...&amp;#34; nmap -p 22 $IP_RANGE --open -oG scan_result.txt # 提取在线主机IP地址 grep &amp;#34;/open/tcp//ssh/&amp;#34; scan_result.txt | awk &amp;#39;{print $2}&amp;#39; &amp;gt; ip_list.txt # 检查是否有找到的IP地址 if [[ ! -s ip_list.txt ]]; then echo &amp;#34;No hosts with open SSH ports found.&amp;#34; exit 1 fi # 逐个IP执行脚本 while IFS= read -r ip; do echo &amp;#34;Uploading and executing script on $ip&amp;#34; # 上传脚本到远程主机 sshpass -p &amp;#34;$PASSWORD&amp;#34; scp -o StrictHostKeyChecking=no &amp;#34;$SCRIPT&amp;#34; &amp;#34;$USERNAME@$ip:$REMOTE_SCRIPT_PATH&amp;#34; if [[ $?</description>
    </item>
    
    <item>
      <title>定制你自己的cockpit</title>
      <link>https://czyt.tech/post/custom-your-own-cockpit/</link>
      <pubDate>Sun, 09 Jun 2024 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/custom-your-own-cockpit/</guid>
      <description>什么是Cockpit Cockpit，官网https://cockpit-project.org是一个基于web的服务器管理界面,可以通过浏览器访问。它提供了一个统一的管理界面,用于管理和监控Linux服务器。以下是Cockpit的一些主要特点:
易用性 提供直观的图形化界面,无需命令行操作 支持多种Linux发行版,如Red Hat、CentOS、Fedora、Debian、Ubuntu等 可以通过浏览器远程访问,无需安装客户端软件
功能特性 系统监控:实时查看CPU、内存、磁盘、网络等系统资源的使用情况 服务管理:启动、停止、重启系统服务 存储管理:管理磁盘分区、LVM、RAID等存储设备 网络配置:配置网卡、防火墙、虚拟网络等网络设置 日志查看:查看系统日志和审计日志 用户管理:添加、删除、修改系统用户和组 软件包管理:安装、更新、删除软件包 安全性 基于角色的访问控制(RBAC),可以为不同用户设置不同的权限 支持SSL/TLS加密,保护数据传输安全 可以与LDAP、Kerberos等认证系统集成 总的来说,Cockpit是一个功能强大、易用的Linux服务器管理工具,可以大大提高管理员的工作效率。它适用于各种规模的Linux服务器,是Linux系统管理的一个不错的选择。
安装 cockpit在主流操作系统都一键安装的包。请参考https://cockpit-project.org/running.html的Installation &amp;amp; Setup部分
自定义你的cockpit 修改登陆界面标题 修改 /etc/cockpit/cockpit.conf
[WebService] LoginTitle=gophers land 更多参数，请参考 https://cockpit-project.org/guide/latest/cockpit.conf.5.html
编写一个rustdesk id viewer页面 创建目录结构 mkdir -p /usr/share/cockpit/rustdesk cd /usr/share/cockpit/rustdesk cockpit支持从下面两个位置获取配置
~/.local/share/cockpit 在您的主目录中。它用于用户特定的包和您正在开发的包。您可以即时编辑这些内容并刷新浏览器以查看更改。 /usr/share/cockpit 和 /usr/share/local/cockpit是可供系统所有用户使用的已安装软件包的位置。更改此路径中的文件需要管理员（“root”）权限。在 Cockpit 运行时，不应更改这些内容。 因为涉及一些js库，我想复用原来的，所以我这里使用的是第二个位置。 可以通过cockpit-bridge --packages 查看已经安装的包：
apps Applications /usr/share/cockpit/apps base1 /usr/share/cockpit/base1 metrics /usr/share/cockpit/metrics network Networking /usr/share/cockpit/networkmanager rustdesk RustDesk ID /usr/share/cockpit/rustdesk shell /usr/share/cockpit/shell static /usr/share/cockpit/static storage Storage /usr/share/cockpit/storaged system Overview, Services, Logs, Terminal /usr/share/cockpit/systemd updates Software updates /usr/share/cockpit/packagekit users Accounts /usr/share/cockpit/users 创建文件 manifest.</description>
    </item>
    
    <item>
      <title>在树莓派3b上搭建GitHub Linux arm64 runner</title>
      <link>https://czyt.tech/post/set-up-github-linux-arm64-runner-on-raspi3b/</link>
      <pubDate>Wed, 22 May 2024 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/set-up-github-linux-arm64-runner-on-raspi3b/</guid>
      <description>最近需要在GitHub Action上自动构建一些软件，但是Github 不提供Arm64的runner，自能自建。
github 官方准备在2024年底开始为开源项目提供arm的runner
树莓派设置 Arch系统 安装基本软件 安装下面的这些软件，不同的构建可能有所区别：
sudo pacman -S curl zip unzip tar cmake ninja docker Github Action 依赖于docker，所以我们需要安装好docker
sudo pacman -S docker 然后将当前用户添加到docker的组
sudo usermod -aG docker $USER 查看和确认:
grep docker /etc/group Ubuntu系统 安装基本软件 docker 安装前的配置
# Add Docker&amp;#39;s official GPG key: sudo apt-get update sudo apt-get install ca-certificates curl sudo install -m 0755 -d /etc/apt/keyrings sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc sudo chmod a+r /etc/apt/keyrings/docker.asc # Add the repository to Apt sources: echo \ &amp;#34;deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.</description>
    </item>
    
    <item>
      <title>一些RustDesk部署的笔记</title>
      <link>https://czyt.tech/post/some-notes-about-rust-desk-deploy/</link>
      <pubDate>Fri, 17 May 2024 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/some-notes-about-rust-desk-deploy/</guid>
      <description>自建 Server 搭建中转服务器 参考官方 https://rustdesk.com/docs/en/self-host/rustdesk-server-oss/install/
一些有用的链接：
https://github.com/infiniteremote/installer/blob/main/install.sh 搭建api server api server是高级版的功能，但是我们可以通过自建api server实现设备id同步等部分操作。推荐使用：
https://github.com/kingmo888/rustdesk-api-server
https://github.com/sctg-development/sctgdesk-server
这个是带web console的用户名和密码分别是admin和Hello,world!
https://github.com/lejianwen/rustdesk-server
更多的实现，可以去Github 搜一搜 https://github.getafreenode.com/topics/rustdesk-api-server
客户端自定义部署 基于Github Action 参考官方 https://rustdesk.com/docs/en/dev/build/all/
对于arm版本的自动化构建，Github Action暂时不提供arm64的runner
基于配置文件和命令行 RustDesk有用的命令行参数 --password 可用于设置永久密码。 --get-id 可用于检索 ID。 --set-id 可用于设置ID，请注意ID应以字母开头。 --silent-install 可用于在 Windows 上静默安装 RustDesk。 RustDesk 配置文件 RustDesk的配置文件，windows为&amp;quot;%appdata%\RustDesk\config\RustDesk2.toml&amp;quot;linux则为~/.config/rustdesk/RustDesk2.toml,下面是一个完整的配置文件示例：
新版貌似会读取登录用户的目录下的，老的版本是修改root用户目录下的文件
rendezvous_server = &amp;#39;rustdesk.xxxx.tech:21116&amp;#39; nat_type = 1 serial = 0 [options] # 对应安全选项-&amp;gt;权限中的完全访问 access-mode = &amp;#39;full&amp;#39; # 对应安全选项-&amp;gt;安全-&amp;gt;允许IP直接访问 direct-server = &amp;#39;Y&amp;#39; # 对应安全选项-&amp;gt;安全-&amp;gt;自动关闭不活跃的会话 allow-auto-disconnect = &amp;#39;Y&amp;#39; stop-service = &amp;#39;Y&amp;#39; key = &amp;#39;KEY&amp;#39; relay-server = &amp;#39;rustdesk.</description>
    </item>
    
    <item>
      <title>Windows ollama一些有用的批处理脚本</title>
      <link>https://czyt.tech/post/some-useful-batch-scripts-for-ollama-windows/</link>
      <pubDate>Thu, 09 May 2024 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/some-useful-batch-scripts-for-ollama-windows/</guid>
      <description>模型设置 模型路径设置 @echo off echo set models storage path to current Dir %~dp0models SETX OLLAMA_MODELS %~dp0models echo setup done timeout 5 这个脚本会将模型的存储路径放在批处理相同目录的models目录下
启动 一键启动ollam和对应模型 @echo off echo start ollama... start %~dp0ollama.exe serve echo boot model start %~dp0ollama.exe run phi3 </description>
    </item>
    
    <item>
      <title>Nom指南中文版</title>
      <link>https://czyt.tech/post/the-nominomicon-guide-cn/</link>
      <pubDate>Mon, 29 Apr 2024 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/the-nominomicon-guide-cn/</guid>
      <description>原文https://tfpk.github.io/nominomicon/introduction.html，使用Google进行机翻
nominomicon 欢迎阅读这本关于Nom的书；使用 Nom 解析器发挥巨大作用的指南。本指南将向您介绍使用 Nom 的理论和实践。
本指南仅假设您：
想学习Nom， 已经熟悉 Rust。 Nom 是一个解析器组合器库。换句话说，它为您提供了定义以下内容的工具：
“解析器”（接受输入并返回输出的函数），以及 “组合器”（采用解析器并将它们组合在一起的函数！）。 通过将解析器与组合器相结合，您可以从简单的解析器构建复杂的解析器。这些复杂的解析器足以理解 HTML、mkv 或 Python！
在我们出发之前，列出一些注意事项很重要：
本指南适用于 Nom7。 Nom 发生了重大变化，因此如果您正在搜索文档或 StackOverflow 答案，您可能会找到较旧的文档。一些常见的表明它是旧版本的指标是： 2021 年 8 月 21 日之前的文档 named! 宏的使用 使用 CompleteStr 或 CompleteByteArray 。 Nom 可以解析（几乎）任何东西；但本指南几乎完全专注于将完整的 &amp;amp;str 解析为事物。 第一章：Nom 方式 首先，我们需要了解 nom 思考解析的方式。正如简介中所讨论的，nom 让我们构建简单的解析器，然后组合它们（使用“组合器”）。
让我们讨论一下“解析器”实际上是做什么的。解析器接受输入并返回结果，其中：
Ok 表示解析器成功找到了它要查找的内容；或者 Err 表示解析器找不到它要查找的内容。 如果解析器成功，它将返回一个元组。元组的第一个字段将包含解析器未处理的所有内容。第二个将包含解析器处理的所有内容。这个想法是解析器可以愉快地解析输入的第一部分，而无法解析整个内容。
如果解析器失败，则可能会返回多个错误。然而，为了简单起见，在接下来的章节中，我们将不对这些进行探讨。
┌─► Ok( │ what the parser didn&amp;#39;t touch, │ what matched the regex │ ) ┌─────────┐ │ my input───►│my parser├──►either──┤ └─────────┘ └─► Err(.</description>
    </item>
    
    <item>
      <title>在你的Rust程序中使用Deref和DerefMut trait</title>
      <link>https://czyt.tech/post/use-deref-and-derefmut-trait-in-your-rust-application/</link>
      <pubDate>Thu, 25 Apr 2024 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/use-deref-and-derefmut-trait-in-your-rust-application/</guid>
      <description>Deref Deref 是一种 Rust 编译器宏，用于实现 Deref trait。Deref trait 允许将自定义类型转换为引用，从而使其能够用于任何需要引用的地方。
Deref 宏通常用于以下场景：
新类型模式: 当您定义一个新类型时，deref 宏可以使其能够像引用一样使用。例如，您可以创建一个 Box 类型，该类型将值存储在堆上，并实现 Deref trait 以便可以使用 * 运算符访问值。 链式访问: deref 宏可以用于创建链式访问语法。例如，您可以创建一个 Vec&amp;lt;Box&amp;lt;T&amp;gt;&amp;gt; 类型，其中 T 是任何可实现 Deref trait 的类型。这允许您使用 * 运算符在向量中迭代并访问每个值。 泛型代码: deref 宏可以用于编写泛型代码，该代码可以与任何可实现 Deref trait 的类型一起使用。例如，您可以创建一个函数，该函数接受任何可实现 Deref trait 的类型并返回其值。 deref宏在 Rust 中扮演着重要的角色，它允许你自定义类型在特定情况下表现得像引用一样。这带来了许多便利，例如：
简化访问底层数据: 无需手动解引用，直接访问结构体内部数据。 使用运算符重载: 使自定义类型支持 * 和 [] 等运算符。 自动解引用: 在需要引用的地方，自动解引用自定义类型。 实用例子 1. 自定义智能指针
use std::ops::Deref; struct MyBox&amp;lt;T&amp;gt;(T); impl&amp;lt;T&amp;gt; Deref for MyBox&amp;lt;T&amp;gt; { type Target = T; fn deref(&amp;amp;self) -&amp;gt; &amp;amp;Self::Target { &amp;amp;self.</description>
    </item>
    
    <item>
      <title>一些Rust的机器学习资料</title>
      <link>https://czyt.tech/post/some-rust-references-about-machine-learning/</link>
      <pubDate>Wed, 24 Apr 2024 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/some-rust-references-about-machine-learning/</guid>
      <description>代码示例 ONNX web interface to YOLOv8 object detection neural network implemented on Rust. 仓库地址 Client/server face detection from your webcam with tokio, axum, tract-onnx and the lightweight ultraface network. 仓库地址 Segment anything inference using Rust llm https://github.com/jondot/awesome-rust-llm https://github.com/gabotechs/MusicGPT 其他 https://github.com/rustai-solutions 文章 图书 </description>
    </item>
    
    <item>
      <title>一些rust clap库的笔记</title>
      <link>https://czyt.tech/post/some-notes-about-rust-clap/</link>
      <pubDate>Fri, 19 Apr 2024 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/some-notes-about-rust-clap/</guid>
      <description>小试牛刀 clap是rust下面的一款命令行解析的库，下面是一些使用的笔记。
在Cargo.toml中添加下面的依赖
[dependencies] clap = {version = &amp;#34;4&amp;#34;,features = [&amp;#34;derive&amp;#34;]} 对应feature的作用如下：
默认特性
std: Not Currently Used. Placeholder for supporting no_std environments in a backwards compatible manner. color: Turns on colored error messages. help: Auto-generate help output usage: Auto-generate usage error-context: Include contextual information for errors (which arg failed, etc) suggestions: Turns on the Did you mean &#39;--myoption&#39;? feature for when users make typos. 可选特性
deprecated: Guided experience to prepare for next breaking release (at different stages of development, this may become default) derive: Enables the custom derive (i.</description>
    </item>
    
    <item>
      <title>使用 Pest 和 PEG 构建 Rust 解析器【译】</title>
      <link>https://czyt.tech/post/building-rust-parser-pest-peg/</link>
      <pubDate>Fri, 19 Apr 2024 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/building-rust-parser-pest-peg/</guid>
      <description>本文原为为 https://blog.logrocket.com/building-rust-parser-pest-peg/，使用Google翻译进行机翻，部分内容做了细微润色。
编写一个高效的词法分析器对来解析复杂的结构可能具有挑战性。如果格式或结构是固定的，并且您必须以易于理解、维护和扩展以适应未来更改的方式编写解析器，那么这会变得更加复杂。
在这些情况下，我们可以使用解析器生成器，而不是手写解析器或手动解析我们的项目。在本文中，我们将回顾什么是解析器生成器，并探索一个名为 Pest 的 Rust 解析工具。我们将涵盖：
[TOC]
请注意，您应该能够轻松地阅读和编写基本的 Rust 代码，例如函数、结构和循环。
什么是解析器生成器？ 解析器生成器是一些程序，它接受解析器需要考虑的规则，然后以编程方式为您生成一个解析器，该解析器将根据这些规则解析输入。
大多数时候，规则以简化语言（例如正则表达式）提供给解析器生成器。因此，当您想要通过更改规则或添加新规则来更新解析器时，您只需更新或添加规则的正则表达式即可。然后，当您运行解析器生成器时，它将重写解析器以适应这些规则。
可以想象使用这样的解析工具可以节省多少时间。许多解析器生成器还会生成词法分析器，因此您不必自己编写词法分析器。如果生成的词法分析器不适合您，您可以选择使用您自己的词法分析器运行解析器（如果需要）。
目前，Rust 生态系统中有多个解析器生成器可供您使用。其中最受欢迎的三个是 LalrPop、Nom 和 Pest。
LalrPop 与 Yacc 非常相似，它让您定义规则和相应的操作。我个人用它来为我的 8086 模拟器项目编写规则。
Nom 是一个解析器组合器库，您可以在其中将规则编写为函数组合。这更面向解析二进制输入，但也可用于解析字符串。
最后，Pest 使用 Parsing Expression Grammar 来定义解析规则。我们将在这篇文章中详细探讨 Rust 与 Pest 的解析。
Pest 中的解析表达式语法是什么？ 解析表达式语法（PEG）是用 Pest 定义 Rust 解析“规则”的方法之一。 Pest 接受具有此类规则定义的文件的输入，并生成遵循它们的 Rust 解析器。
在编写规则时，您应该考虑 Pest 和 PEG 的三个定义特征。
第一个特点是贪婪匹配。 Pest 将始终尝试将输入的最大值与规则相匹配。例如，假设我们编写了如下规则：
match one or more alphabets 在这种情况下，Pest 将消耗输入中的所有内容，直到达到数字、空格或符号。在此之前它不会停止。
要考虑的第二个特征是交替匹配是有序的。为了理解这意味着什么，假设我们给出了多个匹配来满足一条规则，如下所示：
rule1 | rule2 | rule3 Pest 将首先尝试匹配 rule1 。当且仅当 rule1 失败时，Pest才会尝试匹配 rule2 ，依此类推。如果第一条规则匹配，Pest 将不会尝试匹配任何其他规则来找到最佳匹配。</description>
    </item>
    
    <item>
      <title>使用rust操作mongodb</title>
      <link>https://czyt.tech/post/operate-mongodb-in-rust/</link>
      <pubDate>Mon, 15 Apr 2024 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/operate-mongodb-in-rust/</guid>
      <description>准备工作 使用rust进行mongodb连接需要添加依赖，在Cargo.toml中添加下面的依赖
[dependencies] mongodb=&amp;#34;2&amp;#34; serde = &amp;#34;1&amp;#34; 添加serde的原因是我们建模的时候需要用。
预备知识 连接数据库 下面是我们的本地数据库连接
const CONNECT_STR:&amp;amp;str = &amp;#34;mongodb://czyt:czyt@192.168.1.21:27017&amp;#34;; 然后使用连接字符串进行数据库连接
let mut client_options = ClientOptions::parse_async(CONNECT_STR).await?; // Set the server_api field of the client_options object to Stable API version 1 let server_api = ServerApi::builder() .version(ServerApiVersion::V1) .build(); client_options.server_api = Some(server_api); // Create a new client and connect to the server let client = Client::with_options(client_options)?; // Send a ping to confirm a successful connection client.database(&amp;#34;admin&amp;#34;).run_command(doc! { &amp;#34;ping&amp;#34;: 1 }, None).</description>
    </item>
    
    <item>
      <title>enum_dispatch在rust中的简单使用</title>
      <link>https://czyt.tech/post/simple-usage-of-enum-dispatch-in-rust/</link>
      <pubDate>Mon, 08 Apr 2024 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/simple-usage-of-enum-dispatch-in-rust/</guid>
      <description>请先看下面这个例子：
enum Creatures { Dog(Dog), Cat(Cat), } trait Animal { fn make_sound(&amp;amp;self); } struct Dog; struct Cat; impl Animal for Dog { fn make_sound(&amp;amp;self) { println!(&amp;#34;Bark!&amp;#34;); } } impl Animal for Cat { fn make_sound(&amp;amp;self) { println!(&amp;#34;Meow!&amp;#34;); } } fn main() { let animals: Vec&amp;lt;Creatures&amp;gt; = vec![ Creatures::Dog(Dog), Creatures::Cat(Cat), ]; for animal in animals { match animal { Creatures::Dog(dog) =&amp;gt; dog.make_sound(), Creatures::Cat(cat) =&amp;gt; cat.make_sound(), } } } 在 main 函数中，我们创建了一个名为 animals 的 Vec&amp;lt;Creatures&amp;gt; 向量，其中包含不同种类的生物。遍历 animals 向量时，使用 match 语句来确定每个生物的实际类型，然后调用相应实例的 make_sound 方法。</description>
    </item>
    
    <item>
      <title>使用Mono.Cecil自动补丁.net程序</title>
      <link>https://czyt.tech/post/use-mono-cecil-to-auto-patch-dotnet-application/</link>
      <pubDate>Thu, 04 Apr 2024 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/use-mono-cecil-to-auto-patch-dotnet-application/</guid>
      <description>坚果云是我常用的一个工具，但是我一般喜欢使用绿色版，不喜欢程序到处写文件，也不喜欢重装以后还要各种登录。所以要折腾“绿色版”来使用。坚果云的完整版下载链接为
https://pkg-cdn.jianguoyun.com/static/exe/installer/NutstoreWindowsWPF_Full.exe 手动IL处理 一般手动处理坚果云的个人用户资料目录。需要使用dnspyEx，然后修改NutstoreLib.dll中的Utils.DirectoryUtils下的APPDATA_NUTSTORE_DIR,下面是我的一个手动IL修改列表：
0 0000 call string NutstoreLib.Utils.DirectoryUtils::get_NUTSTORE_INSTALL_DIR() 1 0005 newobj instance void [mscorlib]System.IO.DirectoryInfo::.ctor(string) 2 000A call instance class [mscorlib]System.IO.DirectoryInfo [mscorlib]System.IO.DirectoryInfo::get_Parent() 3 000F callvirt instance string [mscorlib]System.IO.FileSystemInfo::get_FullName() 4 0014 ldstr &amp;#34;UserData&amp;#34; 5 0019 call string [Pri.LongPath]Pri.LongPath.Path::Combine(string, string) 6 001E ret 自动IL处理 借助Mono.Cecil我们可以实现上面的功能，自动进行dll的patch修改。
注：因为我不喜欢调用太多的库，所以Pri.LongPath.Path::Combine(string, string)我改为了系统的库
完整代码如下：
using System.Linq; using Mono.Cecil; using Mono.Cecil.Cil; namespace NutstoreAutoPatch { internal class Program { public static void Main(string[] args) { const string nutstoreLib = &amp;#34;NutstoreLib.dll&amp;#34;; const string directoryutils = &amp;#34;NutstoreLib.</description>
    </item>
    
    <item>
      <title>让你的ssh连接更安全</title>
      <link>https://czyt.tech/post/security-your-ssh-connect/</link>
      <pubDate>Tue, 02 Apr 2024 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/security-your-ssh-connect/</guid>
      <description>缘起 最近服务器日志有一些ssh的暴力破解登录记录。所以尝试使用下面几个方案来保证ssh的安全。
修改ssh配置 对 SSH 进行安全加固可以通过多种不同的策略和手段来实行，以下是一些有效的措施：
禁用 Root 登录： 修改 SSH 配置文件 /etc/ssh/sshd_config 中的 PermitRootLogin 选项，将其设置为 no，以防止通过 SSH 使用 root 用户直接登录服务器。 使用公钥加密： 如前所述，通过使用基于密钥的认证来替代密码认证可以极大地提高安全性。 限制用户 SSH 访问： 在 /etc/ssh/sshd_config 中使用 AllowUsers 或 AllowGroups 指令来限制那些用户或者组可以通过 SSH 登录。同样，可以使用 DenyUsers 或 DenyGroups 以禁止特定用户或用户组的访问。 SSH 协议版本： 确保使用的是 SSH-2，因为 SSH-1 已知存在安全漏洞。 更改默认 SSH 端口： 修改配置文件中的 Port 选项，将 SSH 服务的监听端口从默认的 22 更改到其他值。 使用 TCPWrappers 限制访问： 通过 /etc/hosts.allow 和 /etc/hosts.deny 控制哪些 IP 地址允许或拒绝访问。 设置连接超时： 设置自动注销用户的超时时间，避免定期保持未使用的 SSH 会话。使用参数 ClientAliveInterval 和 ClientAliveCountMax 控制这些设置。 使用 Two-Factor Authentication（两因素认证）： 安装并配置像 Google Authenticator 这样的两因素认证系统，要求用户在登录时提供密码以及来自手机或其他设备的一次性密码（OTP）。 使用 iptables 或 ufw 防火墙： 配置 Linux 防火墙以只允许特定的 IP 地址或 IP 范围来进行 SSH 连接。 限制最大登录尝试次数： 在 /etc/ssh/sshd_config 文件中设置 MaxAuthTries 限制登录尝试的次数。 使用复杂且定期更新的密码： 再次强调即使在启用密钥登录的情况下，也应该使用强密码并定期更新。 监控 SSH 访问日志： 定期查看 /var/log/auth.</description>
    </item>
    
    <item>
      <title>一个RustFace demo程序</title>
      <link>https://czyt.tech/post/rustface-demo-app/</link>
      <pubDate>Tue, 27 Feb 2024 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/rustface-demo-app/</guid>
      <description>下面是一个基于RustFace这个库的demo程序。基于原项目 整理。image随便下载一张，model.bin从原项目进行下载即可。
Cargo.toml配置
[package] name = &amp;#34;faceDemo&amp;#34; version = &amp;#34;0.1.0&amp;#34; edition = &amp;#34;2021&amp;#34; # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] rustface = &amp;#34;0&amp;#34; image= &amp;#34;0.23.14&amp;#34; src/main.rs
use rustface::{Detector, FaceInfo, ImageData}; fn main() { let imageFile = &amp;#34;1.png&amp;#34;; let modelFile = &amp;#34;model.bin&amp;#34;; let mut detector = rustface::create_detector(modelFile).unwrap(); detector.set_min_face_size(20); detector.set_score_thresh(2.0); detector.set_pyramid_scale_factor(0.8); detector.set_slide_window_step(4, 4); let img = image::open(imageFile).unwrap(); let gray = img.to_luma8(); let (width, height) = gray.dimensions(); let mut image = ImageData::new(&amp;amp;*gray, width, height); for face in detector.</description>
    </item>
    
    <item>
      <title>Rust完整备忘单【译】</title>
      <link>https://czyt.tech/post/the-completesh-rust-cheat-sheet/</link>
      <pubDate>Fri, 23 Feb 2024 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/the-completesh-rust-cheat-sheet/</guid>
      <description>原文 https://katib.moe/the-completesh-rust-cheat-sheet 本文大部分通过机器翻译进行翻译，小部分进行了微调。官方有个更全的 https://cheats.rs
这个“完整的 Rust 备忘单”提供了 Rust 编程语言的全面指南，涵盖了它的所有主要功能。涵盖的主题范围从非常基础的知识（例如语法和基本概念）到更复杂的方面（例如并发和错误处理）。该备忘单还深入研究了 Rust 的独特功能，例如所有权、借用和生命周期，以及其强大的类型系统和健壮的宏系统。对于每个主题，都提供了清晰的示例来阐明解释。对于刚刚开始使用 Rust 的初学者和想要快速回顾特定 Rust 概念的经验丰富的开发人员来说，这是一个理想的资源。
我编写了这份备忘单作为 Rust 编程语言的综合指南，旨在将其作为个人参考工具。然而，Rust 社区的美妙之处在于共享学习和协作。因此，如果您发现我遗漏的内容、错误，或者您有改进建议，请随时分享您的反馈。请记住，没有人是绝对正确的，本资源也不例外 - 通过您的见解，我们可以继续改进和完善它。快乐 Rustacean！
基本语法和概念 你好世界 这是标准的“你好，世界！” Rust 中的程序。
fn main() { println!(&amp;#34;Hello, world!&amp;#34;); } 变量和可变性 Rust 中的变量默认是不可变的。要使变量可变，请使用 mut 关键字。
let x = 5; // immutable variable let mut y = 5; // mutable variable y = 6; // this is okay 数据类型 Rust 是一种静态类型语言，这意味着它必须在编译时知道所有变量的类型。
let x: i32 = 5; // integer type let y: f64 = 3.</description>
    </item>
    
    <item>
      <title>Rust的一些难点解惑【译】</title>
      <link>https://czyt.tech/post/the-hard-things-about-rust/</link>
      <pubDate>Wed, 21 Feb 2024 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/the-hard-things-about-rust/</guid>
      <description>原文 https://katib.moe/the-hard-things-about-rust, 本文使用机器翻译而成，部分文字进行了调整。
Rust 是一种系统编程语言，运行速度极快，可防止段错误并保证线程安全。虽然这些功能使 Rust 成为系统编程的强大工具，但它们也引入了一些对于来自其他语言的人可能不熟悉的新概念。
在这份综合指南“Rust 的困难之处”中，我们的目标是阐明 Rust 的这些具有挑战性的方面，并使新手和经验丰富的程序员都可以使用它们。我们将阐明这些复杂的概念，并用具体示例和现实场景来说明每个概念，以便更好地理解。
以下是我们将要介绍的内容：
所有权：我们将从 Rust 中所有权的基本概念开始。我们将探讨一个值拥有所有者意味着什么，所有权如何转移，以及 Rust 的所有权模型如何帮助内存管理。 借用和生命周期：在所有权的基础上，我们将深入研究借用和生命周期，这两个相互关联的概念可让您安全地引用数据。 切片：我们将揭开切片的神秘面纱，切片是内存块的视图，它在 Rust 中广泛用于高效访问数据。 错误处理：Rust 处理错误的方法是独特且稳健的。我们将介绍 Result 和 Option 类型，以及如何使用它们进行优雅的错误处理。 并发：我们将深入研究 Rust 强大而复杂的并发模型。我们将讨论线程、消息传递和共享状态并发等。 高级类型和Trait：我们将探索 Rust 的一些高级类型，例如 Box 、 Rc 、 Arc 。我们还将介绍 Trait 和 Trait 对象。 Async/Await 和 Futures：当我们转向高级概念时，我们将解释 Rust 的 async/await 语法和用于处理异步编程的 Futures 模型。 本指南的目标不仅仅是提供这些主题的概述，而是帮助您了解这些概念背后的基本原理、它们在幕后如何工作以及如何在 Rust 程序中有效地使用它们。
无论您是希望深入了解该语言的 Rust 初学者，还是旨在巩固对这些复杂概念的理解的中级 Rustacean，本指南都适合您。让我们踏上这段征服 Rust 难点的旅程吧！
所有权 所有权是 Rust 的一个基本概念。它是 Rust 内存安全方法的一部分，使 Rust 在编程语言中独一无二。理解所有权对于编写 Rust 程序至关重要，因为许多其他 Rust 概念（例如借用和生命周期）都是建立在它之上的。</description>
    </item>
    
    <item>
      <title>golang检测字节是否为utf-8字节的起始字节</title>
      <link>https://czyt.tech/post/golang-check-byte-is-start-byte-of-utf8-bytes/</link>
      <pubDate>Mon, 19 Feb 2024 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/golang-check-byte-is-start-byte-of-utf8-bytes/</guid>
      <description>原理 UTF-8 编码使用不同长度的字节序列来表示 Unicode 字符。这些序列的长度从一个字节到四个字节不等，每个字节都有特定的比特模式。您可以通过观察任何字节的最高位（也就是最左边的几位比特），来判断这个字节是不是某个字符的 UTF-8 编码的起始字节或中间字节：
单字节字符（U+0000 到 U+007F）以 0xxxxxxx 为模式，其中 x 可以是 0 或 1。这种单字节的高位为 0，表示它是 ASCII 字符的起始（也是唯一）字节。
UTF-8 编码的起始字节（即多字节序列的第一个字节）模式为 110xxxxx（对于两字节编码）、1110xxxx（对于三字节编码）或 11110xxx（对于四字节编码）。
对于一个 UTF-8 字符的非起始字节（也称为连续字节或中间字节），其模式为 10xxxxxx。
因此，如果你看到一个字节，它的最高两位是 10，那么它是 UTF-8 编码中的一个连续字节。如果最高一位是 0 或者高位模式匹配 110、1110 或 11110，它就是起始字节。
举例来说：
0xxxxxxx - UTF-8 字符的起始字节（单字节 ASCII 字符） 110xxxxx - 两字节编码的起始字节 1110xxxx - 三字节编码的起始字节 11110xxx - 四字节编码的起始字节 10xxxxxx - 中间字节 通过检查字节的最高位，您就可以迅速确定它是 UTF-8 编码序列的起始字节还是中间字节。
实现 go语言实现 package main import ( &amp;#34;fmt&amp;#34; ) // isUTF8StartByte checks whether a byte is a UTF-8 start byte.</description>
    </item>
    
    <item>
      <title>go switch的6种用法【译】</title>
      <link>https://czyt.tech/post/use-switch-in-go-in-6-ways/</link>
      <pubDate>Sat, 17 Feb 2024 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/use-switch-in-go-in-6-ways/</guid>
      <description>文章原文链接为 https://blog.devtrovert.com/p/switch-in-go-6-ways-to-use-it
照片由 Zbyněk Skrčený 在 Unsplash 上拍摄
Go 以其简单而闻名，但我注意到并不是每个人都熟悉 switch 语句在这种语言中的多功能性。
首先，如果您不熟悉 Go 的 switch 语句，与其他语言相比，它可能看起来有点不同。这是一个简单的例子来展示它的样子：
func main() { var i int = 1 switch i { case 1: fmt.Println(&amp;#34;i is 1&amp;#34;) case 2: fmt.Println(&amp;#34;i is 2&amp;#34;) default: fmt.Println(&amp;#34;i is not 1 or 2&amp;#34;) } } Go 的 switch 的一个很酷的事情是，一旦找到匹配项，它就会停止，你不需要在每个 case 的末尾添加一个 break 语句。
但不仅仅如此。
Go 中的 switch 语句有两部分：分号之前的部分是初始化器，分号之后的部分是我们要检查的值。
我们可以选择同时使用、使用其中之一或都不使用：
switch initializer; value {} switch initializer {} switch value {} switch {} 有趣，对吧？</description>
    </item>
    
    <item>
      <title>跟AI学习Rust</title>
      <link>https://czyt.tech/post/learn-rust-with-ai/</link>
      <pubDate>Fri, 16 Feb 2024 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/learn-rust-with-ai/</guid>
      <description>本文为学习rust过程中，向ai提问的内容汇总。配套图书为《Rust程序设计 第2版》
基础 迭代器 fuse Cow 在 Rust 中，Cow 是 &amp;ldquo;Clone on Write&amp;rdquo; 的缩写，它是一个智能指针类型，属于标准库的 std::borrow 模块。Cow 可以用来封装一个可能是借用（borrowed）也可能是拥有（owned）的值。Cow类型实际上是一个枚举类型，定义如下：
enum Cow&amp;lt;&amp;#39;a, B&amp;gt; where B: &amp;#39;a + ToOwned + ?Sized, { Borrowed(&amp;amp;&amp;#39;a B), Owned(&amp;lt;B as ToOwned&amp;gt;::Owned), } 其中 B 是被借用的类型，而 &amp;lt;B as ToOwned&amp;gt;::Owned 是该类型的拥有版本。一个具体类型必须实现 ToOwned trait，这样 Cow 才能根据需要clone被借用的数据产生一个拥有的副本。 实际用途： Cow 最大的优势在于它提供了一种方法来延迟昂贵的克隆操作，直到真正需要修改数据时才进行，这样可以提高性能。它经常被用于以下场景：
优化读多写少的情况：当数据通常只是被读取，但偶尔需要被修改时，Cow 可以避免不必要的克隆操作。 提供 API 的灵活性：某些函数可能需要对输入数据做出修改，但并不总是需要。这时，使用 Cow 作为参数类型允许调用者传递拥有的也可以是借用的值，增加了 API 的使用灵活性。 处理字符串数据：当处理字符串切片（&amp;amp;str）和字符串（String）时，Cow&amp;lt;str&amp;gt; 可以根据实际情况借用静态字符串或者拥有一个可变的字符串副本。 避免生命周期问题：当要返回一个引用但函数的实际行为可能需要返回一个拥有的值时，使用 Cow 可以更好地管理生命周期问题。 示例: 你可以在下面的示例中看到 Cow 的用法：
use std::borrow::Cow; fn greeting(name: &amp;amp;str) -&amp;gt; Cow&amp;lt;str&amp;gt; { if name.</description>
    </item>
    
    <item>
      <title>使用结构或可变参数选项简化go函数签名【译】</title>
      <link>https://czyt.tech/post/simplify-go-function-signatures-with-structs-or-variadic-options/</link>
      <pubDate>Wed, 14 Feb 2024 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/simplify-go-function-signatures-with-structs-or-variadic-options/</guid>
      <description>文章内容来自func25的 twitter
在Go中设计函数时，我们可能会遇到需要传递大量参数的情况。
这可能会影响函数的目的，并使维护代码成为一件苦差事，特别是当涉及相同类型的参数时。 为了保持整洁，请考虑两种策略：
选项结构。 可变选项。 选项结构体 将参数捆绑到一个结构中，这不仅增强了可读性，还简化了参数传递。
什么时候使用它？ 你的函数有一个很长的参数列表。 您的目标是自记录代码，因为结构字段本质上描述了它们的用途（通过名称）。 您希望轻松设置默认值或灵活修改选项。 使用此模式时， context.Context 应保留为单独的参数，而不应包含在选项结构中。
这是由于上下文在控制请求范围值、截止日期和取消信号方面的独特作用。 但在使用时有一些小技巧：
该结构应该向后兼容，以便在添加新字段时，我们不会破坏之前的任何内容。 我们始终可以在处理结构之前对其进行验证。 考虑隐藏您的选项结构（使其不导出），然后公开 NewXXX() 函数并在那里设置默认值。 可变参数选项 此方法利用 Go 的函数功能，允许您以更简洁的方式传递灵活数量的选项。
它在以下情况下是理想的：
该功能需要高度可配置。
大多数选项是可选的或很少使用。
您更喜欢简洁的调用站点。
设置默认值比使用可选结构更容易，您不需要隐藏它，只需将默认值直接放在 ConnectToDatabase 中即可。</description>
    </item>
    
    <item>
      <title>在 Rust 中使用 Axum【译】</title>
      <link>https://czyt.tech/post/using-axum-in-rust/</link>
      <pubDate>Tue, 30 Jan 2024 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/using-axum-in-rust/</guid>
      <description>本文原文地址为 https://www.shuttle.rs/blog/2023/12/06/using-axum-rust
Rust Web 生态系统中有如此多的后端 Web 框架，很难知道该选择什么。尽管在更早的过去，您可能会看到 Rocket 在受欢迎程度方面跃居排行榜首位，但现在通常是 Axum 和 actix-web 展开激烈的竞争，Axum 慢慢地登上了榜首。在本文中，我们将深入研究 Axum，这是一个由 Tokio 团队支持的用于制作 Rust REST API 的 Web 框架，它易于使用，并且与 Tower 具有超兼容性，Tower 是一个强大的可重用、模块化组件库，用于构建网络应用程序。
在本文中，我们将全面了解如何使用 Axum 编写 Web 服务。这也将包括 0.7 的更改。
Axum的路由 Axum 遵循 REST 风格的 API（例如 Express）的风格，您可以在其中创建处理函数并将它们附加到 axum 的 axum::Router 类型。路线的示例可能如下所示：
async fn hello_world() -&amp;gt; &amp;amp;&amp;#39;static str { &amp;#34;Hello world!&amp;#34; } 然后我们可以将它添加到我们的路由器中，如下所示：
use axum::{Router, routing::get}; fn init_router() -&amp;gt; Router { Router::new() .route(&amp;#34;/&amp;#34;, get(hello_world)) } 为了使处理函数有效，它需要是 axum::response::Response 类型或实现 axum::response::IntoResponse 。这已经针对大多数原始类型和 Axum 自己的所有类型实现了 - 例如，如果我们想要将一些 JSON 数据发送回用户，我们可以使用 Axum 的 JSON 类型作为返回类型来轻松实现这一点， axum::Json 类型包装了我们想要发回的任何内容。正如您在上面看到的，我们还可以单独返回一个字符串（切片）。</description>
    </item>
    
    <item>
      <title>Rust宏示例和实践【译】</title>
      <link>https://czyt.tech/post/rust-macros-example-and-practice/</link>
      <pubDate>Sun, 28 Jan 2024 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/rust-macros-example-and-practice/</guid>
      <description>原文链接为 https://earthly.dev/blog/rust-macros/ ，文章大部分使用机器翻译，小部分进行了文字调整。
本文深入探讨 Rust 宏的强大功能和多功能性。 Earthly 保证构建过程与您创建的宏一样强大。了解更多关于地球的信息。
在 Rust 中，宏是使用通常称为元编程的技术生成其他 Rust 代码的代码片段。宏在编译期间被扩展，并且宏的输出被插入到程序的源代码中。
最著名的宏示例是 println! 。尽管它看起来像函数并且使用起来也像函数，但它实际上在编译过程中进行了扩展，并且 println! 调用被替换为更复杂的实现代码。
在本文中，您将看到一些宏的实际示例，并了解一些有关如何最好地使用它们的提示和技巧。
Rust 宏基础知识 本教程假设您熟悉 Rust 编程的基础知识。
在 Rust 中，有两种类型的宏：声明性宏和过程性宏。逐一查看：
声明性宏 声明性宏是最简单的宏类型，由 macro-rules! 宏定义。它们的外观和行为与 match 表达式类似。
match 表达式将表达式作为输入，并将其与一组预定义模式进行匹配并运行相应的代码。类似地，声明性宏将一段 Rust 源代码作为输入，将源代码与一组预定义的结构进行匹配，并且在成功匹配时，将代码替换为与匹配模式关联的代码。
以下示例显示了正在运行的声明性宏：
declarative_macro.rs//declarative_macro.rs macro_rules! greetings { ($x: expr) =&amp;gt; { println!(&amp;#34;Hello, {}&amp;#34;, $x); }; } fn main() { greetings!(&amp;#34;Earthly&amp;#34;); // Prints &amp;#34;Hello, Earthly&amp;#34; } 这里，宏被命名为 greetings 并用 macro_rules! 定义。在宏主体中，只有一种模式： ($x: expr) =&amp;gt; { .</description>
    </item>
    
    <item>
      <title>在 Rust 中使用 Serde【译】</title>
      <link>https://czyt.tech/post/using-serde-in-rust/</link>
      <pubDate>Thu, 25 Jan 2024 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/using-serde-in-rust/</guid>
      <description>本文原文链接为 https://www.shuttle.rs/blog/2024/01/23/using-serde-rust 。大部分使用机器翻译，个人对机器翻译内容进行了部分润色,对于部分内容进行了增补。
在本文中，我们将讨论 Serde、如何在 Rust 应用程序中使用它以及一些更高级的提示和技巧。
什么是serde？ serde Rust create用于高效地序列化和反序列化多种格式的数据。它通过提供两个可以使用的trait来实现这一点，恰当地命名为 Deserialize 和 Serialize 。作为生态系统中最著名的 crate 之一，它目前支持 20 多种类型的序列化（反序列化）。
首先，您需要将 crate 安装到您的 Rust 应用程序中：
cargo add serde 使用serde 反序列化和序列化数据 序列化和反序列化数据的简单方法是添加 serde derive 功能。这会添加一个宏，您可以使用它来自动实现 Deserialize 和 Serialize - 您可以使用 --features 标志（ -F 来实现）短的）：
cargo add serde -F derive 然后我们可以将宏添加到我们想要实现 Deserialize 或 Serialize 的任何struct体或enum(枚举)中：
use serde::{Deserialize, Serialize}; #[derive(Deserialize, Serialize)] struct MyStruct { message: String, // ... the rest of your fields } 这允许我们使用任何支持 serde 的包在所述格式之间进行转换。作为示例，让我们使用 serde-json 与 JSON 格式相互转换：</description>
    </item>
    
    <item>
      <title>转换数字到Excel列字母实现</title>
      <link>https://czyt.tech/post/convert-number-to-excel-title-letter/</link>
      <pubDate>Thu, 25 Jan 2024 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/convert-number-to-excel-title-letter/</guid>
      <description>根据微软官方文档，excel最大支持1,048,576 行， 16,384 列。下面的代码并未处理这一限制。
Rust 实现代码：
fn convert_to_title(mut n: i32) -&amp;gt; String { let mut result = String::new(); while n != 0 { n -= 1; let letter = (n % 26) as u8 + b&amp;#39;A&amp;#39;; result.insert(0, letter as char); n /= 26; } result } #[test] fn test_convert_to_title() { let aa = convert_to_title(27); assert_eq!(aa, &amp;#34;AC&amp;#34;); } Go 实现代码：
func convertToTitle(n int) string { result := &amp;#34;&amp;#34; for n &amp;gt; 0 { n-- letter := n%26 result = string(&amp;#39;A&amp;#39;+letter) + result n /= 26 } return result } C# 实现代码：</description>
    </item>
    
    <item>
      <title>关于七牛qetag算法的一些记录</title>
      <link>https://czyt.tech/post/some-notes-about-qiniu-qetag-algorithm/</link>
      <pubDate>Mon, 22 Jan 2024 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/some-notes-about-qiniu-qetag-algorithm/</guid>
      <description>背景 今天做七牛相关接口开发的时候发现七牛的文件查询列表返回，有个hash字段，但是不知道是怎么进行计算的。后来查询到七牛的官方仓库 qetag.官方对这个算法的描述是这样的：
qetag 是一个计算文件在七牛云存储上的 hash 值（也是文件下载时的 etag 值）的实用程序。
七牛的 hash/etag 算法是公开的。算法大体如下：
如果你能够确认文件 &amp;lt;= 4M，那么 hash = UrlsafeBase64([0x16, sha1(FileContent)])。也就是，文件的内容的sha1值（20个字节），前面加一个byte（值为0x16），构成 21 字节的二进制数据，然后对这 21 字节的数据做 urlsafe 的 base64 编码。 如果文件 &amp;gt; 4M，则 hash = UrlsafeBase64([0x96, sha1([sha1(Block1), sha1(Block2), &amp;hellip;])])，其中 Block 是把文件内容切分为 4M 为单位的一个个块，也就是 BlockI = FileContent[I*4M:(I+1)*4M]。 为何需要公开 hash/etag 算法？这个和 “消重” 问题有关，详细见：
https://developer.qiniu.com/kodo/kb/1365/how-to-avoid-the-users-to-upload-files-with-the-same-key http://segmentfault.com/q/1010000000315810 为何在 sha1 值前面加一个byte的标记位(0x16或0x96）？
0x16 = 22，而 2^22 = 4M。所以前面的 0x16 其实是文件按 4M 分块的意思。 0x96 = 0x80 | 0x16。其中的 0x80 表示这个文件是大文件（有多个分块），hash 值也经过了2重的 sha1 计算。 语言封装 C# 实现 基于官方仓库的csharp代码做了部分修改</description>
    </item>
    
    <item>
      <title>Golang 高级时间工具函数</title>
      <link>https://czyt.tech/post/golang-date-time-utilities/</link>
      <pubDate>Thu, 18 Jan 2024 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/golang-date-time-utilities/</guid>
      <description>本文为 https://medium.com/canopas/golang-date-time-utilities-part-2-b1192eb04842 文章的翻译。正文部分进行了部分调整。
背景介绍 在编程世界中，处理日期和时间是一项常见的任务，通常需要精确性和灵活性。
虽然 Go 编程语言的标准库提供了 time 软件包来处理与时间相关的操作，但在某些情况下，开发人员需要额外的实用程序来简化与时间相关的任务。
在本篇博文中，我们将探讨一组实用工具函数，它们是 time 程序包的封装，可为操作提供便利。如果您不了解 time程序包，请考虑在深入学习高级实用程序之前参考一下相关文档。
有关基本功能，请参阅您始终需要的时间实用功能。
🎯 那么，让我们深入探讨一下如何实现。
实现 1.获取月初 一个月的开始是许多日期相关计算的基本参考点。让我们创建一个函数，将日期作为输入，并根据系统时区返回相应月份的第一天：
func StartOfMonth(date time.Time) time.Time { return time.Date(date.Year(), date.Month(), 1, 0, 0, 0, 0, date.Location()) } // function called StartOfMonth(time.Now()) // output 2024-01-01 00:00:00 +0530 IST 此函数将月日设置为 1，其他部分保持不变。
2.获取月末数据 相反，获取月末也同样重要。下面的函数返回给定月份最后一天的最后一秒：
func EndOfMonth(date time.Time) time.Time { firstDayOfNextMonth := StartOfMonth(date).AddDate(0, 1, 0) return firstDayOfNextMonth.Add(-time.Second) } // function called EndOfMonth(time.Now()) // output 2024-01-31 23:59:59 +0530 IST 该函数利用之前定义的 StartOfMonth 函数查找下个月的第一天，然后减去一秒，得到当前月份的月底。</description>
    </item>
    
    <item>
      <title>如何获取一个Github或者gitlab用户的公钥</title>
      <link>https://czyt.tech/post/how-to-get-a-github-or-gitlab-users-public-keys/</link>
      <pubDate>Wed, 17 Jan 2024 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/how-to-get-a-github-or-gitlab-users-public-keys/</guid>
      <description>背景 今天无意在t上看到，然后找到这个帖子 https://stackoverflow.com/questions/16158158/what-is-the-public-url-for-the-github-public-keys
How TO 获取 GitHub 可以通过下面链接
https://github.com/USER.keys https://github.com/USER.gpg 当然也可以通过github的api方式来获取
curl -i https://api.github.com/users/&amp;lt;username&amp;gt;/keys GitLab可以使用下面链接
https://gitlab.com/USER.keys https://gitlab.com/USER.gpg 使用 以github为例
curl https://github.com/&amp;lt;username&amp;gt;.keys | tee -a ~/.ssh/authorized_keys 添加完毕以后，对方就可以用ssh直接连接到你的电脑了。
这个帖子还举了bitbucket的例子
curl -i https://bitbucket.org/api/1.0/users/&amp;lt;accountname&amp;gt;/ssh-keys 延伸阅读 史上最全 SSH 暗黑技巧详解 </description>
    </item>
    
    <item>
      <title>Google Service Weaver中文文档[机翻]</title>
      <link>https://czyt.tech/post/google-service-weaver-docs-cn/</link>
      <pubDate>Fri, 12 Jan 2024 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/google-service-weaver-docs-cn/</guid>
      <description>本文为 Service Weaver 文档的机器翻译+细节微调。
Service Weaver是什么 ？ Service Weaver 是一个用于编写、部署和管理分布式应用程序的编程框架。您可以在计算机上本地运行、测试和调试 Service Weaver 应用程序，然后使用单个命令将该应用程序部署到云。
$ go run . # Run locally. $ weaver ssh deploy weaver.toml # Run on multiple machines. $ weaver gke deploy weaver.toml # Run on Google Cloud. $ weaver kube deploy weaver.toml # Run on Kubernetes. Service Weaver 应用程序由许多组件组成。组件被表示为常规的 Go 接口，组件之间通过调用这些接口定义的方法进行交互。这使得编写 Service Weaver 应用程序变得容易。您不必编写任何网络或序列化代码；你只要写 Go 就可以了。 Service Weaver 还提供用于日志日志、指标、跟踪、路由、测试等的库。
您可以像运行单个命令一样轻松地部署 Service Weaver 应用程序。在幕后，Service Weaver 将沿着组件边界Profile您的二进制文件，从而允许不同的组件在不同的计算机上运行。 Service Weaver 将为您复制、自动缩放和共同定位这些分布式组件。它还将代表您管理所有网络详细信息，确保不同的组件可以相互通信，并且客户端可以与您的应用程序通信。</description>
    </item>
    
    <item>
      <title>一些使用go-fyne的笔记</title>
      <link>https://czyt.tech/post/some-notes-about-using-go-fyne/</link>
      <pubDate>Thu, 11 Jan 2024 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/some-notes-about-using-go-fyne/</guid>
      <description>界面交互 中文字体设置 查阅相关资料，有下面几种解决方案，下面来依次说明。
环境变量 可以通过指定 FYNE_FONT 环境变量来使用替代字体
使用字体bundle 安装fyne工具，使用下面的命令：
go install fyne.io/fyne/v2/cmd/fyne@latest 准备好要使用的字体，我们这里使用miSans，使用下面命令
fyne bundle MiSans-Normal.ttf &amp;gt; bundle.go 然后创建一个theme
package tinytheme import ( &amp;#34;fyne.io/fyne/v2&amp;#34; &amp;#34;fyne.io/fyne/v2/theme&amp;#34; &amp;#34;fyneHello/fontRes&amp;#34; &amp;#34;image/color&amp;#34; ) type ChineseTheme struct{} var _ fyne.Theme = (*ChineseTheme)(nil) func (m *ChineseTheme) Font(s fyne.TextStyle) fyne.Resource { return fontRes.ResourceMiSansTTF } func (*ChineseTheme) Color(n fyne.ThemeColorName, v fyne.ThemeVariant) color.Color { return theme.DefaultTheme().Color(n, v) } func (*ChineseTheme) Icon(n fyne.ThemeIconName) fyne.Resource { return theme.DefaultTheme().Icon(n) } func (*ChineseTheme) Size(n fyne.</description>
    </item>
    
    <item>
      <title>使用go来编写graphql服务</title>
      <link>https://czyt.tech/post/go-graphql-go/</link>
      <pubDate>Fri, 29 Dec 2023 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/go-graphql-go/</guid>
      <description>本文为 文章 Go GraphQL Go!!! A beginner&amp;rsquo;s guide to GraphQL in Go using Ent. 的翻译。大部分使用机翻，部分内容作了相应调整。原文地址为 https://psj.codes/go-graphql-go
您是否想知道计算机和应用程序如何相互通信以获取信息？嗯，他们使用一种称为 API 的东西，它代表应用程序编程接口。 API 充当桥梁，允许不同的软件系统相互通信并交换数据。
在互联网的早期，构建 API 具有挑战性。开发人员必须以一种对每个使用它们的人都有意义的方式进行设计。这就像试图从调酒师那里点一杯饮料，而调酒师的菜单很复杂，有太多的选择。您通常会得到比您需要的更多或不够的信息，例如订购一杯简单的橙汁并收到整个水果篮！这给开发人员带来了挫败感并浪费了时间，他们必须筛选不必要的数据或发出多个请求才能获得他们想要的东西。想象一下，您必须向调酒师要一杯饮料，但您收到的不是简单的订单，而是完整的饮料目录！更糟糕的是，传统 API（称为 REST API）依赖大量端点。这些端点充当访问数据不同部分的特定路径。这就像一个迷宫，里面有无数扇门需要穿过。但随后，改变游戏规则的事情发生了。 Facebook 在 2012 年推出了 GraphQL，这是一种构建 API 的革命性方法，彻底扭转了局面。借助 GraphQL，开发人员终于告别了数据过度获取和数据获取不足的麻烦。快进到 2015 年，Facebook 开源了 GraphQL，并于 2018 年将 GraphQL 捐赠给了 Linux 基金会。
GraphQL 是一种 API 查询语言，或者有人可能会说它是开发 API 的新标准。
在本博客中，我们将探讨 GraphQL 如何应对传统 REST API 面临的挑战。我们还将踏上在 Go 中构建 GraphQL 服务器的实践之旅，为了使我们的开发过程更加令人兴奋和高效，我们将利用 Ent 的强大功能，这是一个专为 Go 设计的令人惊叹的实体库。
GraphQL 救世主 在简介中，我们提到了 RESTful API 的问题。让我们尝试理解它们并研究 GraphQL 如何解决它们。</description>
    </item>
    
    <item>
      <title>golang并发二三事</title>
      <link>https://czyt.tech/post/the-few-things-i-known-about-go-concurrency-/</link>
      <pubDate>Mon, 18 Dec 2023 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/the-few-things-i-known-about-go-concurrency-/</guid>
      <description>本文主要是鸟窝《深入理解go并发编程》中的读书速记以及一些并发库的使用例子集合
常用的并发库使用 sourcegraph conc waitgroup 创建一组协程并等待完成：
标准库
func main() { var wg sync.WaitGroup for i := 0; i &amp;lt; 10; i++ { wg.Add(1) go func() { defer wg.Done() // crashes on panic! doSomething() }() } wg.Wait() } conc
func main() { var wg conc.WaitGroup for i := 0; i &amp;lt; 10; i++ { wg.Go(doSomething) } wg.Wait() } 下面是一个官网博客的例子：
写一个函数，给定用户的名字，通过网络获取姓氏
func fetchLastName(ctx context.Context, firstName string) (string, error) { req, err := http.</description>
    </item>
    
    <item>
      <title>使用melody来创建正则表达式</title>
      <link>https://czyt.tech/post/use-melody-for-create-regexp/</link>
      <pubDate>Fri, 15 Dec 2023 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/use-melody-for-create-regexp/</guid>
      <description>melody是一款rust编写的编译输出为正则表达式的语言。Arch用户可以使用 paru -Syu melody 来安装，vscode和jetbrains系的IDE也有插件。
语法 下面是基于官方book的机翻语法。
量词 ... of - 用于表达特定数量的模式。相当于正则表达式 {5} （假设 5 of ... ） ... to ... of - 用于表示模式范围内的数量。相当于正则表达式 {5,9} （假设 5 to 9 of ... ） over ... of - 用于表达多个模式。相当于正则表达式 {6,} （假设 over 5 of ... ） some of - 用于表达 1 个或多个模式。相当于正则表达式 + any of - 用于表达 0 个或多个模式。相当于正则表达式 * option of - 用于表示模式的 0 或 1。相当于正则表达式 ? 所有量词前面都可以添加 lazy 以匹配最少数量的字符而不是最多的字符（贪婪）。相当于正则表达式 +? 、 *?</description>
    </item>
    
    <item>
      <title>使用uber cff进行并发编程</title>
      <link>https://czyt.tech/post/use-uber-cff-for-concurrency-programming/</link>
      <pubDate>Thu, 14 Dec 2023 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/use-uber-cff-for-concurrency-programming/</guid>
      <description>第一个项目 配置相关工具 先决条件
Go 1.18 或更新版本 带有 go.mod 文件的项目 大多数go项目应采取以下步骤建立 cff。
如果项目目录中还没有 &amp;ldquo;tools.go&amp;rdquo;，请在其中创建一个。您将在此指定开发时的依赖关系。
cat &amp;gt; tools.go &amp;lt;&amp;lt;EOF //go:build tools package tools // use your project&amp;#39;s package name here EOF 确保使用与项目目录相同的软件包名称。
将 import _ &amp;quot;go.uber.org/cff/cmd/cff&amp;quot; 添加到 tools.go 中。
echo &amp;#39;import _ &amp;#34;go.uber.org/cff/cmd/cff&amp;#34;&amp;#39; &amp;gt;&amp;gt; tools.go 运行 go mod tidy 获取最新版本的 cff，或运行 go get go.uber.org/cff@main 获取当前未发布的分支。
go mod tidy 将 cff CLI 安装到项目的 bin/ 子目录下。
GOBIN=$(pwd)/bin go install go.uber.org/cff/cmd/cff 请随意 gitignore 此目录。
echo &amp;#39;/bin&amp;#39; &amp;gt;&amp;gt; .</description>
    </item>
    
    <item>
      <title>使用uber-go的fx进行依赖注入</title>
      <link>https://czyt.tech/post/using-uber-go-fx-for-go-dependency-injection/</link>
      <pubDate>Wed, 13 Dec 2023 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/using-uber-go-fx-for-go-dependency-injection/</guid>
      <description>入门 下面是一个官方的例子：
package main import ( &amp;#34;context&amp;#34; &amp;#34;fmt&amp;#34; &amp;#34;go.uber.org/fx&amp;#34; &amp;#34;io&amp;#34; &amp;#34;net&amp;#34; &amp;#34;net/http&amp;#34; &amp;#34;os&amp;#34; ) func main() { fx.New( fx.Provide( NewHTTPServer, NewEchoHandler, NewServeMux, ), fx.Invoke(func(srv *http.Server) {}), ).Run() } func NewHTTPServer(lc fx.Lifecycle, mux *http.ServeMux) *http.Server { srv := &amp;amp;http.Server{ Addr: &amp;#34;:8080&amp;#34;, Handler: mux, } lc.Append(fx.Hook{ OnStart: func(ctx context.Context) error { ln, err := net.Listen(&amp;#34;tcp&amp;#34;, srv.Addr) if err != nil { return err } fmt.Println(&amp;#34;Starting HTTP server at&amp;#34;, srv.Addr) go srv.Serve(ln) return nil }, OnStop: func(ctx context.</description>
    </item>
    
    <item>
      <title>为Mongodb安装Percona Monitoring and Management</title>
      <link>https://czyt.tech/post/setup-percona-monitoring-and-management-for-mongodb/</link>
      <pubDate>Sat, 18 Nov 2023 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/setup-percona-monitoring-and-management-for-mongodb/</guid>
      <description>Percona Monitoring and Management (PMM) 是一种开源数据库可观察性、监控和管理工具，可与 MySQL、PostgreSQL、MongoDB 及其运行的服务器一起使用。它使您能够在一个位置查看所有数据库的节点到单个查询的性能指标。通过查询分析，您可以快速找到成本高昂且运行缓慢的查询以解决瓶颈。此外，Percona Advisors 为您提供性能、安全性和配置建议，帮助您保持数据库保持最佳性能。备份、恢复和内置开源私有 DBaaS 等警报和管理功能旨在提高 IT 团队的工作速度。
软件安装 安装环境为Ubuntu 22.04，下面的步骤参考了Percona官网的安装文档
安装服务端 本安装需要Docker环境，如果当前机器没有安装Docker，脚本会自动进行安装
使用下面命令安装
curl -fsSL https://www.percona.com/get/pmm | /bin/bash 或者
curl -fsSL https://www.percona.com/get/pmm | /bin/bash 安装完毕以后，请稍等片刻会显示server的访问信息
Gathering/downloading required components, this may take a moment Checking docker installation - installed. Starting PMM server... Created PMM Data Volume: pmm-data Created PMM Server: pmm-server Use the following command if you ever need to update your container by hand: docker run -d -p 443:443 --volumes-from pmm-data --name pmm-server --restart always percona/pmm-server:2 PMM Server has been successfully setup on this system!</description>
    </item>
    
    <item>
      <title>系统设计101</title>
      <link>https://czyt.tech/post/system-desigin-101-cn/</link>
      <pubDate>Tue, 24 Oct 2023 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/system-desigin-101-cn/</guid>
      <description>本文使用AI自动翻译，原文仓库地址
用直观和简单的术语解释复杂的系统。
无论您是在准备系统设计面试，还是只是想了解系统在表面之下是如何工作的，我们都希望本资料库能帮助您实现这一目标。
通信协议 架构风格定义了应用程序编程接口（API）不同组件之间的交互方式。因此，它们通过提供设计和构建 API 的标准方法，确保了效率、可靠性以及与其他系统集成的便捷性。以下是最常用的样式：
SOAP： 成熟、全面、基于 XML
最适合企业应用
RESTful： 流行、易于实施的 HTTP 方法
网络服务的理想选择
GraphQL： 查询语言，请求特定数据
减少网络开销，加快响应速度
gRPC： 现代化、高性能的协议缓冲器
适合微服务架构
WebSocket： 实时、双向、持久连接
非常适合低延迟数据交换
Webhook 事件驱动、HTTP 回调、异步
事件发生时通知系统
REST API 与 GraphQL 在应用程序接口设计方面，REST 和 GraphQL 各有优缺点。
下图显示了 REST 和 GraphQL 的快速比较。
REST
使用 GET、POST、PUT、DELETE 等标准 HTTP 方法进行 CRUD 操作。 当你需要在不同的服务/应用程序之间建立简单、统一的接口时，它就能很好地发挥作用。 缓存策略可以直接实施。 缺点是可能需要多次往返，从不同的端点收集相关数据。 GraphQL
为客户提供单个端点，以便准确查询所需数据。 客户端在嵌套查询中指定所需的确切字段，服务器只返回包含这些字段的优化有效载荷。 支持用于修改数据的突变和用于实时通知的订阅。 非常适合聚合多个来源的数据，并能很好地满足快速发展的前端需求。 不过，它将复杂性转移到了客户端，如果没有适当的保护措施，可能会允许滥用查询 缓存策略可能比 REST 更加复杂。 REST 和 GraphQL 之间的最佳选择取决于应用程序和开发团队的具体要求。GraphQL 非常适合复杂或频繁变化的前端需求，而 REST 则适合需要简单一致的合同的应用。</description>
    </item>
    
    <item>
      <title>12 个改变我生产力的个人go技巧【译】</title>
      <link>https://czyt.tech/post/12-personal-go-tricks-that-transformed-my-productivity-mne/</link>
      <pubDate>Thu, 05 Oct 2023 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/12-personal-go-tricks-that-transformed-my-productivity-mne/</guid>
      <description>原文链接https://dev.to/func25/12-personal-go-tricks-that-transformed-my-productivity-mne
作者 我通常在 Devtrovert 分享有关系统设计和 Go 的见解。请随时查看我的 LinkedIn Phuong Le 以获取最新帖子。
在从事生产项目时，我注意到我经常重复代码并利用某些技术，直到后来回顾我的工作时才意识到这一点。
为了解决这个问题，我开发了一个解决方案，事实证明它对我很有帮助，而且我认为它对其他人也可能有用。
下面是从我的实用程序库中随机挑选的一些有用且通用的代码片段，没有任何特定的分类或特定于系统的技巧。
1.跟踪使用时间的技巧 如果您有兴趣跟踪 Go 中函数的执行时间，您可以使用一个简单而有效的技巧，只需使用“defer”关键字的一行代码即可。您所需要的只是一个 TrackTime 函数：
// Utility func TrackTime(pre time.Time) time.Duration { elapsed := time.Since(pre) fmt.Println(&amp;#34;elapsed:&amp;#34;, elapsed) return elapsed } func TestTrackTime(t *testing.T) { defer TrackTime(time.Now()) // &amp;lt;--- THIS time.Sleep(500 * time.Millisecond) } // elapsed: 501.11125ms 1.5.两阶段延迟 Go 延迟的强大之处不仅在于任务完成后的清理工作，还在于任务完成后的清理工作。这也是为了做好准备，请考虑以下事项：
func setupTeardown() func() { fmt.Println(&amp;#34;Run initialization&amp;#34;) return func() { fmt.Println(&amp;#34;Run cleanup&amp;#34;) } } func main() { defer setupTeardown()() // &amp;lt;-------- fmt.</description>
    </item>
    
    <item>
      <title>go泛型备忘录【译】</title>
      <link>https://czyt.tech/post/go-generics-cheatsheet/</link>
      <pubDate>Mon, 25 Sep 2023 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/go-generics-cheatsheet/</guid>
      <description>原文 https://gosamples.dev/generics-cheatsheet/
入门 泛型发布 Go 中的泛型自 2022 年 3 月 15 日发布的 1.18 版本起可用。
泛型函数 使用泛型，您可以创建以类型作为参数的函数。而不是为每种类型编写单独的函数，例如：
func LastInt(s []int) int { return s[len(s)-1] } func LastString(s []string) string { return s[len(s)-1] } // etc. 您可以编写带有类型参数的函数：
func Last[T any](s []T) T { return s[len(s)-1] } 类型参数在方括号中声明。它们描述了给定函数允许的类型：
泛型函数调用 您可以像调用任何其他函数一样调用通用函数：
func main() { data := []int{1, 2, 3} fmt.Println(Last(data)) data2 := []string{&amp;#34;a&amp;#34;, &amp;#34;b&amp;#34;, &amp;#34;c&amp;#34;} fmt.Println(Last(data2)) } 您不必像下面的示例那样显式声明类型参数，因为它是根据传递的参数推断的。此功能称为类型推断，仅适用于函数。
func main() { data := []int{1, 2, 3} fmt.</description>
    </item>
    
    <item>
      <title>学习zig【译】</title>
      <link>https://czyt.tech/post/openmymind-learn-zig/</link>
      <pubDate>Sat, 23 Sep 2023 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/openmymind-learn-zig/</guid>
      <description>原文链接 https://www.openmymind.net/learning_zig/ 采用Google翻译机翻整理
安装 Zig Zig 的下载页面包括适用于常见平台的预编译二进制文件。在此页面上，您将找到最新开发版本以及主要版本的二进制文件。本指南跟踪的最新版本可以在页面顶部找到。
对于我的计算机，我将下载 zig-macos-aarch64-0.12.0-dev.161+6a5463951.tar.xz。您可能使用的是不同的平台或更新的版本。展开存档后，您应该有一个 zig 二进制文件（除了其他内容之外），您需要为其添加别名或添加到您的路径中；无论你习惯什么流程。
您现在应该能够运行 zig zen 和 zig version 来测试您的设置。
语言概述 - 第 1 部分 Zig 是一种强类型编译语言。它支持泛型，具有强大的编译时元编程功能，并且不包含垃圾收集器。许多人认为 Zig 是 C 的现代替代品。因此，该语言的语法与 C 类似。我们正在讨论以分号结尾的语句和大括号分隔的块。
Zig 代码如下所示：
const std = @import(&amp;#34;std&amp;#34;); // This code won&amp;#39;t compile if `main` isn&amp;#39;t `pub` (public) pub fn main() void { const user = User{ .power = 9001, .name = &amp;#34;Goku&amp;#34;, }; std.debug.print(&amp;#34;{s}&amp;#39;s power is {d}\n&amp;#34;, .{user.name, user.power}); } pub const User = struct { power: u64, name: []const u8, }; 如果将上述内容保存为learning.</description>
    </item>
    
    <item>
      <title>Go 中的 Redis 缓存：初学者指南【译】</title>
      <link>https://czyt.tech/post/redis-caching-golang/</link>
      <pubDate>Fri, 22 Sep 2023 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/redis-caching-golang/</guid>
      <description>原文链接：https://betterstack.com/community/guides/scaling-go/redis-caching-golang/ 使用Google机翻
Redis 是一种通用的内存数据存储，通常用于缓存、会话管理、发布/订阅等。它的灵活性和广泛的用例使其成为个人和商业项目的热门选择。
本文将提供关于使用 Redis 作为 Go 程序缓存的可访问介绍，探索其最流行的应用程序。您将学习如何在 Go 应用程序中连接到 Redis 服务器并执行基本的数据库操作，利用其功能来提高性能并减少数据库负载。
让我们开始吧！
先决条件 要按照本文进行操作，请确保您的计算机上安装了最新版本的 Go。如果您缺少 Go，可以在此处找到安装说明。
步骤 1 — 安装和配置 Redis 请按照此处的说明为您的操作系统安装最新的 Redis 稳定版本（撰写本文时为 v7.x）。
redis-server --version 输出
Redis server v=7.0.12 sha=00000000:0 malloc=jemalloc-5.2.1 bits=64 build=d706905cc5f560c1 安装后，通过执行以下命令确认 Redis 正在运行：
sudo systemctl status redis 输出
● redis-server.service - Advanced key-value store Loaded: loaded (/lib/systemd/system/redis-server.service; enabled; vendor preset: enabled) Active: active (running) since Wed 2023-08-09 08:23:32 UTC; 5min ago Docs: http://redis.</description>
    </item>
    
    <item>
      <title>一些windows定制的相关资源</title>
      <link>https://czyt.tech/post/some-resources-for-windows-customization/</link>
      <pubDate>Wed, 20 Sep 2023 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/some-resources-for-windows-customization/</guid>
      <description>脚本 移除Edge @echo off reg delete &amp;#34;HKLM\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\Microsoft Edge&amp;#34; /v &amp;#34;NoRemove&amp;#34; /f &amp;gt;NUL 2&amp;gt;nul reg delete &amp;#34;HKLM\SOFTWARE\WOW6432Node\Microsoft\EdgeUpdate\ClientState\{56EB18F8-B008-4CBD-B6D2-8C97FE7E9062}&amp;#34; /v &amp;#34;experiment_control_labels&amp;#34; /f &amp;gt;NUL 2&amp;gt;nul reg add &amp;#34;HKLM\SOFTWARE\WOW6432Node\Microsoft\EdgeUpdateDev&amp;#34; /v &amp;#34;AllowUninstall&amp;#34; /t REG_DWORD /d 1 /f &amp;gt;NUL 2&amp;gt;nul for /D %%I in (&amp;#34;%ProgramFiles(x86)%\Microsoft\Edge\Application\*&amp;#34;) do ( if exist &amp;#34;%%I\Installer\setup.exe&amp;#34; ( echo Uninstalling Edge Chromium pushd &amp;#34;%%I\Installer&amp;#34; setup.exe --uninstall --msedge --force-uninstall --system-level --delete-profile popd ) ) msiexec /X{2BFF39DC-EFF0-355C-80CD-41D847013784} /qn /norestart set &amp;#34;value=MicrosoftEdgeAutoLaunch_.*&amp;#34; set &amp;#34;path=HKCU\Software\Microsoft\Windows\CurrentVersion\Run&amp;#34; for /f &amp;#34;tokens=1,*&amp;#34; %%A in (&amp;#39;reg query &amp;#34;%path%&amp;#34; /f &amp;#34;Microsoft&amp;#34; ^| findstr /R &amp;#34;%value%&amp;#34;&amp;#39;) do ( reg delete &amp;#34;%path%&amp;#34; /v &amp;#34;%%A&amp;#34; /f ) del /q /f &amp;#34;%userprofile%\Desktop\Microsoft Edge.</description>
    </item>
    
    <item>
      <title>Golang编译进阶【译】</title>
      <link>https://czyt.tech/post/go-build-in-advance/</link>
      <pubDate>Thu, 31 Aug 2023 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/go-build-in-advance/</guid>
      <description>本文翻译自 https://dev.to/jacktt/go-build-in-advance-4o8n
I/构建选项 以下是 go build 命令最常用的一些选项：
-o ：指定输出文件名。默认输出文件名是主包的名称，Windows 上添加 .exe 后缀。 -v ：详细输出。此选项在编译包时打印包的名称。 -work ：打印临时工作目录的名称，退出时不删除。该选项对于调试很有用。 -x ：打印命令。此选项打印 go build 命令正在执行的命令。 -asmflags ：传递给 go tool asm 调用的参数。 -buildmode ：要使用的构建模式。默认构建模式是 exe 。其他可能的值有 shared 、 pie 和 plugin 。 -buildvcs ：是否使用版本控制信息标记二进制文件。默认值为 auto 。 有关 go build 命令的更多信息，您可以运行以下命令：
go help build II/ 将包含哪些文件 当您在 Go 中使用 go build 命令时，它会编译当前目录及其子目录中的 Go 源文件以创建可执行二进制文件。默认情况下，Go 只编译 .go 文件，忽略目录中的其他类型的文件。然而，值得注意的是 go build 命令的行为可能会受到构建标签、构建约束的影响。
go build 通常会忽略以下类型的文件：
1. 具有非 .</description>
    </item>
    
    <item>
      <title>如何使用C#检查网络连接</title>
      <link>https://czyt.tech/post/how-to-check-network-status-in-csharp/</link>
      <pubDate>Thu, 31 Aug 2023 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/how-to-check-network-status-in-csharp/</guid>
      <description>调用Windows API 在C#中可以通过Pinvoke调用windows API方式来进行网络连接的检查：
[DllImport(&amp;#34;wininet.dll&amp;#34;, SetLastError=true)] extern static bool InternetGetConnectedState(out int lpdwFlags, int dwReserved); [Flags] enum ConnectionStates { Modem = 0x1, LAN = 0x2, Proxy = 0x4, RasInstalled = 0x10, Offline = 0x20, Configured = 0x40, } MSDN地址 https://learn.microsoft.com/en-us/windows/win32/api/wininet/nf-wininet-internetgetconnectedstate 对应的返回值Description如下：
Value Meaning INTERNET_CONNECTION_CONFIGURED0x40 Local system has a valid connection to the Internet, but it might or might not be currently connected. INTERNET_CONNECTION_LAN0x02 Local system uses a local area network to connect to the Internet.</description>
    </item>
    
    <item>
      <title>使用go发送邮件的注意事项</title>
      <link>https://czyt.tech/post/some-tips-about-using-send-mail-in-go/</link>
      <pubDate>Fri, 25 Aug 2023 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/some-tips-about-using-send-mail-in-go/</guid>
      <description>服务器设置 SPF设置 如果你使用的是企业邮箱，可能需要添加SPF记录。SPF（Sender Policy Framework） 是电子邮件系统中发送方策略框架的缩写，它的内容写在DNS的txt类型的记录里面；作用是防止别人伪造你的邮件地址进行发信，是一种非常高效的反垃圾邮件解决方案。如果你的服务器没有设置邮件的SPF，那么在发送邮件到Gmail等邮箱地址时，会发生退信。
一般给域名添加SPF记录的方式是添加一条TXT记录。以腾讯企业邮箱为例，添加的TXT记录值是v=spf1 include:spf.mail.qq.com -all
使用go可以实现查询域名的TXT信息。
func TestNetLookupTxt(t *testing.T) { txt, err := net.LookupTXT(&amp;#34;czyt.tech&amp;#34;) if err != nil { t.Fatal(err) } t.Log(txt) } DKIM 腾讯企业邮箱 DKIM配置说明
DMARC DMARC（Domain-based Message Authentication, Reporting &amp;amp; Conformance）是一种基于现有的SPF和DKIM协议的可扩展电子邮件认证协议，邮件收发双方建立了邮件反馈机制，便于邮件发送方和邮件接收方共同对域名的管理进行完善和监督。对于未通过前述检查的邮件，接收方则按照发送方指定的策略进行处理，如直接投入垃圾箱或拒收。从而有效识别并拦截欺诈邮件和钓鱼邮件，保障用户个人信息安全。这里同样以腾讯企业邮箱为例。在DNS管理的地方添加以下DMARC记录：
主机记录： _dmarc
记录类型：TXT
记录值: v=DMARC1; p=none; rua=mailto:mailauth-reports@qq.com
注意：DMARC记录里，有一个值可由你来自定义： p：用于告知收件方，当检测到某封邮件存在伪造发件人的情况，收件方要做出什么处理；
p=none; 为收件方不作任何处理
p=quarantine; 为收件方将邮件标记为垃圾邮件
p=reject; 为收件方拒绝该邮件
rua：用于在收件方检测后，将一段时间的汇总报告，发送到哪个邮箱地址。
ruf：用于当检测到伪造邮件时，收件方须将该伪造信息的报告发送到哪个邮箱地址。ruf=mailto:xxx@xxxxxx.com;
DMARC是基于DKIM和SPF的，所以开启DMARC必须先开启DKIM或SPF任意一种
消息体 Message-Id 对于Gmail等邮箱，如果你在发送邮箱的时候没有带上Message-Id也会触发退信。这时需要你在邮件发送的Header中添加Message-Id.例如&amp;lt;4867a3d78a50438bad95c0f6d072fca5@mailbox01.contoso.com&amp;gt;。可以参考微软的相关文档
邮件模板 对于常见的邮件模板，可以使用Hermes这个Golang库。下面是一个例子：
package main import ( &amp;#34;github.com/matcornic/hermes/v2&amp;#34; ) type inviteCode struct { } func (w *inviteCode) Name() string { return &amp;#34;invite_code&amp;#34; } func (w *inviteCode) Email() hermes.</description>
    </item>
    
    <item>
      <title>使用Hashcorp的cleanhttp</title>
      <link>https://czyt.tech/post/the-usage-of-hashcorp-go-cleanhttp/</link>
      <pubDate>Wed, 23 Aug 2023 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/the-usage-of-hashcorp-go-cleanhttp/</guid>
      <description>缘起 早上在某地方看到这样一张图
大意是说任何第三方库都可以拦截您的所有 HTTP 调用，然后推荐了一个库 cleanhttp
官网的介绍：
Functions for accessing &amp;ldquo;clean&amp;rdquo; Go http.Client values 用于访问“干净”Go http.Client 值的函数
The Go standard library contains a default http.Client called http.DefaultClient. It is a common idiom in Go code to start with http.DefaultClient and tweak it as necessary, and in fact, this is encouraged; from the http package documentation: Go 标准库包含一个名为 http.DefaultClient 的默认 http.Client 。在 Go 代码中，以 http.DefaultClient 开头并根据需要进行调整是一种常见的习惯用法，事实上，这是值得鼓励的；来自 http 包文档：
The Client&amp;rsquo;s Transport typically has internal state (cached TCP connections), so Clients should be reused instead of created as needed.</description>
    </item>
    
    <item>
      <title>Rxgo使用备忘录</title>
      <link>https://czyt.tech/post/rxgo-usage-memo/</link>
      <pubDate>Sun, 20 Aug 2023 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/rxgo-usage-memo/</guid>
      <description>官网文档 &amp;ndash;机器翻译内容&amp;ndash;
介绍 ReactiveX，简称 Rx，是一个用于使用 Observable 流进行编程的 API。
RxGo 实现基于管道的概念。管道是由通道连接的一系列阶段，其中每个阶段是一组运行相同功能的 goroutine。
让我们看一个具体的例子，每个框都是一个运算符：
我们使用 Just 运算符基于固定的项目列表创建一个静态 Observable。 我们使用 Map 运算符定义一个转换函数（将圆形转换为方形）。 我们使用 Filter 运算符过滤每个黄色方块。 在此示例中，最终物品在通道中发送，可供消费者使用。使用 RxGo 消费或生成数据的方法有很多种。在频道中发布结果只是其中之一。
每个算子都是一个转换阶段。默认情况下，一切都是顺序的。然而，我们可以通过定义同一运算符的多个实例来利用现代 CPU 架构。每个运算符实例都是连接到公共通道的 goroutine。
RxGo 的理念是实现 ReactiveX 概念并利用主要的 Go 原语（通道、goroutines 等），以便两个世界之间的集成尽可能顺利。
安装 RxGo v2 go get -u github.com/reactivex/rxgo/v2 入门 你好世界 让我们创建第一个 Observable 并使用一个项目：
observable := rxgo.Just(&amp;#34;Hello, World!&amp;#34;)() ch := observable.Observe() item := &amp;lt;-ch fmt.Println(item.V) Just 运算符从静态项目列表创建一个 Observable。 Of(value) 根据给定值创建一个项目。如果我们想从错误中创建一个项目，我们必须使用 Error(err) 。这与 v1 不同，v1 直接接受值或错误而无需包装它。这一改变的理由是什么？它是为了（希望）Go 2 中的泛型功能为 RxGo 做好准备。</description>
    </item>
    
    <item>
      <title>在GO中使用日志库slog</title>
      <link>https://czyt.tech/post/logging-in-go-using-slog/</link>
      <pubDate>Wed, 09 Aug 2023 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/logging-in-go-using-slog/</guid>
      <description>本文根据三篇文章机翻拼凑而来。其中两篇文章发布时，slog还未进入标准库。golang 1.21.0 于2023-08-09发布，slog也包含在正式库中，本文根据原文内容进行了部分的修订和补充。
什么是slog？ slog 是 Go 团队的一个实验性日志记录包，提供结构化日志记录的功能。
本文向您概述了此包中的日志记录功能。
安装 ＃ 创建一个新的 go 项目并引入 log/slog
使用记录器# 立即导入并开始使用记录器。
package main import ( &amp;#34;log/slog&amp;#34; ) func main() { slog.Info(&amp;#34;Go is best language!&amp;#34;) } 输出：
$ go run main.go 2022/12/15 01:31:23 INFO Go is best language! 默认情况下，输出包括时间、日志级别和消息。
以下日志级别可用。
Debug Info Warn Error 结构化日志# slog 是一个结构化记录器，支持两种格式的日志记录：文本和 json。
让我们看一下文本记录器。
文本处理程序# 您首先创建一个文本处理程序和一个新的记录器。
package main import ( &amp;#34;os&amp;#34; &amp;#34;log/slog&amp;#34; ) func main() { textHandler := slog.NewTextHandler(os.Stdout,nil) logger := slog.</description>
    </item>
    
    <item>
      <title>HashiCorp go-plugin包使用指南</title>
      <link>https://czyt.tech/post/hashcorp-go-plugin-package-usage-memo/</link>
      <pubDate>Fri, 04 Aug 2023 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/hashcorp-go-plugin-package-usage-memo/</guid>
      <description>1. 介绍 HashiCorp的go-plugin包是一个强大的Go语言插件系统,它通过RPC实现主程序和插件之间的通信。这个系统被广泛应用于HashiCorp的多个项目中,如Terraform、Nomad、Vault、Boundary和Waypoint等。本文将循序渐进地介绍go-plugin的使用方法,并提供简单易复现的例子。
2. 基本概念 go-plugin的工作原理是启动子进程并通过RPC进行通信。它支持标准的net/rpc和gRPC两种通信方式。主要特点包括:
插件是Go接口的实现 支持跨语言插件 支持复杂参数和返回值 支持双向通信 内置日志功能 协议版本控制 支持stdout/stderr同步 TTY保留 插件运行时主机升级 加密安全的插件 3. 单向通信示例 让我们从一个简单的单向通信示例开始,实现一个基本的问候插件。
3.1 定义接口 首先,我们需要定义插件将要实现的接口:
// shared/interface.go package shared import &amp;#34;context&amp;#34; type Greeter interface { Greet(ctx context.Context, name string) (string, error) } 3.2 实现插件 接下来,我们实现这个接口作为一个插件:
// plugin/main.go package main import ( &amp;#34;context&amp;#34; &amp;#34;fmt&amp;#34; &amp;#34;github.com/hashicorp/go-plugin&amp;#34; &amp;#34;path/to/your/shared&amp;#34; ) type GreeterPlugin struct{} func (g *GreeterPlugin) Greet(ctx context.Context, name string) (string, error) { return fmt.Sprintf(&amp;#34;Hello, %s!&amp;#34;, name), nil } var handshakeConfig = plugin.</description>
    </item>
    
    <item>
      <title>如何为七牛已绑定域名的bucket获取Let&#39;s Encrypt证书</title>
      <link>https://czyt.tech/post/how-to-get-free-lets-encrypt-ssl-for-qiniu-bucket-domain/</link>
      <pubDate>Wed, 02 Aug 2023 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/how-to-get-free-lets-encrypt-ssl-for-qiniu-bucket-domain/</guid>
      <description>关于Let&amp;rsquo;s Encrypt证书 官网的说明是
一个为 2.25 亿个网站提供 TLS 证书的非盈利性证书颁发机构。
官网 ： https://letsencrypt.org/zh-cn/
获取证书的验证方式 目前有很多自动工具可以获取，需要有相关的域名或者服务器权限。认证的方式有三种，这里引用下官网的说明。验证方式
当您从 Let’s Encrypt 获得证书时，我们的服务器会验证您是否使用 ACME 标准定义的验证方式来验证您对证书中域名的控制权。 大多数情况下，验证由 ACME 客户端自动处理，但如果您需要做出一些更复杂的配置决策，那么了解更多有关它们的信息会很有用。 如果您不确定怎么做，请使用您的客户端的默认设置或使用 HTTP-01。
HTTP-01 验证 这是当今最常见的验证方式。 Let’s Encrypt 向您的 ACME 客户端提供一个令牌，然后您的 ACME 客户端将在您对 Web 服务器的 http://&amp;lt;你的域名&amp;gt;/.well-known/acme-challenge/（用提供的令牌替换 ）路径上放置指定文件。 该文件包含令牌以及帐户密钥的指纹。 一旦您的 ACME 客户端告诉 Let’s Encrypt 文件已准备就绪，Let’s Encrypt 会尝试获取它（可能从多个地点进行多次尝试）。 如果我们的验证机制在您的 Web 服务器上找到了放置于正确地点的正确文件，则该验证被视为成功，您可以继续申请颁发证书。 如果验证检查失败，您将不得不再次使用新证书重新申请。 我们的 HTTP-01 验证最多接受 10 次重定向。 我们只接受目标为“http:”或“https:”且端口为 80 或 443 的重定向。 我们不目标为 IP 地址的重定向。 当被重定向到 HTTPS 链接时，我们不会验证证书是否有效（因为验证的目的是申请有效证书，所以它可能会遇到自签名或过期的证书）。
HTTP-01 验证只能使用 80 端口。 因为允许客户端指定任意端口会降低安全性，所以 ACME 标准已禁止此行为。</description>
    </item>
    
    <item>
      <title>Avalonia使用备忘</title>
      <link>https://czyt.tech/post/avalonia-usage-memo/</link>
      <pubDate>Mon, 31 Jul 2023 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/avalonia-usage-memo/</guid>
      <description>安装 模板 可以安装一些Avalonia的dotnet模板
dotnet new install Templates.Prism.Avalonia dotnet new install Avalonia.Templates IDE插件 Rider里面安装插件 AvaloniaRider
VisualStudio安装插件 Avalonia for Visual Studio
Avalonia 中的一些特性 Binding $parent 您可以使用$parent符号绑定到目标在逻辑上的父级：
&amp;lt;Button DockPanel.Dock=&amp;#34;Bottom&amp;#34; HorizontalAlignment=&amp;#34;Stretch&amp;#34; HorizontalContentAlignment=&amp;#34;Center&amp;#34; x:CompileBindings=&amp;#34;False&amp;#34; Command=&amp;#34;{Binding $parent[Window].DataContext.AddItem}&amp;#34;&amp;gt;Add Item &amp;lt;/Button&amp;gt; &amp;lt;Border Tag=&amp;#34;Hello World!&amp;#34;&amp;gt; &amp;lt;TextBlock Text=&amp;#34;{Binding $parent.Tag}&amp;#34;/&amp;gt; &amp;lt;/Border&amp;gt; 也可以通过在$parent符号添加索引器绑定到父控件的父控件：
&amp;lt;Border Tag=&amp;#34;Hello World!&amp;#34;&amp;gt; &amp;lt;Border&amp;gt; &amp;lt;TextBlock Text=&amp;#34;{Binding $parent[1].Tag}&amp;#34;/&amp;gt; &amp;lt;/Border&amp;gt; &amp;lt;/Border&amp;gt; 索引器从0开始，因此$parent[0]等同于$parent。 还可以按类型绑定到祖先：
&amp;lt;Border Tag=&amp;#34;Hello World!&amp;#34;&amp;gt; &amp;lt;Decorator&amp;gt; &amp;lt;TextBlock Text=&amp;#34;{Binding $parent[Border].Tag}&amp;#34;/&amp;gt; &amp;lt;/Decorator&amp;gt; &amp;lt;/Border&amp;gt; 最后，您可以组合索引器和类型：
&amp;lt;Border Tag=&amp;#34;Hello World!&amp;#34;&amp;gt; &amp;lt;Border&amp;gt; &amp;lt;Decorator&amp;gt; &amp;lt;TextBlock Text=&amp;#34;{Binding $parent[Border;1].Tag}&amp;#34;/&amp;gt; &amp;lt;/Decorator&amp;gt; &amp;lt;/Border&amp;gt; &amp;lt;/Border&amp;gt; 如果需要在祖先类型中包含XAML命名空间，一般使用:字符：</description>
    </item>
    
    <item>
      <title>Buf使用备忘</title>
      <link>https://czyt.tech/post/buf-usage-memo/</link>
      <pubDate>Sat, 29 Jul 2023 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/buf-usage-memo/</guid>
      <description>Buf 工具针对于Schema驱动、基于 Protobuf 的 API 开发，为服务发布者和服务客户端提供可靠和更好的用户体验。简化了您的 Protobuf 管理策略，以便您可以专注于重要的事情。
下载安装 可以直接去buf的GitHub的release页面下载，其他的安装方式参考官方文档
使用 三个yaml文件 初次接触buf项目的时候，有个疑问就是buf项目中buf.yaml buf.gen.yaml buf.work.yaml这个三个文件的区别和用途。下面是简单的一个表，列出了三个文件的区别：
文件名 文件位置 说明 buf.yaml 每个proto模块定义的根目录 buf.yaml 配置的位置告诉 buf 在哪里搜索 .proto 文件，模块的依赖项以及如何处理导入 buf.gen.yaml 一般放在仓库的根目录 文件控制 buf generate 命令如何针对任何输入执行 protoc 插件 buf.work.yaml 一般放在仓库的根目录 定义项目需要哪些proto模块 示例目录结构：
. ├── buf.gen.yaml ├── buf.work.yaml ├── proto │ ├── acme │ │ └── weather │ │ └── v1 │ │ └── weather.proto │ └── buf.yaml └── vendor └── protoc-gen-validate ├── buf.yaml └── validate └── validate.</description>
    </item>
    
    <item>
      <title>浅析Jetbrains的产品版本和更新API设计</title>
      <link>https://czyt.tech/post/a-brief-analysis-of-jetbrains-version-and-update-api-desgin/</link>
      <pubDate>Fri, 28 Jul 2023 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/a-brief-analysis-of-jetbrains-version-and-update-api-desgin/</guid>
      <description>接口分析 单个产品信息接口 首先我们通过http抓包来看DataGrip这个产品查询接口，访问的接口地址为下面这个地址
https://data.services.jetbrains.com/products?code=DG&amp;amp;release.type=eap,rc,release&amp;amp;fields=distributions,link,name,releases&amp;amp;_=1690557030459
从接口上我们能看到有下面几个方面：
graphql风格接口设计。
支持产品代码、软件包通道、软件平台的筛选。主要有下面几个：
平台 说明 Windows linux windowsZip windows压缩包 windowsARM64 mac macM1 该接口返回信息如下：
{ &amp;#34;DG&amp;#34;: [ { &amp;#34;date&amp;#34;: &amp;#34;2023-07-20&amp;#34;, &amp;#34;type&amp;#34;: &amp;#34;release&amp;#34;, &amp;#34;downloads&amp;#34;: { &amp;#34;linuxARM64&amp;#34;: { &amp;#34;link&amp;#34;: &amp;#34;https://download.jetbrains.com/datagrip/datagrip-2023.2-aarch64.tar.gz&amp;#34;, &amp;#34;size&amp;#34;: 570768510, &amp;#34;checksumLink&amp;#34;: &amp;#34;https://download.jetbrains.com/datagrip/datagrip-2023.2-aarch64.tar.gz.sha256&amp;#34; }, &amp;#34;linux&amp;#34;: { &amp;#34;link&amp;#34;: &amp;#34;https://download.jetbrains.com/datagrip/datagrip-2023.2.tar.gz&amp;#34;, &amp;#34;size&amp;#34;: 569402212, &amp;#34;checksumLink&amp;#34;: &amp;#34;https://download.jetbrains.com/datagrip/datagrip-2023.2.tar.gz.sha256&amp;#34; }, &amp;#34;thirdPartyLibrariesJson&amp;#34;: { &amp;#34;link&amp;#34;: &amp;#34;https://resources.jetbrains.com/storage/third-party-libraries/datagrip/datagrip-2023.2-third-party-libraries.json&amp;#34;, &amp;#34;size&amp;#34;: 62706, &amp;#34;checksumLink&amp;#34;: &amp;#34;https://resources.jetbrains.com/storage/third-party-libraries/datagrip/datagrip-2023.2-third-party-libraries.json.sha256&amp;#34; }, &amp;#34;windows&amp;#34;: { &amp;#34;link&amp;#34;: &amp;#34;https://download.jetbrains.com/datagrip/datagrip-2023.2.exe&amp;#34;, &amp;#34;size&amp;#34;: 447884488, &amp;#34;checksumLink&amp;#34;: &amp;#34;https://download.jetbrains.com/datagrip/datagrip-2023.2.exe.sha256&amp;#34; }, &amp;#34;windowsZip&amp;#34;: { &amp;#34;link&amp;#34;: &amp;#34;https://download.jetbrains.com/datagrip/datagrip-2023.2.win.zip&amp;#34;, &amp;#34;size&amp;#34;: 566939835, &amp;#34;checksumLink&amp;#34;: &amp;#34;https://download.</description>
    </item>
    
    <item>
      <title>Golang高效解码xml文件</title>
      <link>https://czyt.tech/post/golang-effecttive-decode-xml/</link>
      <pubDate>Wed, 26 Jul 2023 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/golang-effecttive-decode-xml/</guid>
      <description>xml处理需要引用encoding/xml包.一般推荐使用 xml.Decoder 替代 xml.Unmarshal。 xml.Decoder 是一个流式 XML 解码器，它可以边读取边解码，而不需要将整个 XML 文档加载到内存中。相比之下，xm1.Unmarshal 会将整个 XML 文档加载到内存中然后再进行解码。因此，对于大型 XML 文件，使用xml.Decoder 可以节省内存并提高性能。
小的Xml文件 下面是一个例子
package main import ( &amp;#34;encoding/xml&amp;#34; &amp;#34;os&amp;#34; &amp;#34;testing&amp;#34; ) type UserData struct { Name string `xml:&amp;#34;name&amp;#34;` Age int32 `xml:&amp;#34;age&amp;#34;` } type Pocket struct { Data []UserData `xml:&amp;#34;users&amp;#34;` } func TestXmlDecode(t *testing.T) { file, err := os.Open(&amp;#34;testdata/userdata.xml&amp;#34;) if err != nil { t.Fatal(err) } var pocket Pocket if err := xml.NewDecoder(file).Decode(&amp;amp;pocket); err != nil { t.</description>
    </item>
    
    <item>
      <title>使用C#以编程方式切换Windows专注模式</title>
      <link>https://czyt.tech/post/using-csharp-to-toogle-windows-focus-assist-mode-programmatically/</link>
      <pubDate>Mon, 24 Jul 2023 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/using-csharp-to-toogle-windows-focus-assist-mode-programmatically/</guid>
      <description>缘起 最近需要以编程方式调用windows api实现windows10专注模式的切换，但是Google一圈，没有现成代码。找到的相关帖子要么是cpp的要么是rust的，而且是undocument的Windows api。
Csharp调用 以下是完整代码
public static class FocusAssistToogle { private const string NtdllDlDll = &amp;#34;ntdll.dll&amp;#34;; private const uint DataBufferSize = 4; private static readonly byte[] DisableDataBuf = { 0x00, 0x00, 0x00, 0x00 }; // 01仅优先通知 02 仅限闹钟 private static readonly byte[] EnableDataBuf = { 0x02, 0x00, 0x00, 0x00 }; [DllImport(NtdllDlDll, SetLastError = true)] private static extern int ZwUpdateWnfStateData( ref WnfSWnfStateName sWnfStateName, byte[] buffer, uint bufferSize, IntPtr previousStateData, IntPtr currentStateData, uint previousStateDataSize, uint currentStateDataSize); [StructLayout(LayoutKind.</description>
    </item>
    
    <item>
      <title>Zig相关资源</title>
      <link>https://czyt.tech/post/zig-language-related-resources/</link>
      <pubDate>Thu, 20 Jul 2023 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/zig-language-related-resources/</guid>
      <description>博客 https://www.openmymind.net https://matklad.github.io https://kristoff.it 教程 https://zigbyexample.github.io Zig Cookbook https://ikrima.dev/dev-notes/zig/zig-crash-course/ https://ikrima.dev/dev-notes/zig/zig-metaprogramming/ https://zig.guide https://course.ziglang.cc Introduction to Zig Zig Common Tasks zig资讯 zig news 软件包 https://zig.pm </description>
    </item>
    
    <item>
      <title>Zig语言快速参考</title>
      <link>https://czyt.tech/post/zig-language-quick-reference/</link>
      <pubDate>Wed, 19 Jul 2023 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/zig-language-quick-reference/</guid>
      <description>本文使用AI自动翻译，原文链接
第 0 章 - 入门 欢迎 Zig 是一种通用编程语言和工具链，用于维护健壮、最佳和可重用的软件。
警告：最新的主要版本是 0.10.1 - Zig 仍然是 1.0 之前的版本；仍然不建议在生产中使用，并且您可能会遇到编译器错误。
要遵循本指南，我们假设您已经：
先前的编程经验 对低级编程概念的一些理解 了解 C、C++、Rust、Go、Pascal 或类似语言将有助于遵循本指南。您应该有一个可用的编辑器、终端和互联网连接。本指南是非官方的，与 Zig Software Foundation 无关，旨在从一开始就按顺序阅读。
Installation 本指南假设您使用 Zig 的主版本而不是最新的主要版本，这意味着从网站下载二进制文件或从源代码编译；您的包管理器中的 Zig 版本可能已过时。本指南不支持 Zig 0.10.1。
从以下位置下载并提取 Zig 的预构建主二进制文件： https://ziglang.org/download/ 将 Zig 添加到您的路径
linux, macos, bsd
将 Zig 二进制文件的位置添加到 PATH 环境变量中。对于安装，请添加 export PATH=$PATH:~/zig 或类似于 /etc/profile（系统范围）或 $HOME/.profile。如果这些更改没有立即应用，请从 shell 运行该行。
windows
a) 系统范围（admin powershell）
[Environment]::SetEnvironmentVariable( &amp;#34;Path&amp;#34;, [Environment]::GetEnvironmentVariable(&amp;#34;Path&amp;#34;, &amp;#34;Machine&amp;#34;) + &amp;#34;;C:\your-path\zig-windows-x86_64-your-version&amp;#34;, &amp;#34;Machine&amp;#34; ) b) 用户级别（powershell）</description>
    </item>
    
    <item>
      <title>Golang 防火墙编程</title>
      <link>https://czyt.tech/post/programming-firewall-in-go/</link>
      <pubDate>Mon, 03 Jul 2023 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/programming-firewall-in-go/</guid>
      <description>非编程方式 Windows 使用netsh方式进行防火墙规则的维护
Linux 编程方式 Windows Tailscale开发了一个应用WFP的库inet.af/wf 。参考参考链接。在tailscale中的封装代码如下(源链接)：
// Copyright (c) Tailscale Inc &amp;amp; AUTHORS // SPDX-License-Identifier: BSD-3-Clause //go:build windows package wf import ( &amp;#34;fmt&amp;#34; &amp;#34;net/netip&amp;#34; &amp;#34;os&amp;#34; &amp;#34;golang.org/x/sys/windows&amp;#34; &amp;#34;inet.af/wf&amp;#34; &amp;#34;tailscale.com/net/netaddr&amp;#34; ) // Known addresses. var ( linkLocalRange = netip.MustParsePrefix(&amp;#34;ff80::/10&amp;#34;) linkLocalDHCPMulticast = netip.MustParseAddr(&amp;#34;ff02::1:2&amp;#34;) siteLocalDHCPMulticast = netip.MustParseAddr(&amp;#34;ff05::1:3&amp;#34;) linkLocalRouterMulticast = netip.MustParseAddr(&amp;#34;ff02::2&amp;#34;) ) type direction int const ( directionInbound direction = iota directionOutbound directionBoth ) type protocol int const ( protocolV4 protocol = iota protocolV6 protocolAll ) // getLayers returns the wf.</description>
    </item>
    
    <item>
      <title>Nginx使用备忘</title>
      <link>https://czyt.tech/post/nginx-usage-memo/</link>
      <pubDate>Wed, 21 Jun 2023 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/nginx-usage-memo/</guid>
      <description>安装和更新 安装 以ArchLinux为例
yay -S nginx
生成的systemctl单元如下
[Unit] Description=A high performance web server and a reverse proxy server After=network.target network-online.target nss-lookup.target [Service] Type=forking PIDFile=/run/nginx.pid PrivateDevices=yes SyslogLevel=err ExecStart=/usr/bin/nginx -g &amp;#39;pid /run/nginx.pid; error_log stderr;&amp;#39; ExecReload=/usr/bin/nginx -s reload KillMode=mixed [Install] WantedBy=multi-user.target 更新 查看现有Nginx的编译参数
➜ ~ nginx -V nginx version: nginx/1.22.1 built with OpenSSL 3.0.7 1 Nov 2022 (running with OpenSSL 3.0.8 7 Feb 2023) TLS SNI support enabled configure arguments: --prefix=/etc/nginx --conf-path=/etc/nginx/nginx.conf --sbin-path=/usr/bin/nginx --pid-path=/run/nginx.</description>
    </item>
    
    <item>
      <title>初学Flutter时我遇到的问题汇总</title>
      <link>https://czyt.tech/post/the-issues-i-came-with-flutter-when-i-am-a-newbie/</link>
      <pubDate>Thu, 25 May 2023 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/the-issues-i-came-with-flutter-when-i-am-a-newbie/</guid>
      <description>这些是我学习Flutter过程中遇到的问题列表
项目问题 Android Studio丢失Image Asset新建项 这样会在新的界面打开IDE，等同步完成，然后就有新建项了。
调试 Flutter编辑时，没有色板预览 需要设置Java运行环境，设置好以后，就可以用了。
Debug条件运行 需要引入flutter/foundation.dart然后，使用kDebugMode进行判断即可。
import &amp;#39;package:flutter/foundation.dart&amp;#39;; if (kDebugMode) { print(&amp;#34; changed $v&amp;#34;); } 隐藏Debug 条幅 在代码的theme入口代码添加debugShowCheckedModeBanner: false,,完整代码如下：
class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: &amp;#39;Flutter Demo&amp;#39;, theme: ThemeData( colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), useMaterial3: true, ), debugShowCheckedModeBanner: false, home: const MyHomePage(title: &amp;#39;Flutter Demo Home Page&amp;#39;), ); } } AndroidStudio可以显示设备但是Flutter的设备选择没有设备 先检查Android SDK
PS C:\Windows\system32&amp;gt; flutter doctor --android-licenses Flutter assets will be downloaded from https://storage.</description>
    </item>
    
    <item>
      <title>Dart语言参考</title>
      <link>https://czyt.tech/post/dart-lang-reference/</link>
      <pubDate>Sun, 21 May 2023 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/dart-lang-reference/</guid>
      <description>Dart语言学习入门过程中的一些记录，仅记录有差异的。可能会跟go等其他语言进行一个对比。
语言基础 运算符 截断除法运算符（truncating division operator） 比如计算 23➗ 7
使用 23/7 使用下面的代码
void main (){ print(23/7); } // 输出 3.2857142857142856 使用~/运算符
void main (){ print(23~/7); } // 输出 3 String 变量值内插 Dart使用下面的方式进行值的内插
void main() { var greeter = &amp;#34;Dart🐟&amp;#34;; print(&amp;#34;打印机:$greeter&amp;#34;); } 这一点跟C#有一点相似，C#使用下面的方式：
void main() { var greeter = &amp;#34;C#🐟&amp;#34;; print($&amp;#34;打印机:{greeter}&amp;#34;); } Dart中如果变量需要进行值计算，那么跟开始的例子相似。
void main() { var greeter = &amp;#34;Dart🐟&amp;#34;; print(&amp;#34;打印机:${greeter.length}&amp;#34;); } 函数 Dart函数不支持重载，但是提供了可选命名参数和可选参数等方式。
可选参数 String Fake(String UserName, [String? carIdentifier]) { if (carIdentifier !</description>
    </item>
    
    <item>
      <title>使用aws go-sdk访问cloudflare R2文件</title>
      <link>https://czyt.tech/post/using-aws-go-sdk-to-access-cloudflare-r2-files/</link>
      <pubDate>Sun, 21 May 2023 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/using-aws-go-sdk-to-access-cloudflare-r2-files/</guid>
      <description>准备 需要准备Cloudflare的accountId,相应的R2 ak sk 和bucketName等信息.
var ( accountId = &amp;#34;xxxxx&amp;#34; accessKeyId = &amp;#34;cbdade718b2ca877882csssssfcf&amp;#34; accessKeySecret = &amp;#34;04917c7d745422022e266f6b06&amp;#34; bucketName = &amp;#34;gopher&amp;#34; ) 完整代码 package main import ( &amp;#34;context&amp;#34; &amp;#34;fmt&amp;#34; &amp;#34;github.com/aws/aws-sdk-go-v2/aws&amp;#34; &amp;#34;github.com/aws/aws-sdk-go-v2/config&amp;#34; &amp;#34;github.com/aws/aws-sdk-go-v2/credentials&amp;#34; &amp;#34;github.com/aws/aws-sdk-go-v2/service/s3&amp;#34; &amp;#34;log&amp;#34; ) func main() { var ( accountId = &amp;#34;xxxxx&amp;#34; accessKeyId = &amp;#34;cbdade718b2ca877882csssssfcf&amp;#34; accessKeySecret = &amp;#34;04917c7d745422022e266f6b06&amp;#34; bucketName = &amp;#34;gopher&amp;#34; ) var r2Resolver = aws.EndpointResolverWithOptionsFunc(func(service, region string, options ...interface{}) (aws.Endpoint, error) { return aws.Endpoint{ URL: fmt.Sprintf(&amp;#34;https://%s.r2.cloudflarestorage.com&amp;#34;, accountId), }, nil }) cfg, err := config.</description>
    </item>
    
    <item>
      <title>使用C#连接wifi</title>
      <link>https://czyt.tech/post/use-csharp-to-connect-wifi/</link>
      <pubDate>Mon, 24 Apr 2023 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/use-csharp-to-connect-wifi/</guid>
      <description>需要安装库 Managed Native Wifi 获取Wifi列表 示例代码
private List&amp;lt;AvailableNetworkPack&amp;gt; GetAvaliableNetworks() { var networks = new List&amp;lt;AvailableNetworkPack&amp;gt;(); foreach (var network in NativeWifi.EnumerateAvailableNetworks()) { if (!networks.Contains(network)) { networks.Add(network); } } return networks; } 连接wifi 创建Profile 应该支持这些类型open, WEP and WPA-PSK的网络
private static string CreateSecurityWifiProfile(string ssid, string password) { string hex = CreateHexSSIDName(ssid); return string.Format(@&amp;#34;&amp;lt;?xml version=&amp;#34;&amp;#34;1.0&amp;#34;&amp;#34;?&amp;gt; &amp;lt;WLANProfile xmlns=&amp;#34;&amp;#34;http://www.microsoft.com/networking/WLAN/profile/v1&amp;#34;&amp;#34;&amp;gt; &amp;lt;name&amp;gt;{0}&amp;lt;/name&amp;gt; &amp;lt;SSIDConfig&amp;gt; &amp;lt;SSID&amp;gt; &amp;lt;hex&amp;gt;{2}&amp;lt;/hex&amp;gt; &amp;lt;name&amp;gt;{0}&amp;lt;/name&amp;gt; &amp;lt;/SSID&amp;gt; &amp;lt;/SSIDConfig&amp;gt; &amp;lt;connectionType&amp;gt;ESS&amp;lt;/connectionType&amp;gt; &amp;lt;connectionMode&amp;gt;auto&amp;lt;/connectionMode&amp;gt; &amp;lt;MSM&amp;gt; &amp;lt;security&amp;gt; &amp;lt;authEncryption&amp;gt; &amp;lt;authentication&amp;gt;WPA2PSK&amp;lt;/authentication&amp;gt; &amp;lt;encryption&amp;gt;AES&amp;lt;/encryption&amp;gt; &amp;lt;useOneX&amp;gt;false&amp;lt;/useOneX&amp;gt; &amp;lt;/authEncryption&amp;gt; &amp;lt;sharedKey&amp;gt; &amp;lt;keyType&amp;gt;passPhrase&amp;lt;/keyType&amp;gt; &amp;lt;protected&amp;gt;false&amp;lt;/protected&amp;gt; &amp;lt;keyMaterial&amp;gt;{1}&amp;lt;/keyMaterial&amp;gt; &amp;lt;/sharedKey&amp;gt; &amp;lt;/security&amp;gt; &amp;lt;/MSM&amp;gt; &amp;lt;MacRandomization xmlns=&amp;#34;&amp;#34;http://www.</description>
    </item>
    
    <item>
      <title>在树莓派3b上部署minio服务</title>
      <link>https://czyt.tech/post/deploy-minio-on-raspi-3b/</link>
      <pubDate>Wed, 12 Apr 2023 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/deploy-minio-on-raspi-3b/</guid>
      <description>安装 我的树莓派安装的是manjaro,直接执行如下命令即可
yay -S minio 官方的安装文档开源参考
https://min.io/docs/minio/linux/operations/install-deploy-manage/deploy-minio-single-node-single-drive.html
启用服务 systemctl enable minio
修改配置 主要修改mino的设置文件，文件位置为/etc/minio/minio.conf
# Local export path. MINIO_VOLUMES=&amp;#34;/srv/minio/data/&amp;#34; # Server user. MINIO_ROOT_USER=gopher # Server password. MINIO_ROOT_PASSWORD=gopher # Use if you want to run Minio on a custom port. MINIO_OPTS=&amp;#34;--console-address :8888&amp;#34; MINIO_SERVER_URL=&amp;#34;https://minio.xxx.org&amp;#34; MINIO_BROWSER_REDIRECT_URL=&amp;#34;https://minio-console.xxx.org&amp;#34; 修改 MINIO_OPTS 主要是为了自定义Console的端口,而这个参数主要是在service定义中使用，安装软件后自动使用的service(路径为/usr/lib/systemd/system/minio.service)定义如下
[Unit] Description=Minio Documentation=https://docs.minio.io Wants=network-online.target After=network-online.target AssertFileIsExecutable=/usr/bin/minio [Service] # Specifies the maximum file descriptor number that can be opened by this process LimitNOFILE=65536 Type=simple User=minio Group=minio EnvironmentFile=/etc/minio/minio.</description>
    </item>
    
    <item>
      <title>一些Rust的学习资料</title>
      <link>https://czyt.tech/post/rust-related-resources/</link>
      <pubDate>Tue, 28 Mar 2023 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/rust-related-resources/</guid>
      <description>在线教程 concurrency programming via rust https://blog.fudenglong.site/Programming-Rust/ jetbrains出品的rust教程 Rust Book experiment 微软出品：写给.net开发人员的Rust教程 Google Android团队写的Rust教程 通过例子学rust https://cheats.rs/ Rust语言圣经 Brown 大学版本rust程序设计实验版 learn how to write macros in Rust Operating System development tutorials in Rust on the Raspberry Pi Rust语言实战 inside rust std library A Plugin System in Rust https://learning-rust.github.io https://github.com/CleanCut/ultimate_rust_crash_course Writing a JVM in Rust Rust 宏小册 Writing an OS in Rust 清华大学程序设计训练（Rust） Rust 异步编程指南 rust ffi guide Rust基础教程 rCore-Tutorial-Book 第三版 OffensiveRust RustPrimer Rust Atomics and Locks中文版 Rust 程序设计语言 2021版 中文 The Rust on ESP Book中文版 rust 教程资料收集 - fkysly case studies Y分钟速成X=Rust Rust 101 https://teach-rs.</description>
    </item>
    
    <item>
      <title>我和AI讨论的一些C#话题</title>
      <link>https://czyt.tech/post/the-csharp-topics-i-talked-with-ai/</link>
      <pubDate>Fri, 24 Mar 2023 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/the-csharp-topics-i-talked-with-ai/</guid>
      <description>很久没有用C#，最近需要使用。下面是跟AI问的一些C#的问题，未作整理。
基础 Span类型 c# Span的应用场景及具体例子
Span是一种新的引用类型，它允许存储和操作连续的内存块。它特别适用于那些需要高效处理内存块的应用场景，例如字符串处理、IO操作和序列化/反序列化。
下面是一些具体的例子：
字符串处理：Span可以用于快速地操作字符串，例如从字符串中截取子串、替换子串、查找子串等。下面是一个例子： string str = &amp;#34;hello world&amp;#34;; Span&amp;lt;char&amp;gt; span = str.AsSpan(6, 5); // 从第6个字符开始，截取长度为5的子串 IO操作：Span可以用于将IO操作映射到内存中，以提高性能。下面是一个例子： using (FileStream stream = File.OpenRead(&amp;#34;file.txt&amp;#34;)) { byte[] buffer = new byte[1024 * 1024]; while (stream.Read(buffer) &amp;gt; 0) { Span&amp;lt;byte&amp;gt; span = buffer.AsSpan(); // 将字节数组映射为Span // 处理Span } } 序列化/反序列化：Span可以用于快速地序列化和反序列化数据，尤其是在网络传输等场景中。下面是一个例子： public static void Serialize&amp;lt;T&amp;gt;(T value, Span&amp;lt;byte&amp;gt; buffer) where T : struct { unsafe { fixed (byte* ptr = buffer) { *(T*)ptr = value; // 将值拷贝到Span中 } } } public static T Deserialize&amp;lt;T&amp;gt;(Span&amp;lt;byte&amp;gt; buffer) where T : struct { unsafe { fixed (byte* ptr = buffer) { return *(T*)ptr; // 从Span中读取值 } } } 异步 c# SynchronizationContext的使用场景及例子</description>
    </item>
    
    <item>
      <title>【译】如何使用 http.ResponseController 类型</title>
      <link>https://czyt.tech/post/how-to-use-the-http-responsecontroller-type/</link>
      <pubDate>Thu, 09 Mar 2023 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/how-to-use-the-http-responsecontroller-type/</guid>
      <description>本文原文地址 https://www.alexedwards.net/blog/how-to-use-the-http-responsecontroller-type，使用chatGPT翻译
One of my favorite things about the recent Go 1.20 release is the new http.ResponseController type, which brings with it three nice benefits: 关于最近的 Go 1.20 版本，我最喜欢的事情之一是新的 http.ResponseController 类型，它带来了三个好处：
You can now override your server-wide read and write deadlines on a per request basis. 您现在可以根据每个请求覆盖服务器范围内的读取和写入截止日期。 The pattern for using the http.Flusher and http.Hijacker interfaces is clearer and feels less hacky. No more type assertions necessary! 使用 http.Flusher 和 http.</description>
    </item>
    
    <item>
      <title>golang CGO参考</title>
      <link>https://czyt.tech/post/golang-cgo-reference/</link>
      <pubDate>Fri, 03 Feb 2023 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/golang-cgo-reference/</guid>
      <description>开源项目 https://github.com/dolthub/go-library-sample https://github.com/draffensperger/go-interlang https://github.com/kbehouse/go_call_cxx_so https://github.com/tailscale/libtailscale https://github.com/iikira/golang-msvc https://github.com/vladimirvivien/go-cshared-examples https://github.com/tailscale/libtailscale/tree/main 文档 Embedding Go in C Calling C code from go C? Go? Cgo! CGO编程（Go语言高级编程） https://stackoverflow.com/questions/14581063/golang-cgo-converting-union-field-to-go-type https://sunzenshen.github.io/tutorials/2015/05/09/cgotchas-intro.html https://totallygamerjet.hashnode.dev/the-smallest-go-binary-5kb 代码片段 Convert &amp;lsquo;C&amp;rsquo; array to golang slice
func carray2slice(array *C.int, len int) []C.int { var list []C.int sliceHeader := (*reflect.SliceHeader)((unsafe.Pointer(&amp;amp;list))) sliceHeader.Cap = len sliceHeader.Len = len sliceHeader.Data = uintptr(unsafe.Pointer(array)) return list } </description>
    </item>
    
    <item>
      <title>命令行的艺术</title>
      <link>https://czyt.tech/post/the-art-of-commandline/</link>
      <pubDate>Thu, 02 Feb 2023 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/the-art-of-commandline/</guid>
      <description>本文摘自项目 https://github.com/jlevy/the-art-of-command-line
命令行的艺术 熟练使用命令行是一种常常被忽视，或被认为难以掌握的技能，但实际上，它会提高你作为工程师的灵活性以及生产力。本文是一份我在 Linux 上工作时，发现的一些命令行使用技巧的摘要。有些技巧非常基础，而另一些则相当复杂，甚至晦涩难懂。这篇文章并不长，但当你能够熟练掌握这里列出的所有技巧时，你就学会了很多关于命令行的东西了。
这篇文章是许多作者和译者共同的成果。 这里的部分内容 首次 出现 于 Quora， 但已经迁移到了 GitHub，并由众多高手做出了许多改进。 如果你在本文中发现了错误或者存在可以改善的地方，请贡献你的一份力量。
前言 涵盖范围：
这篇文章不仅能帮助刚接触命令行的新手，而且对具有经验的人也大有裨益。本文致力于做到覆盖面广（涉及所有重要的内容），具体（给出具体的最常用的例子），以及简洁（避免冗余的内容，或是可以在其他地方轻松查到的细枝末节）。在特定应用场景下，本文的内容属于基本功或者能帮助您节约大量的时间。 本文主要为 Linux 所写，但在仅限 OS X 系统章节和仅限 Windows 系统章节中也包含有对应操作系统的内容。除去这两个章节外，其它的内容大部分均可在其他类 Unix 系统或 OS X，甚至 Cygwin 中得到应用。 本文主要关注于交互式 Bash，但也有很多技巧可以应用于其他 shell 和 Bash 脚本当中。 除去“标准的”Unix 命令，本文还包括了一些依赖于特定软件包的命令（前提是它们具有足够的价值）。 注意事项：
为了能在一页内展示尽量多的东西，一些具体的信息可以在引用的页面中找到。我们相信机智的你知道如何使用 Google 或者其他搜索引擎来查阅到更多的详细信息。文中部分命令需要您使用 apt-get，yum，dnf，pacman， pip 或 brew（以及其它合适的包管理器）来安装依赖的程序。 遇到问题的话，请尝试使用 Explainshell 去获取相关命令、参数、管道等内容的解释。 基础 学习 Bash 的基础知识。具体地，在命令行中输入 man bash 并至少全文浏览一遍; 它理解起来很简单并且不冗长。其他的 shell 可能很好用，但 Bash 的功能已经足够强大并且到几乎总是可用的（ 如果你只学习 zsh，fish 或其他的 shell 的话，在你自己的设备上会显得很方便，但过度依赖这些功能会给您带来不便，例如当你需要在服务器上工作时）。
熟悉至少一个基于文本的编辑器。通常而言 Vim （vi） 会是你最好的选择，毕竟在终端中编辑文本时 Vim 是最好用的工具（甚至大部分情况下 Vim 要比 Emacs、大型 IDE 或是炫酷的编辑器更好用）。</description>
    </item>
    
    <item>
      <title>Golang Web框架Buffalo 简单使用</title>
      <link>https://czyt.tech/post/golang-web-framework-buffalo-basic-usage/</link>
      <pubDate>Sun, 29 Jan 2023 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/golang-web-framework-buffalo-basic-usage/</guid>
      <description>官方文档 https://gobuffalo.io
安装 安装要求
Before installing make sure you have the required dependencies installed:
A working Go environment Go version v1.16.0. Frontend Requirements# The following requirements are optional. You don’t need them if you want to build an API or if you prefer to build your app in an old-fashioned way.
node version 8 or greater either yarn or npm for the asset pipeline built upon webpack. Database Specific Requirements# Again, if you don’t need a database, you won’t need these.</description>
    </item>
    
    <item>
      <title>从Golang的开源项目中学习不同的功能实现</title>
      <link>https://czyt.tech/post/learn-how-to-implement-features-from-go-open-source-project/</link>
      <pubDate>Fri, 25 Nov 2022 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/learn-how-to-implement-features-from-go-open-source-project/</guid>
      <description>缘起 最近看到有些go开源项目中的代码，看到其中的功能，故整理备用。
密码 阈值解密（Threshold Decryption） 来源 取自公众号文章
package main import ( &amp;#34;crypto/rand&amp;#34; &amp;#34;fmt&amp;#34; &amp;#34;github.com/hashicorp/vault/shamir&amp;#34; ) func main() { // 1. 生成一个随机密钥（如AES-256密钥） secretKey := make([]byte, 32) _, err := rand.Read(secretKey) if err != nil { panic(err) } fmt.Printf(&amp;#34;原始密钥: %x\n&amp;#34;, secretKey) // 2. 分片为3份，至少需要2份恢复（阈值k=2，总分片n=3） shards, err := shamir.Split(secretKey, 3, 2) if err != nil { panic(err) } // 3. 模拟分片存储（实际中分发给不同机构） shard1, shard2, shard3 := shards[0], shards[1], shards[2] fmt.Printf(&amp;#34;分片1: %x\n分片2: %x\n分片3: %x\n&amp;#34;, shard1, shard2, shard3) // 4.</description>
    </item>
    
    <item>
      <title>C#扫码枪输入Hook</title>
      <link>https://czyt.tech/post/scanner-input-hook-via-csharp/</link>
      <pubDate>Tue, 01 Nov 2022 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/scanner-input-hook-via-csharp/</guid>
      <description>摘自网络，测试可用
public class ScanerHook { public delegate void ScanerDelegate(ScanerCodes codes); public event ScanerDelegate ScanerEvent; //private const int WM_KEYDOWN = 0x100;//KEYDOWN //private const int WM_KEYUP = 0x101;//KEYUP //private const int WM_SYSKEYDOWN = 0x104;//SYSKEYDOWN //private const int WM_SYSKEYUP = 0x105;//SYSKEYUP //private static int HookProc(int nCode, Int32 wParam, IntPtr lParam); private int hKeyboardHook = 0;//声明键盘钩子处理的初始值 private ScanerCodes codes = new ScanerCodes();//13为键盘钩子 //定义成静态，这样不会抛出回收异常 private static HookProc hookproc; delegate int HookProc(int nCode, Int32 wParam, IntPtr lParam); [DllImport(&amp;#34;user32.</description>
    </item>
    
    <item>
      <title>使用protoc-gen-star编写protoc插件</title>
      <link>https://czyt.tech/post/writing-a-protoc-plugin-using-protoc-gen-star/</link>
      <pubDate>Sat, 29 Oct 2022 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/writing-a-protoc-plugin-using-protoc-gen-star/</guid>
      <description>预备知识 需要安装的软件 protoc golang go 软件包 github.com/lyft/protoc-gen-star 插件调用步骤 protoc，PB编译器，使用一组标志（记录在protoc -h下）进行配置，并将一组文件作为参数交给它。在这种情况下，I标志可以被多次指定，是它在proto文件中用于导入依赖关系的查找路径。默认情况下，官方描述符protos已经被包含在内。
myplugin_out 告诉 protoc 使用 protoc-gen-myplugin protoc-plugin。这些插件会从系统的 PATH 环境变量中自动解析，或者可以用另一个标志明确指定。官方的protoc-plugins (例如，protoc-gen-python) 已经在protoc注册了。该标志的值是特定于特定插件的，但 :&amp;hellip;/generated 后缀除外。这个后缀表示protoc将把该包生成的文件放在哪个根目录下（相对于当前工作目录）。然而，这个生成的输出目录不会传播给 protoc-gen-myplugin，所以它需要在标志的左边重复。PG* 通过一个 output_path 参数支持这一点。
protoc 解析传入的 proto 文件，确保它们在语法上是正确的，并加载任何导入的依赖项。它将这些文件和依赖关系转换成描述符 (它们本身就是 PB 消息)，并创建一个 CodeGeneratorRequest (又是一个 PB)。protoc 将这个请求序列化，然后执行每个配置的 protoc-plugin，通过 stdin 发送有效载荷。
protoc-gen-myplugin 启动，接收请求的有效载荷，并将其解密。一个基于 PG* 的 protoc-plugin 有两个阶段。首先，PG* 对从 protoc 收到的 CodeGeneratorRequest 进行解密，并为每个文件和其包含的所有实体创建一个完全连接的抽象语法树 (AST)。为这个插件指定的任何参数也会被解析，以便以后使用。
当这一步完成后，PG*就会执行任何注册的模块，把构建的AST交给它。模块可以被写成生成人工制品（例如，文件），或者只是对所提供的图进行某种形式的验证而没有任何其他副作用。模块在针对PB的操作方面提供了极大的灵活性。
一旦所有的模块都被运行，PG*会将任何自定义的工件写入文件系统，或者将生成器特定的工件序列化为CodeGeneratorResponse并将数据发送到其stdout。这整个流程看起来像这样。
foo.proto → protoc → CodeGeneratorRequest → protoc-gen-myplugin → CodeGeneratorResponse → protoc → foo.pb.go 假设插件名称为diy,则需要编译程序为protoc-gen-diy，并将程序加入系统Path变量，通过下面的命令调用插件。
protoc -I .</description>
    </item>
    
    <item>
      <title>C# dllimport 备忘录</title>
      <link>https://czyt.tech/post/csharp-dll-import-memo/</link>
      <pubDate>Sun, 09 Oct 2022 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/csharp-dll-import-memo/</guid>
      <description>dllImport的入口点问题 通过Dependencies查询Dll对应方法的EntryPoint
然后在dllimport的attribute中显式申明EntryPoint
[DllImport(&amp;#34;demo.dll&amp;#34;, SetLastError = true,EntryPoint =&amp;#34;??0DemoManager@EcgParser@Gfeit@@AEAA@XZ&amp;#34;)] public static extern IntPtr DemoManager(); 导入类方法的问题 最好的方式还是使用C++构造wrapper，然后通过windowsApi的方式调用Pinvoke
参考链接 swig nuget
swig
C++/C# interoperability
Working with C++ Interface Classes from C#
Call function in unmanaged DLL from C# and pass custom data types [Marshal]
SWIG and C#
Example for SWIG to wrap C++ library in .Net 6</description>
    </item>
    
    <item>
      <title>golang http Reverse Proxy使用备忘</title>
      <link>https://czyt.tech/post/golang-http-reverse-proxy-usage-memo/</link>
      <pubDate>Fri, 30 Sep 2022 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/golang-http-reverse-proxy-usage-memo/</guid>
      <description>创建 一般使用 使用 httputil.NewSingleHostReverseProxy 即可
返回Response 当我们想实现获取通过ReverseProxy的请求结果时，可以使用自定义的 responsewriter 来实现。参考定义
func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) { .... } type ResponseWriter interface { // Header returns the header map that will be sent by // WriteHeader. The Header map also is the mechanism with which // Handlers can set HTTP trailers. // // Changing the header map after a call to WriteHeader (or // Write) has no effect unless the modified headers are // trailers.</description>
    </item>
    
    <item>
      <title>tailscale的泛型SingleFlight</title>
      <link>https://czyt.tech/post/generic-singleflight-by-tailscale/</link>
      <pubDate>Fri, 23 Sep 2022 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/generic-singleflight-by-tailscale/</guid>
      <description>源地址 tailscale仓库
完整代码如下
// Copyright (c) 2022 Tailscale Inc &amp;amp; AUTHORS All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Copyright 2013 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package singleflight provides a duplicate function call suppression // mechanism.</description>
    </item>
    
    <item>
      <title>Rasp3b 安装Postgresql</title>
      <link>https://czyt.tech/post/install-postgresql-on-rasp3b/</link>
      <pubDate>Sat, 17 Sep 2022 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/install-postgresql-on-rasp3b/</guid>
      <description>安装 系统信息
使用命令安装 yay -S postgresql
初始化及配置 启用数据库服务 sudo systemctl enable --now postgresql
开启数据库服务 sudo systemctl start postgresql
初始化数据 su - postgres -c &amp;quot;initdb --locale en_US.UTF-8 -D &#39;/var/lib/postgres/data&#39;&amp;quot;
查询配置文件路径
su - postgres [postgres@homeserver ~]$ ls data [postgres@homeserver ~]$ psql psql (14.5) 输入 &amp;#34;help&amp;#34; 来获取帮助信息. postgres=# SHOW config_file; config_file ---------------------------------------- /var/lib/postgres/data/postgresql.conf (1 行记录) 修改监听 修改配置/var/lib/postgres/data/postgresql.conf 文件中的listen_addresses = &#39;*&#39;监听所有地址，重启服务sudo systemctl restart postgresql生效。
允许远程访问 修改配置文件同级目录下的pg_hba.conf,添加一行
# TYPE DATABASE USER CIDR-ADDRESS METHOD host all all 0.</description>
    </item>
    
    <item>
      <title>.NET6 从JSON获取配置</title>
      <link>https://czyt.tech/post/dotnet6-load-config-from-json/</link>
      <pubDate>Tue, 06 Sep 2022 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/dotnet6-load-config-from-json/</guid>
      <description>环境准备 nuget包 Microsoft.Extensions.Configuration Microsoft.Extensions.Configuration.Binder Microsoft.Extensions.Configuration.Json (当需要从Json文件添加记录时，安装此nuget包) Microsoft.Extensions.Configuration.EnvironmentVariables (当需要从环境变量添加记录时，安装此nuget包) C#开发环境 visual studio 2019 + visual Code 示例代码 // See https://aka.ms/new-console-template for more information using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration.Json; Console.WriteLine(&amp;#34;Hello, World!&amp;#34;); ConfigurationBuilder configurationBuilder = new ConfigurationBuilder(); IConfiguration c = configurationBuilder.AddJsonFile(&amp;#34;appsettings.json&amp;#34;).AddEnvironmentVariables().Build(); var k = c.GetRequiredSection(&amp;#34;Settings&amp;#34;).Get&amp;lt;Settings&amp;gt;().KeyOne; var n = 1; public class NestedSettings { public string Message { get; set; } = null!; } public class Settings { public int KeyOne { get; set; } public bool KeyTwo { get; set; } public NestedSettings KeyThree { get; set; } = null!</description>
    </item>
    
    <item>
      <title>浅谈windows默认Shell的替换</title>
      <link>https://czyt.tech/post/a-brief-talk-about-replace-windows-default-shell-with-wpf/</link>
      <pubDate>Wed, 31 Aug 2022 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/a-brief-talk-about-replace-windows-default-shell-with-wpf/</guid>
      <description>Windows XP时代 Xp时代提供的是通过注册表来自定义shell
设置所有用户的shell 注册表键HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Winlogon\Shell
设置当前用户的shell注册表键 HKEY_Current_User\Software\Microsoft\Windows NT\CurrentVersion\Winlogon\Shell
注册表键值类型 REG_SZ
值修改为你要自定义为shell的程序的完整路径。
在windows10下使用该技巧可能会出现黑屏的现象，参考stackoverflow的回答
Simply replacing the &amp;ldquo;explorer.exe&amp;rdquo; (HKLM\SOFTWARE\Microsoft\Window NT\Winlogon\Shell) with a custom app location provided a black screen.
A much simpler way, and it works great, was to create a BATCH script to call the custom app through elevated powershell&amp;hellip;
powershell -nologo -noprofile -executionpolicy bypass -command &amp;#34;start-process -verb &amp;#39;runas&amp;#39; -filepath &amp;lt;full path of custom app executable&amp;gt;&amp;#34; By replacing &amp;ldquo;explorer.exe&amp;rdquo; with this batch script I was able to successfully create a kiosk style lockdown under Windows 10 PRO with a non-UWP app.</description>
    </item>
    
    <item>
      <title>Golang 默认的CGO参数编译导致的GLIBC错误</title>
      <link>https://czyt.tech/post/golang-default-cgo-flags-caused-glibc-missing-error/</link>
      <pubDate>Tue, 30 Aug 2022 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/golang-default-cgo-flags-caused-glibc-missing-error/</guid>
      <description>问题描述 使用go正常编译了Linux下的程序，放到服务器上报错
./app: /lib64/libc.so.6: version `GLIBC_2.34&amp;#39; not found (required by ./app) 解决 Google了下，发现相同的Issue,于是通过go env检查本机golang运行环境，发现CGO默认启用而且程序也不涉及CGO相关的东西，于是设置CGO参数为关闭。然后编译程序
CGO_ENABLED=&amp;quot;0&amp;quot; go build -v
重新上传，运行OK.</description>
    </item>
    
    <item>
      <title>在Alibaba Cloud Linux上安装MongoDB</title>
      <link>https://czyt.tech/post/install-mongodb-on-alibaba-cloud-linux/</link>
      <pubDate>Tue, 30 Aug 2022 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/install-mongodb-on-alibaba-cloud-linux/</guid>
      <description>安装步骤 查询系统版本 执行命令lsb_release -a返回下面的内容
LSB Version:	:core-4.1-amd64:core-4.1-noarch Distributor ID:	AlibabaCloud Description:	Alibaba Cloud Linux release 3 (Soaring Falcon) Release:	3 Codename:	SoaringFalcon 添加yum源 创建repo文件etc/yum.repos.d/mongodb.repo并输入下面的内容，这里安装的mongodb版本为6.0,其他版本请参考官网（配置偶数版本，奇数版不适合生产使用）。
官网的配置文件如下：
[mongodb-org-6.0] name=MongoDB Repository baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/6.0/x86_64/ gpgcheck=1 enabled=1 gpgkey=https://www.mongodb.org/static/pgp/server-6.0.asc 使用这个配置文件是安装不了的，需要修改$releasever为相应的版本，Alibaba Cloud Linux 3修改为8 （设置一个releasever的环境变量也许也可以，没有验证。）即可。即下面的样子
[mongodb-org-6.0] name=MongoDB Repository baseurl=https://repo.mongodb.org/yum/redhat/8/mongodb-org/6.0/x86_64/ gpgcheck=1 enabled=1 gpgkey=https://www.mongodb.org/static/pgp/server-6.0.asc 使用命令 yum -y install mongodb-org 安装即可。另外阿里云也提供了国内的镜像源，上面的配置文件可以修改为下面的内容，也是等效的。
[mongodb-org-6.0] name=MongoDB Repository baseurl=http://mirrors.aliyun.com/mongodb/yum/redhat/8/mongodb-org/6.0/x86_64/ gpgcheck=1 enabled=1 gpgkey=https://www.mongodb.org/static/pgp/server-6.0.asc 参考链接 如何在Alibaba Cloud Linux 3上安装MongoDB 5.0 </description>
    </item>
    
    <item>
      <title>golang http客户端使用自定义dns</title>
      <link>https://czyt.tech/post/golang-http-use-custom-dns/</link>
      <pubDate>Mon, 22 Aug 2022 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/golang-http-use-custom-dns/</guid>
      <description>摘自互联网 原文
package main import ( &amp;#34;context&amp;#34; &amp;#34;io/ioutil&amp;#34; &amp;#34;log&amp;#34; &amp;#34;net&amp;#34; &amp;#34;net/http&amp;#34; &amp;#34;time&amp;#34; ) func main() { var ( dnsResolverIP = &amp;#34;8.8.8.8:53&amp;#34; // Google DNS resolver. dnsResolverProto = &amp;#34;udp&amp;#34; // Protocol to use for the DNS resolver dnsResolverTimeoutMs = 5000 // Timeout (ms) for the DNS resolver (optional) ) dialer := &amp;amp;net.Dialer{ Resolver: &amp;amp;net.Resolver{ PreferGo: true, Dial: func(ctx context.Context, network, address string) (net.Conn, error) { d := net.Dialer{ Timeout: time.Duration(dnsResolverTimeoutMs) * time.</description>
    </item>
    
    <item>
      <title>golang转换任意长度[] byte为int</title>
      <link>https://czyt.tech/post/golang-convert-any-length-bytes-array-to-int/</link>
      <pubDate>Sat, 30 Jul 2022 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/golang-convert-any-length-bytes-array-to-int/</guid>
      <description>package main import ( &amp;#34;encoding/binary&amp;#34; &amp;#34;fmt&amp;#34; ) func main() { slices := [][]byte{ {1}, {1, 2}, {1, 2, 3}, {1, 2, 3, 4}, {1, 2, 3, 4, 5}, {1, 2, 3, 4, 5, 6}, {1, 2, 3, 4, 5, 6, 7}, {1, 2, 3, 4, 5, 6, 7, 8}, } for _, s := range slices { fmt.Println(getInt1(s), getInt2(s)) } } func getInt1(s []byte) int { var b [8]byte copy(b[8-len(s):], s) return int(binary.</description>
    </item>
    
    <item>
      <title>Protobuf golang小札</title>
      <link>https://czyt.tech/post/protobuf-golang-litle-notes/</link>
      <pubDate>Mon, 25 Jul 2022 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/protobuf-golang-litle-notes/</guid>
      <description>Oneof 如果您有许多字段的消息，并且最多可以同时设置一个字段，则可以使用Oneof功能来执行此行为并保存内存。一个字段就像常规字段一样，除了单一共享内存中的所有字段，最多可以同时设置一个字段。设置Oneof的任何成员都会自动清除所有其他成员。
​	Google protobuf 文档#Oneof
示例proto 创建protoOneof.proto 的proto文件
syntax = &amp;#34;proto3&amp;#34;; package oneof_test; option go_package =&amp;#39;.;oneof&amp;#39;; message WeiboUser{ string user_id = 1; string user_nick = 2; } message DouyinUser{ string auth_token = 1; string nick_name = 2; } message User{ oneof user_source{ string weibo_url = 1; string douyin_url = 2; } oneof user_info{ WeiboUser weibo_user_info = 3; DouyinUser douyin_user_info = 4; } } 使用命令生成go代码
protoc --proto_path=. --go_out=paths=source_relative:./oneof ./protoOneof.proto 生成的protoOneof.pb.go代码如下：</description>
    </item>
    
    <item>
      <title>使用gotests生成表驱动测试</title>
      <link>https://czyt.tech/post/use-gotests-to-generate-table-driven-tests/</link>
      <pubDate>Fri, 22 Jul 2022 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/use-gotests-to-generate-table-driven-tests/</guid>
      <description>使用gotests可以很方便的生成表驱动测试代码，表驱动测试的具体内容，请参考go官方的wiki。下面是具体的使用方法。
安装 使用下面命令进行安装
go install github.com/cweill/gotests/gotests@latest 如果是go1.16之前的版本，可以使用命令 go get -u github.com/cweill/gotests/...来进行安装。
使用 gotests支持的参数如下：
Usage of C:\Users\czyt\go\bin\gotests.exe:-allgenerate tests for all functions and methods-excl stringregexp. generate tests for functions and methods that don&amp;#39;t match. Takes precedence over -only, -exported, and -all-exportedgenerate tests for exported functions and methods. Takes precedence over -only and -all-i print test inputs in error messages-nosubtestsdisable generating tests using the Go 1.</description>
    </item>
    
    <item>
      <title>ETCD一键安装脚本</title>
      <link>https://czyt.tech/post/etcd-install-script/</link>
      <pubDate>Thu, 21 Jul 2022 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/etcd-install-script/</guid>
      <description>最近要使用ETCD，脚本根据官方GitHub脚本修改而来
#!/usr/bin/bash ETCD_VER=v3.5.4 # choose either URL GOOGLE_URL=https://storage.googleapis.com/etcd GITHUB_URL=https://fastgit.czyt.tech/https://github.com/etcd-io/etcd/releases/download ARCH=linux-arm64 DOWNLOAD_URL=${GITHUB_URL} INSTALL_DIR=/opt/etcd rm -f /tmp/etcd-${ETCD_VER}-${ARCH}.tar.gz rm -rf ${INSTALL_DIR} &amp;amp;&amp;amp; mkdir -p ${INSTALL_DIR} curl -L ${DOWNLOAD_URL}/${ETCD_VER}/etcd-${ETCD_VER}-${ARCH}.tar.gz -o /tmp/etcd-${ETCD_VER}-${ARCH}.tar.gz tar xzvf /tmp/etcd-${ETCD_VER}-${ARCH}.tar.gz -C ${INSTALL_DIR} --strip-components=1 rm -f /tmp/etcd-${ETCD_VER}-${ARCH}.tar.gz ${INSTALL_DIR}/etcd --version ${INSTALL_DIR}/etcdctl version ${INSTALL_DIR}/etcdutl version 其中的ARCH请根据实际情况修改。
参考 https://etcd.io/docs/v3.5/demo/ </description>
    </item>
    
    <item>
      <title>Golang Expr不完全指南</title>
      <link>https://czyt.tech/post/golang-expr-uncompleted-reference/</link>
      <pubDate>Wed, 13 Jul 2022 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/golang-expr-uncompleted-reference/</guid>
      <description>安装 库的说明
Expr package provides an engine that can compile and evaluate expressions. An expression is a one-liner that returns a value (mostly, but not limited to, booleans). It is designed for simplicity, speed and safety.
The purpose of the package is to allow users to use expressions inside configuration for more complex logic. It is a perfect candidate for the foundation of a business rule engine.
安装
go get -u github.</description>
    </item>
    
    <item>
      <title>Golang DSL参考</title>
      <link>https://czyt.tech/post/golang-dsl-reference/</link>
      <pubDate>Mon, 11 Jul 2022 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/golang-dsl-reference/</guid>
      <description>ANTLR 4 图书 The definitive ANTLR 4 reference (2014) 英文版下载 中文版下载 文章 使用ANTLR和Go实现DSL入门 手把手教你使用ANTLR和Go实现一门DSL语言part1 part2part3part4part5 Parsing with ANTLR 4 and Go 实例代码 bilibili gengine link go-zero link grule-rule-engine https://github.com/kulics-works/feel-go monkey.go windows 环境配置 配置好Java环境，然后将下面的批处理加入系统环境变量：
antlr.cmd
@echo off java -classpath %~dp0antlr-4.12.0-complete.jar org.antlr.v4.Tool %* grun.cmd
@echo off java -classpath %~dp0antlr-4.12.0-complete.jar org.antlr.v4.gui.TestRig %* Others 图书 Writing A Compiler In Go Writing an Interpreter in Go µGo语言实现——从头开发一个迷你Go语言编译器 文章 Build your own DSL with Go &amp;amp; HCL</description>
    </item>
    
    <item>
      <title>Vue 相关资源</title>
      <link>https://czyt.tech/post/vue-related-resource/</link>
      <pubDate>Thu, 30 Jun 2022 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/vue-related-resource/</guid>
      <description> Vue - The Complete Guide (incl. Router &amp;amp; Composition API) The Vue.js 3 Masterclass TypeScript Friendly Vue 3 Vue.js Fundamentals </description>
    </item>
    
    <item>
      <title>Golang io.Pipe 使用</title>
      <link>https://czyt.tech/post/golang-io-pipe-usage/</link>
      <pubDate>Fri, 24 Jun 2022 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/golang-io-pipe-usage/</guid>
      <description>介绍 // Pipe creates a synchronous in-memory pipe. // It can be used to connect code expecting an io.Reader // with code expecting an io.Writer. // // Reads and Writes on the pipe are matched one to one // except when multiple Reads are needed to consume a single Write. // That is, each Write to the PipeWriter blocks until it has satisfied // one or more Reads from the PipeReader that fully consume // the written data.</description>
    </item>
    
    <item>
      <title>go embed 使用小记</title>
      <link>https://czyt.tech/post/go-embed-usage-note/</link>
      <pubDate>Thu, 23 Jun 2022 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/go-embed-usage-note/</guid>
      <description>​ go embed 是go 1.16 开始添加的特性，允许嵌入文件及文件夹，在Go程序中进行使用。官方还为此添加了embed.FS的对象。下面将常用的使用场景进行简单列举：
嵌入单个文件 官方的例子
嵌入文件并绑定到字符串变量 import _ &amp;#34;embed&amp;#34; //go:embed hello.txt var s string print(s) 嵌入文件并绑定到字节变量 import _ &amp;#34;embed&amp;#34; //go:embed hello.txt var b []byte print(string(b)) 嵌入文件并绑定到文件对象 import &amp;#34;embed&amp;#34; //go:embed hello.txt var f embed.FS data, _ := f.ReadFile(&amp;#34;hello.txt&amp;#34;) print(string(data)) 嵌入目录 嵌入时，可以在多行或者一行输入要嵌入的文件和文件夹。
package server import &amp;#34;embed&amp;#34; // content holds our static web server content. //go:embed image/* template/* //go:embed html/index.html var content embed.FS 在匹配文件夹时，embed会嵌入包括子目录下的所有除.和_开头的文件（递归），所以上面的代码大致等价于下面的代码：
// content is our static web server content.</description>
    </item>
    
    <item>
      <title>Git小技巧</title>
      <link>https://czyt.tech/post/git-tricks/</link>
      <pubDate>Fri, 17 Jun 2022 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/git-tricks/</guid>
      <description>Windows下GIT的几个小技巧 记住git密码 使用下面命令可以设置记住git密码，但推荐使用ssh进行操作。
git config credential.helper store 设置换行符转换 在windows下开发时，迁出的代码是CRLF会导致编译的sh脚本不能正确执行:
git config --global core.autocrlf false Git推送到多个服务器 要实现一次push到多个远程仓库 本机git仓库A https://aaaaa.git 要同步push的远程git仓库B https://bbbbb.git
通过git remote add添加 先使用git remote -v查看远程仓库的情况 ,然后添加一个git仓库
git remote add b https://bbbbb.git 再次查看远程仓库情况，如果需要push，则需要push两次
通过git remote set-url 添加 如果按上面添加过remote分支，需要先git remote rm b,使用下面命令添加即可。
git remote set-url --add a https://bbbbb.git 查看远程仓库情况，看看是否已经是两个push地址了 。这个只需push一次就行了
修改配置文件 打开 .git/config 找到 [remote &amp;ldquo;github&amp;rdquo;]，添加对应的 url 即可，效果如下。这种方法其实和方法二是一样的。
[remote &amp;#34;a&amp;#34;] url = https://aaaaa.git fetch = +refs/heads/*:refs/remotes/a/* url = https://bbbbb.git 参考链接
● 一个项目push到多个远程Git仓库 https://segmentfault.</description>
    </item>
    
    <item>
      <title>Golang nocopy check</title>
      <link>https://czyt.tech/post/golang-nocopy-check/</link>
      <pubDate>Fri, 17 Jun 2022 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/golang-nocopy-check/</guid>
      <description>目的 实现nocopy的目的在于，golang在进行参数传递时，都是传递副本的方式。但是某些情况，我们是需要进行传递对象的引用的（特别是一些指针对象，可能会导致多个指针的副本的操作造成程序陷入恐慌），为了杜绝调用者的复制，只能指针传递全局唯一对象。那么就可以通过添加nocopy来实现对go vet参数支持的no copy 检查。
实现 golang里面最常用的sync.WaitGroup就是通过nocopy实现的。参考定义
// A WaitGroup must not be copied after first use. type WaitGroup struct { noCopy noCopy // 64-bit value: high 32 bits are counter, low 32 bits are waiter count. // 64-bit atomic operations require 64-bit alignment, but 32-bit // compilers do not ensure it. So we allocate 12 bytes and then use // the aligned 8 bytes in them as state, and the other 4 as storage // for the sema.</description>
    </item>
    
    <item>
      <title>golang正则校验支付宝微信支付授权码</title>
      <link>https://czyt.tech/post/golang-check-wechat-alipay-authcode-via-regxp/</link>
      <pubDate>Fri, 17 Jun 2022 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/golang-check-wechat-alipay-authcode-via-regxp/</guid>
      <description>参考sdk定义
package main import ( &amp;#34;fmt&amp;#34; &amp;#34;regexp&amp;#34; ) // wechat pay 用户付款码条形码规则：18位纯数字，以10、11、12、13、14、15开头 // alipay 支付授权码，25~30开头的长度为16~24位的数字，实际字符串长度以开发者获取的付款码长度为准 func main() { // wechat regwechat:=regexp.MustCompile(&amp;#34;^(1[0-5])\\d{16}$&amp;#34;) matchwechat := regwechat.MatchString(&amp;#34;154658833119096245&amp;#34;) fmt.Println(matchwechat) // alipay regalipay:=regexp.MustCompile(&amp;#34;^(2[5-9]|30)\\d{14,22}$&amp;#34;) matchalipay := regalipay.MatchString(&amp;#34;307573774583867517336&amp;#34;) fmt.Println(matchalipay) } 参考
微信
支付宝</description>
    </item>
    
    <item>
      <title>Linux环境下Perl提权</title>
      <link>https://czyt.tech/post/perl-privilege-escalation-in-linux/</link>
      <pubDate>Fri, 17 Jun 2022 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/perl-privilege-escalation-in-linux/</guid>
      <description>事故起因 我们公司的应用程序部署目录有个bin目录，手误，删除的时候输入的是/bin
事故现象 ● SSH 不能登陆进来了 ● ls、chmod等常用命令都不能使用了 ● wget 还能用
事故解决 通过查找谷歌，发现有个perl带有提权的功能,简单来说就是
perl -e &amp;#34;chmod 0777, &amp;#39;/bin/ls&amp;#39;&amp;#34; 通过这个方式可以对指定的文件进行权限的修改。于是从另外的机器上打包了一个/bin目录，放到网上，wget 下载到本地wget bin.tar.gz
​ 本机开外网ssh转发，scp 拷贝tar文件到目录，执行
perl -e &amp;#34;chmod 0777, &amp;#39;./tar&amp;#39;&amp;#34; ,再使用tar进行文件解压./tar xvzf bin.tar.gz -C /,然后再给chmod执行文件赋予执行权限
perl -e &amp;#34;chmod 0777, &amp;#39;/bin/chmod&amp;#39;&amp;#34; 然后再通过chmod 执行 chmod -R +x /bin/给/bin目录下的可执行程序文件授予执行权限。至此，完成事故修复。
参考连接 ● https://perldoc.perl.org/functions/chmod.html</description>
    </item>
    
    <item>
      <title>ebpf Golang参考</title>
      <link>https://czyt.tech/post/ebpf-golang-reference/</link>
      <pubDate>Sat, 11 Jun 2022 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/ebpf-golang-reference/</guid>
      <description>整理一个列表，持续更新。
理论 ebf官网 B站视频 eBPF 和 Go，超能力组合 实践 Tracing Go Functions with eBPF part1 part2 Getting Started with eBPF and Go Linux中基于eBPF的恶意利用与检测机制 如何用eBPF分析Golang应用 使用BPF, 将Go网络程序的吞吐提升8倍 使用ebpf跟踪rpcx微服务 BPF MAP机制 一种通用数据结构，可以存储不同类型数据的通用数据结构 Andrii Nakryiko 抽象数据容器(abstract data container) bpf系统调用的说明 《使用C语言从头开发一个Hello World级别的eBPF程序》 《Linux Observability with BPF》 《揭秘BPF map前生今世》 bpf系统调用说明 官方bpf map参考手册 bpftool参考手册 《Building BPF applications with libbpf-bootstrap》 https://github.com/DavadDi/bpf_study https://github.com/mikeroyal/eBPF-Guide#go-development golang 包及项目 https://github.com/cilium/ebpf https://github.com/danger-dream/ebpf-firewall https://github.com/mozillazg/hello-libbpfgo </description>
    </item>
    
    <item>
      <title>Go性能优化参考</title>
      <link>https://czyt.tech/post/golang-perf-reference/</link>
      <pubDate>Sat, 11 Jun 2022 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/golang-perf-reference/</guid>
      <description>电子书 编写和优化Go代码 Go Optimizations 101 https://github.com/dgryski/go-perfbook https://github.com/DataDog/go-profiler-notes https://github.com/bobstrecansky/HighPerformanceWithGo/ https://github.com/caibirdme/hand-to-hand-optimize-go Tool flameshow goref Go package https://github.com/aclements/go-perf https://github.com/256dpi/god https://github.com/divan/expvarmon https://github.com/go-perf/awesome-go-perf https://github.com/iyashjayesh/monigo 文章 官方博客 Profiling Go Programs
Profile-guided optimization
https://dave.cheney.net/high-performance-go-workshop/dotgo-paris.html
https://github.com/golang/go/wiki/Performance
https://sumercip.com/posts/inside-the-go-cpu-profiler/
How to Write Benchmarks in Go : https://dave.cheney.net/2013/06/30/how-to-write-benchmarks-in-go
Improving Observability of GoLang Services
Debugging performance issues in Go programs : https://github.com/golang/go/wiki/Performance
Go execution tracer : https://blog.gopheracademy.com/advent-2017/go-execution-tracer/ (see also the The tracer design doc link)
A whirlwind tour of Go’s runtime environment variables (see godebug) : https://dave.</description>
    </item>
    
    <item>
      <title>Cap&#39;n Proto Windows环境设置</title>
      <link>https://czyt.tech/post/capn-proto-setup-in-windows/</link>
      <pubDate>Fri, 10 Jun 2022 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/capn-proto-setup-in-windows/</guid>
      <description>Cap&amp;rsquo;n proto 号称是比protobuff更快的proto语言。官网截图
Cap’n Proto is an insanely fast data interchange format and capability-based RPC system. Think JSON, except binary. Or think Protocol Buffers, except faster. In fact, in benchmarks, Cap’n Proto is INFINITY TIMES faster than Protocol Buffers.
协议特性
Cap’n Proto’s RPC protocol has the following notable features. Since the protocol is complicated, the feature set has been divided into numbered “levels”, so that implementations may declare which features they have covered by advertising a level number.</description>
    </item>
    
    <item>
      <title>Golang反射使用指南</title>
      <link>https://czyt.tech/post/golang-reflect-reference/</link>
      <pubDate>Thu, 02 Jun 2022 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/golang-reflect-reference/</guid>
      <description>Go是一门强类型的语言，在大多数情况下，申明一个变量、函数、struct都是直截了当的。在大多数情况下，这些都是够用的，但有时你想在程序运行中来动态扩展程序的信息，也许你想把文件或网络请求中的数据映射到一个变量中;也许你想建立一个能处理不同类型的工具(虽然Go1.18有了泛型)。在这些情况下，你需要使用反射。反射使你有能力在运行时检查、修改和创建变量、函数和结构的能力。
反射的核心 图片转自 Go 语言设计与实现
反射的三大核心是*Types, Kinds, Values,下面将围绕这三个方面来进行讲解。
我们先定义一个struct对象。
type User struct { Name	string Age int } 类型Types 通过反射获取类型
u := User{ Name: &amp;#34;czyt&amp;#34;, Age: 18, } uptr := &amp;amp;u ot := reflect.TypeOf(u) otptr := reflect.TypeOf(uptr) log.Println(ot.Name()) // 打印 User log.Println(otptr.Name()) // 打印 空 通过调用Name()方法返回类型的名称，某些类型，如切片或指针，没有名称，此方法返回一个空字符串。
种类Kinds Kind通过调用Kind()得来。
u := User{ Name: &amp;#34;czyt&amp;#34;, Age: 18, } uptr := &amp;amp;u ot := reflect.TypeOf(u) otptr := reflect.TypeOf(uptr) log.Println(ot.Kind()) // 输出 struct log.Println(otptr.Kind()) // 输出 ptr Kind() 返回的是kind类型的枚举。</description>
    </item>
    
    <item>
      <title>Golang MongoDB ODM mgm使用</title>
      <link>https://czyt.tech/post/golang-mongodb-mgm-odm-usage/</link>
      <pubDate>Tue, 31 May 2022 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/golang-mongodb-mgm-odm-usage/</guid>
      <description>(本文大部分内容根据官方文档翻译而来)
环境准备 golang 1.10+ mongodb mgm 模型定义 定义 定义模型
type Book struct { // DefaultModel adds _id, created_at and updated_at fields to the Model mgm.DefaultModel `bson:&amp;#34;,inline&amp;#34;` Name string `json:&amp;#34;name&amp;#34; bson:&amp;#34;name&amp;#34;` Pages int `json:&amp;#34;pages&amp;#34; bson:&amp;#34;pages&amp;#34;` } func NewBook(name string, pages int) *Book { return &amp;amp;Book{ Name: name, Pages: pages, } } mgm 在创建表时会自动检测Model生成的Collection名称
book:=Book{} // Print your model collection name. collName := mgm.CollName(&amp;amp;book) fmt.Println(collName) // 打印: books 如果要自定义生成Collection的名称。需要实现CollectionNameGetter接口。
func (model *Book) CollectionName() string { return &amp;#34;my_books&amp;#34; } // mgm return &amp;#34;my_books&amp;#34; collection coll:=mgm.</description>
    </item>
    
    <item>
      <title>Flutter开发Maven配置</title>
      <link>https://czyt.tech/post/maven-setting-for-flutter-dev/</link>
      <pubDate>Fri, 27 May 2022 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/maven-setting-for-flutter-dev/</guid>
      <description>在Flutter开发时，可能因为网络等原因导致maven不能正常工作，造成Flutter项目卡住的情况。下面是解决办法。原文链接 https://flutter.cn/community/china
如果你在国内使用 Flutter，那么你可能需要找一个与官方同步的可信的镜像站点，帮助你的 Flutter 命令行工具到该镜像站点下载其所需的资源。你需要为此设置两个环境变量：PUB_HOSTED_URL 和 FLUTTER_STORAGE_BASE_URL，然后再运行 Flutter 命令行工具。
以 macOS 或者与 Linux 相近的系统为例，这里有以下步骤帮助你设定镜像。在系统终端里执行如下命令设定环境变量，并通过 GitHub 检出 Flutter SDK：
content_copy
$ export PUB_HOSTED_URL=https://pub.flutter-io.cn$ export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn$ git clone -b dev https://github.com/flutter/flutter.git$ export PATH=&amp;#34;$PWD/flutter/bin:$PATH&amp;#34;$ cd ./flutter$ flutter doctor Flutter SDK配置修改 flutter的maven设置在&amp;lt;安装目录&amp;gt;\packages\flutter_tools\gradle\flutter.gradle
打包配置 buildscript {repositories {maven { url &amp;#39;https://maven.aliyun.com/repository/google&amp;#39; }maven { url &amp;#39;https://maven.aliyun.com/repository/public&amp;#39; }maven { url &amp;#39;https://maven.aliyun.com/repository/central&amp;#39; }maven { url &amp;#39;https://maven.aliyun.com/repository/jcenter&amp;#39; }// google()// jcenter()}dependencies {/* When bumping, also update ndkVersion above.</description>
    </item>
    
    <item>
      <title>MongoDB操作指北</title>
      <link>https://czyt.tech/post/operate-mongodb-tutorial/</link>
      <pubDate>Thu, 26 May 2022 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/operate-mongodb-tutorial/</guid>
      <description>TL;DR
环境准备 mongoDB 预备知识 MongoDB常见的数据类型
数据类型 示例 说明 Null {&amp;quot;x&amp;quot; : null} Boolean {&amp;quot;x&amp;quot; : true} Number {&amp;quot;x&amp;quot; : 3.14} {&amp;quot;x&amp;quot; : 3} {&amp;quot;x&amp;quot; : NumberInt(&amp;quot;3&amp;quot;)} {&amp;quot;x&amp;quot; : NumberLong(&amp;quot;3&amp;quot;)} 默认64位浮点数，整数需要使用NumberInt和NumberLong String {&amp;quot;x&amp;quot; : &amp;quot;foobar&amp;quot;} 编码格式为UTF-8 Date {&amp;quot;x&amp;quot; : new Date()} 64位时间戳(从January 1, 1970)，不存时区。通过new Date()进行调用。 Regular expression {&amp;quot;x&amp;quot; : /foobar/i} javascript 正则 Array {&amp;quot;x&amp;quot; : [&amp;quot;a&amp;quot;, &amp;quot;b&amp;quot;, &amp;quot;c&amp;quot;]} Embedded document {&amp;quot;x&amp;quot; : {&amp;quot;foo&amp;quot; : &amp;quot;bar&amp;quot;}} Object ID {&amp;quot;x&amp;quot; : ObjectId()} 文档12字节的ID Binary data 一个任意字节的字符串。是保存非UTF-8字符串到数据库的唯一方法。 Code {&amp;quot;x&amp;quot; : function() { /* .</description>
    </item>
    
    <item>
      <title>通过注册表禁用windows10自动更新</title>
      <link>https://czyt.tech/post/block-windows10-update-via-registry/</link>
      <pubDate>Thu, 19 May 2022 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/block-windows10-update-via-registry/</guid>
      <description>缘起 近期项目上设备会自动更新windows10为windows11，通过搜索，搜索到第三方工具windows-update-blocker ，因为改工具支持命令行参数，故也很方便于集成。批处理大致如下
@echo off pushd %~dp0 echo 开始禁用windows更新服务 %~dp0Wub_x64.exe /D /P timeout 3 背后的操作 作为技术人，还是需要知道软件做了什么背后的操作，通过TotalUninstaller监控，获取到软件写入的注册表如下,实现的手段就是镜像劫持windows更新的进程，并且更新windows的组策略选项：
Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer] &amp;#34;NoWindowsUpdate&amp;#34;=dword:00000001 [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options] &amp;#34;WubBlockLists&amp;#34;=hex(7):57,00,61,00,61,00,53,00,4D,00,65,00,64,00,69,00,63,00,\ 2E,00,65,00,78,00,65,00,00,00,57,00,61,00,61,00,73,00,4D,00,65,00,64,00,69,\ 00,63,00,41,00,67,00,65,00,6E,00,74,00,2E,00,65,00,78,00,65,00,00,00,57,00,\ 69,00,6E,00,64,00,6F,00,77,00,73,00,31,00,30,00,55,00,70,00,67,00,72,00,61,\ 00,64,00,65,00,2E,00,65,00,78,00,65,00,00,00,57,00,69,00,6E,00,64,00,6F,00,\ 77,00,73,00,31,00,30,00,55,00,70,00,67,00,72,00,61,00,64,00,65,00,72,00,41,\ 00,70,00,70,00,2E,00,65,00,78,00,65,00,00,00,55,00,70,00,64,00,61,00,74,00,\ 65,00,41,00,73,00,73,00,69,00,73,00,74,00,61,00,6E,00,74,00,2E,00,65,00,78,\ 00,65,00,00,00,55,00,73,00,6F,00,43,00,6C,00,69,00,65,00,6E,00,74,00,2E,00,\ 65,00,78,00,65,00,00,00,72,00,65,00,6D,00,73,00,68,00,2E,00,65,00,78,00,65,\ 00,00,00,45,00,4F,00,53,00,6E,00,6F,00,74,00,69,00,66,00,79,00,2E,00,65,00,\ 78,00,65,00,00,00,53,00,69,00,68,00,43,00,6C,00,69,00,65,00,6E,00,74,00,2E,\ 00,65,00,78,00,65,00,00,00,75,00,70,00,66,00,63,00,2E,00,65,00,78,00,65,00,\ 00,00,49,00,6E,00,73,00,74,00,61,00,6C,00,6C,00,41,00,67,00,65,00,6E,00,74,\ 00,2E,00,65,00,78,00,65,00,00,00,4D,00,75,00,73,00,4E,00,6F,00,74,00,69,00,\ 66,00,69,00,63,00,61,00,74,00,69,00,6F,00,6E,00,2E,00,65,00,78,00,65,00,00,\ 00,4D,00,75,00,73,00,4E,00,6F,00,74,00,69,00,66,00,69,00,63,00,61,00,74,00,\ 69,00,6F,00,6E,00,55,00,78,00,2E,00,65,00,78,00,65,00,00,00,00,00,00,00 [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\EOSnotify.exe] &amp;#34;Debugger&amp;#34;=&amp;#34;/&amp;#34; [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\InstallAgent.exe] &amp;#34;Debugger&amp;#34;=&amp;#34;/&amp;#34; [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\MusNotification.exe] &amp;#34;Debugger&amp;#34;=&amp;#34;/&amp;#34; [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\MusNotificationUx.exe] &amp;#34;Debugger&amp;#34;=&amp;#34;/&amp;#34; [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\remsh.</description>
    </item>
    
    <item>
      <title>Golang监测Linux网络事件</title>
      <link>https://czyt.tech/post/golang-monitor-linux-network-events/</link>
      <pubDate>Tue, 17 May 2022 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/golang-monitor-linux-network-events/</guid>
      <description>代码 package main import ( &amp;#34;fmt&amp;#34; &amp;#34;syscall&amp;#34; ) func main() { l, _ := ListenNetlink() for { msgs, err := l.ReadMsgs() if err != nil { fmt.Println(&amp;#34;Could not read netlink: %s&amp;#34;, err) } for _, m := range msgs { if IsNewAddr(&amp;amp;m) { fmt.Println(&amp;#34;New Addr&amp;#34;) } if IsDelAddr(&amp;amp;m) { fmt.Println(&amp;#34;Del Addr&amp;#34;) } } } } type NetlinkListener struct { fd int sa *syscall.SockaddrNetlink } func ListenNetlink() (*NetlinkListener, error) { groups := (1 &amp;lt;&amp;lt; (syscall.</description>
    </item>
    
    <item>
      <title>Golang False sharing</title>
      <link>https://czyt.tech/post/golang-false-sharing/</link>
      <pubDate>Thu, 12 May 2022 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/golang-false-sharing/</guid>
      <description>缘起 来自于一段prometheus代码
type stripeLock struct { sync.RWMutex // Padding to avoid multiple locks being on the same cache line. _ [40]byte } 简单地讲就是因为CPU读取数据的缓存机制问题，可能导致性能上的不同差异。参考资料见后文。
常见类型的内存占用大小（Go101）：
Kinds of Types Value Size Required by Go Specification bool 1 byte not specified int8, uint8 (byte) 1 byte 1 byte int16, uint16 2 bytes 2 bytes int32 (rune), uint32, float32 4 bytes 4 bytes int64, uint64, float64, complex64 8 bytes 8 bytes complex128 16 bytes 16 bytes int, uint 1 word architecture dependent, 4 bytes on 32-bit architectures and 8 bytes on 64-bit architectures uintptr 1 word large enough to store the uninterpreted bits of a pointer value string 2 words not specified pointer (safe or unsafe) 1 word not specified slice 3 words not specified map 1 word not specified channel 1 word not specified function 1 word not specified interface 2 words not specified struct (the sum of sizes of all fields) + (the number of padding bytes) the size of a struct type is zero if it contains no fields that have a size greater than zero array (element value size) * (array length) the size of an array type is zero if its element type has zero size 参考 https://medium.</description>
    </item>
    
    <item>
      <title>WPF与虚拟键盘的那些事</title>
      <link>https://czyt.tech/post/wpf-virtual-keyboard-related/</link>
      <pubDate>Mon, 25 Apr 2022 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/wpf-virtual-keyboard-related/</guid>
      <description>缘起 近期项目使用到相关技术，故整理文章一篇。
获取可用输入设备 软件的本质无非是输入和输出，那么WPF如何获取电脑是否有可用输入设备呢？查询了Google,在StackOverflow上找到一个提问，原帖地址，代码如下：
KeyboardCapabilities keyboardCapabilities = new Windows.Devices.Input.KeyboardCapabilities(); return keyboardCapabilities.KeyboardPresent != 0 ? true : false; 如果没有可用输入设备，那么就该虚拟键盘上场了。windows里面有两个虚拟键盘的程序，一个是TabTip.exe一个是osk.exe,可以直接调用进程，也可以使用 WPF的第三方组件https://github.com/maximcus/WPFTabTip 详细实现可以参考后面的链接。
平板模式 下面代码将当前系统的运行模式改为平板模式
public static readonly Guid CLSID_ImmersiveShell = new Guid(&amp;#34;C2F03A33-21F5-47FA-B4BB-156362A2F239&amp;#34;); [ComImport()] [Guid(&amp;#34;4FDA780A-ACD2-41F7-B4F2-EBE674C9BF2A&amp;#34;)] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface ITabletModeController { int GetMode(ref int mode); int SetMode(int mode, int modeTrigger); } [ComImport] [Guid(&amp;#34;6D5140C1-7436-11CE-8034-00AA006009FA&amp;#34;)] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface IServiceProvider { [return: MarshalAs(UnmanagedType.IUnknown)] object QueryService(ref Guid service, ref Guid riid); } 调用
var pSP = (IServiceProvider)Activator.CreateInstance(Type.GetTypeFromCLSID(CLSID_ImmersiveShell)); var pTMC = (ITabletModeController)pSP.</description>
    </item>
    
    <item>
      <title>Keep运动接口</title>
      <link>https://czyt.tech/post/keep-api-collect/</link>
      <pubDate>Thu, 21 Apr 2022 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/keep-api-collect/</guid>
      <description>基础接口 授权 curl --location --request POST &amp;#39;https://api.gotokeep.com/v1.1/users/login&amp;#39; \ --header &amp;#39;Content-Type: application/json&amp;#39; \ --data-raw &amp;#39;{&amp;#34;mobile&amp;#34;: 18888888888, &amp;#34;password&amp;#34;: &amp;#34;aa&amp;#34;}&amp;#39; 返回token内容需要作为后续请求的header传递，返回示例：
{ &amp;#34;ok&amp;#34;: true, &amp;#34;data&amp;#34;: { &amp;#34;userId&amp;#34;: &amp;#34;011981111e131&amp;#34;, &amp;#34;level&amp;#34;: 0, &amp;#34;goal&amp;#34;: 0, &amp;#34;gender&amp;#34;: &amp;#34;M&amp;#34;, &amp;#34;token&amp;#34;: &amp;#34;xxxxxxxxxxxx&amp;#34;, &amp;#34;userRegisterInfo&amp;#34;: null }, &amp;#34;errorCode&amp;#34;: &amp;#34;0&amp;#34;, &amp;#34;now&amp;#34;: &amp;#34;2022-04-21T05:02:57Z&amp;#34;, &amp;#34;version&amp;#34;: &amp;#34;1.0.0&amp;#34;, &amp;#34;text&amp;#34;: null, &amp;#34;more&amp;#34;: {} } 动作库 获取动作分类
curl --location --request GET &amp;#39;https://api.gotokeep.com/training/v2/trainingpoints/exerciselib&amp;#39; \ --header &amp;#39;Authorization: Bearer xxxxxxxxx&amp;#39; 返回
{ &amp;#34;ok&amp;#34;: true, &amp;#34;data&amp;#34;: [ { &amp;#34;name&amp;#34;: &amp;#34;胸部&amp;#34;, &amp;#34;_id&amp;#34;: &amp;#34;54826e417fb786000069ad82&amp;#34;, &amp;#34;url&amp;#34;: &amp;#34;http://static1.</description>
    </item>
    
    <item>
      <title>为Kratos prtobuf文件添加多种编译输出</title>
      <link>https://czyt.tech/post/add-muti-kinds-output-for-kratos/</link>
      <pubDate>Fri, 08 Apr 2022 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/add-muti-kinds-output-for-kratos/</guid>
      <description>Csharp 安装Grpc.tools https://www.nuget.org/packages/Grpc.Tools/
下载解压 nupkg文件（改扩展名为zip），也可以使用附件的7z包
解压 找到tools中对应系统架构的软件，设置下环境变量，让系统可以找到就行。
Linux 需要创建一个符号链接
ln -s `which grpc_csharp_plugin` /usr/bin/protoc-gen-grpc-csharp 修改Kratos项目的Make文件 在api这个make任务中添加下面内容
--csharp_out=./api/pipe/v1 \ --grpc-csharp_out=./api/pipe/v1 \ 完整内容为
.PHONY: api # generate api proto api: protoc --proto_path=./api \ --proto_path=./third_party \ --go_out=paths=source_relative:./api \ --go-http_out=paths=source_relative:./api \ --go-grpc_out=paths=source_relative:./api \ --csharp_out=./api/pipe/v1 \ --grpc-csharp_out=./api/pipe/v1 \ --openapi_out==paths=source_relative:. \ 参考
https://github.com/grpc/grpc/blob/master/src/csharp/BUILD-INTEGRATION.md
📎tools.7z
Python 安装必要包 pip install grpclib protobuf 查询路径 which protoc-gen-grpclib_python 或者 which protoc-gen-python_grpc我这里返回信息如下： ➜ czyt which protoc-gen-grpclib_python /usr/sbin/protoc-gen-grpclib_python 如法炮制，创建软链接 ln -s /usr/sbin/protoc-gen-grpclib_python /usr/sbin/protoc-gen-grpc_python 修改Makefile 添加下面的内容,再执行make api生成api即可。 --python_out=.</description>
    </item>
    
    <item>
      <title>个人Golang环境安装快速设置</title>
      <link>https://czyt.tech/post/personal-golang-env-quick-set/</link>
      <pubDate>Thu, 24 Mar 2022 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/personal-golang-env-quick-set/</guid>
      <description>下载 官方下载 https://go.dev/dl/
Google 香港镜像
Golang Downloads Mirrors
更多请参考 Thanks Mirror
环境设置 设置proxy
go env -w GOPROXY=https://goproxy.io,https://goproxy.cn,direct 安装相关工具 进程工具 goreman go install github.com/mattn/goreman@latest
框架Cli kratos go install github.com/go-kratos/kratos/cmd/kratos/v2@latest
wire go install github.com/google/wire/cmd/wire@latest
ent go install entgo.io/ent/cmd/ent@latest
entimport go install ariga.io/entimport/cmd/entimport@latest
entproto go install entgo.io/contrib/entproto/cmd/entproto@latest
代码Lint golangci-lint go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
golines go install github.com/segmentio/golines@latest
Go into the Goland settings and click &amp;ldquo;Tools&amp;rdquo; -&amp;gt; &amp;ldquo;File Watchers&amp;rdquo; then click the plus to create a new file watcher Set the following properties and confirm by clicking OK: Name: golines File type: Go files Scope: Project Files Program: golines Arguments: $FilePath$ -w Output paths to refresh: $FilePath$ gofumpt go install mvdan.</description>
    </item>
    
    <item>
      <title>Rasp3b 安装MongoDB</title>
      <link>https://czyt.tech/post/install-mongodb-on-rasp3b/</link>
      <pubDate>Wed, 23 Mar 2022 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/install-mongodb-on-rasp3b/</guid>
      <description>安装 机器安装的是Manjaro,所以本文介绍的是Manjaro的树莓派3安装方式
➜ ~ screenfetch czyt@** OS: Manjaro-ARM 22.01 Kernel: aarch64 Linux 5.15.24-1-MANJARO-ARM-RPI ##### Uptime: 21d 21h 58m ####### Packages: Unknown ##O#O## Shell: zsh 5.8.1 ####### Disk: 11G / 118G (9%) ########### CPU: BCM2835 @ 4x 1.2GHz ############# GPU: ############### RAM: 248MiB / 919MiB ################ ################# ##################### ##################### ################# 使用命令 yay -S mongodb44-bin进行安装，安装完毕后
启用服务 systemctl enable mongodb
检查服务状态 systemctl status mongodb
● mongodb.service - MongoDB Database Server Loaded: loaded (/usr/lib/systemd/system/mongodb.service; enabled; vendor preset: disabled) Active: active (running) since Wed 2022-03-23 13:11:08 CST; 11s ago Docs: https://docs.</description>
    </item>
    
    <item>
      <title>WPF Prism 8如何注册Logging</title>
      <link>https://czyt.tech/post/how-to-register-logging-in-prism8/</link>
      <pubDate>Tue, 08 Mar 2022 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/how-to-register-logging-in-prism8/</guid>
      <description>Nuget包 基础包 Microsoft Logging Abstractions Microsoft Extensions DependencyInjection 可选日志包 可以按实际需求进行选择，如NLog等,我们这里采用的是 Serilog 这个Nuget包Serilog Extensions Logging
根据日志输出的目标不同，可以选择不同的扩展方法包
目标 包名 说明 文件 Serilog.Sinks.File WiteTo可以使用File方法详细说明 命令行 Serilog.Sinks.Console 调试输出 Serilog.Sinks.Debug WiteTo可以使用Debug方法 其他扩展，请搜索 点击
日志容器注册 我们使用的是 DryIoc 进行注册，需要安装Nuget包 DryIoc.Microsoft.DependencyInjection 具体代码如下：
protected override IContainerExtension CreateContainerExtension() { var serviceCollection = new ServiceCollection(); serviceCollection.AddLogging(loggingBuilder =&amp;gt; loggingBuilder.AddSerilog(dispose: true)); return new DryIocContainerExtension(new Container(CreateContainerRules()) .WithDependencyInjectionAdapter(serviceCollection)); } 如果是Unity 则需要安装包 Unity.Microsoft.DependencyInjection 具体代码如下：
protected override IContainerExtension CreateContainerExtension() { var serviceCollection = new ServiceCollection(); serviceCollection.AddLogging(loggingBuilder =&amp;gt; loggingBuilder.</description>
    </item>
    
    <item>
      <title>grpc-golang windows环境搭建说明</title>
      <link>https://czyt.tech/post/grpc-golang-setup-in-windows/</link>
      <pubDate>Mon, 28 Feb 2022 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/grpc-golang-setup-in-windows/</guid>
      <description>下载protoc，打开链接 下载后将对应的文件解压到gopath的bin目录。 下载protoc的golang插件。下载地址 链接 下载后放在protoc的同级目录（需要改扩展名为exe） 测试，定义一个Proto syntax = &amp;#34;proto3&amp;#34;; option go_package = &amp;#34;.;hello&amp;#34;; package main; message String { string value = 1; } 然后执行命令 protoc hello.proto --go_out=. ,大功告成，生成的文件内容如下：
// Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.24.0-devel // protoc v3.12.3 // source: hello.proto package hello import ( proto &amp;#34;github.com/golang/protobuf/proto&amp;#34; protoreflect &amp;#34;google.golang.org/protobuf/reflect/protoreflect&amp;#34; protoimpl &amp;#34;google.golang.org/protobuf/runtime/protoimpl&amp;#34; reflect &amp;#34;reflect&amp;#34; sync &amp;#34;sync&amp;#34; ) const ( // Verify that this generated code is sufficiently up-to-date.</description>
    </item>
    
    <item>
      <title>Rust安装及配置</title>
      <link>https://czyt.tech/post/rust-setup-and-config/</link>
      <pubDate>Mon, 28 Feb 2022 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/rust-setup-and-config/</guid>
      <description>下载rustup 从此处下载，如果你需要安装vs的cpp生成工具，可以在这个页面进行下载。
设置rustup镜像 字节提供的镜像 https://rsproxy.cn
export RUSTUP_DIST_SERVER=&amp;#34;https://rsproxy.cn&amp;#34; export RUSTUP_UPDATE_ROOT=&amp;#34;https://rsproxy.cn/rustup&amp;#34; 设置两个环境变量即可。windows可以使用下面的命令进行设置：
setx RUSTUP_DIST_SERVER &amp;#34;https://rsproxy.cn&amp;#34; setx RUSTUP_UPDATE_ROOT &amp;#34;https://rsproxy.cn/rustup&amp;#34; 中科大 设置环境变量 RUSTUP_DIST_SERVER (用于更新 toolchain)
export RUSTUP_DIST_SERVER=https://mirrors.ustc.edu.cn/rust-static 以及 RUSTUP_UPDATE_ROOT (用于更新 rustup)
export RUSTUP_UPDATE_ROOT=https://mirrors.ustc.edu.cn/rust-static/rustup 华中科技大学 **方法一：**在“系统-高级系统设置-环境变量” 中增加环境变量。
变量名为 RUSTUP_DIST_SERVER，值为https://mirrors.hust.edu.cn/rustup。 变量名为 RUSTUP_UPDATE_ROOT，值为https://mirrors.hust.edu.cn/rustup/rustup。 **方法二（推荐）：**直接执行下面的Powershell脚本：
[System.Environment]::SetEnvironmentVariable(&amp;#34;RUSTUP_DIST_SERVER&amp;#34;, &amp;#34;https://mirrors.hust.edu.cn/rustup&amp;#34;, &amp;#34;User&amp;#34;) [System.Environment]::SetEnvironmentVariable(&amp;#34;RUSTUP_UPDATE_ROOT&amp;#34;, &amp;#34;https://mirrors.hust.edu.cn/rustup/rustup&amp;#34;, &amp;#34;User&amp;#34;) 设置RUSTUP_HOME和CARGO_HOME可以实现自定义安装路径
对于使用buf的开发者，需要添加下面的内容：
[registries.buf] index = &amp;#34;sparse+https://buf.build/gen/cargo/&amp;#34; credential-provider = &amp;#34;cargo:token&amp;#34; 然后登陆,token可以从这里获取
cargo login --registry buf &amp;#34;Bearer {token}&amp;#34; 更多内容，请参考https://buf.build/docs/bsr/generated-sdks/cargo
crates.io 镜像 编辑 ~/.cargo/config ，这里使用的是中科大的镜像。
cargo版本 1.39 中添加了对 .toml 扩展的支持，并且是首选形式。如果两个文件都存在，Cargo 将使用不带扩展名的文件。</description>
    </item>
    
    <item>
      <title>一个免费的TTS接口</title>
      <link>https://czyt.tech/post/a-free-tts-api/</link>
      <pubDate>Mon, 28 Feb 2022 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/a-free-tts-api/</guid>
      <description>示例：
https://dds.dui.ai/runtime/v1/synthesize?voiceId=ppangf_csn&amp;amp;text=您好世界&amp;amp;speed=1&amp;amp;volume=50&amp;amp;audioType=wav 使用步骤
graph LR;选择声音 --&gt; 输入要转语音文本 --&gt; 拼接URL --&gt; 使用语音参数说明：
text 要转音频的文本内容 （200字以内） speed 语速 volume 声音大小 voiceId 发音类型可以取下面的值： VoiceId 名称 说明 qiumum_0gushi 精品秋木 活泼开朗适合有声读物等场景 kaolam_diantai 精品考拉 电台男声温柔的电台男声 juan1f 小美 客服女声声音甜美热情，客服、营销场景均适用 xmguof 婷婷 营销女声音色亲切大方，适用于电话销售、调研回访等场景 xmamif 小咪 营销女声活力甜美，适用于电话营销、邀约等场景 lunaif_ctn 晓健 标准粤语女声偏正式的标准粤语，适用于新闻播报等场景 hchunf_ctn 何春 自然粤语女声音色偏甜美自然，适用于家居播报等场景 dayaof_csd 大瑶 山东话女声音色偏甜美自然，适用于家居播报等场景 wqingf_csn 文卿 四川话女声音色偏甜美自然，适用于车载导航等场景 ppangf_csn 胖胖 四川话女声音色偏甜美自然，适用于家居播报等场景 yezi1f_csh 叶子 上海话女声音色偏甜美自然，适用于家居播报等场景 madoufp_yubo 麻豆 娱播女声甜美欢快的女声，适合做娱乐新闻的播报 madoufp_wenrou 麻豆 甜美温柔客服、营销、阅读听书的场景均可使用 xjingfp 小静 甜美女声音色甜美知性，可用于娱乐新闻等播报 xjingf_gushi 小静 自然音色甜美知性，可用于娱乐新闻等播报 xjingf 小静 商务知性音色甜美知性，可用于娱乐新闻等播报 zhilingfp 小玲 甜美女神音色亲切、欢快、自然，适合用于各种场景 zhilingfp_huankuai 小玲 欢快自然音色亲切、欢快、自然，适合用于各种场景 zhilingfa 小玲 标准小玲的音色亲切，甜美，自然，适合用于各种场景 zhilingf 传统小玲 甜美性感音色甜美、自然、性感，适合用于各种场景 anonyf 小佚 平和沉稳音色沉稳严肃，适合用于新闻播报等 xbekef 贝壳 可爱女童童真可爱，适合讲幼儿故事 xijunma 精品小军 新闻播报适合新闻播报等场景 xijunm 传统小军 标准正式标准发音，适合新闻播报等场景 geyou 葛爷 淡定风趣模仿葛优音色 gdgm 纲叔 沉稳幽默模仿郭德纲音色 zxcm 星哥 风趣幽默模仿周星驰音色 qianranf 传统然然 天真俏皮成人女声模仿女童音色 hyanif 小妮 温柔亲切适合情感电台播报等场景 gqlanf 标准小兰 邻家女声温柔的邻家女声，适合做客服音色 gqlanfp 精品小兰 温柔甜美温柔的邻家女声，适合做客服音色 qianranfa 标准然然 天真俏皮语速1.</description>
    </item>
    
    <item>
      <title>golang webserver with genergic base64 /favicon.ico</title>
      <link>https://czyt.tech/post/golang-web-server-add-base64-favicon/</link>
      <pubDate>Wed, 23 Feb 2022 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/golang-web-server-add-base64-favicon/</guid>
      <description>package main import ( &amp;#34;fmt&amp;#34; &amp;#34;net/http&amp;#34; ) func main() { http.HandleFunc(&amp;#34;/favicon.ico&amp;#34;, favicon) http.HandleFunc(&amp;#34;/&amp;#34;, hello) fmt.Printf(&amp;#34;listening on http://localhost:8000/\n&amp;#34;) http.ListenAndServe(&amp;#34;localhost:8000&amp;#34;, nil) } func favicon(w http.ResponseWriter, r *http.Request) { fmt.Printf(&amp;#34;%s\n&amp;#34;, r.RequestURI) w.Header().Set(&amp;#34;Content-Type&amp;#34;, &amp;#34;image/x-icon&amp;#34;) w.Header().Set(&amp;#34;Cache-Control&amp;#34;, &amp;#34;public, max-age=7776000&amp;#34;) fmt.Fprintln(w, &amp;#34;data:image/x-icon;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQEAYAAABPYyMiAAAABmJLR0T///////8JWPfcAAAACXBIWXMAAABIAAAASABGyWs+AAAAF0lEQVRIx2NgGAWjYBSMglEwCkbBSAcACBAAAeaR9cIAAAAASUVORK5CYII=\n&amp;#34;) } func hello(w http.ResponseWriter, r *http.Request) { fmt.Printf(&amp;#34;%s\n&amp;#34;, r.RequestURI) fmt.Fprintln(w, &amp;#34;Hello, World!&amp;#34;) } </description>
    </item>
    
    <item>
      <title>Golang嵌入可执行程序</title>
      <link>https://czyt.tech/post/golang-embed-executable-file/</link>
      <pubDate>Wed, 23 Feb 2022 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/golang-embed-executable-file/</guid>
      <description>reddit链接 On Linux it might be possible to use the memfd_create system call, but that&amp;rsquo;s not portable to other operating systems.
need go 1.16 +
package main import ( _ &amp;#34;embed&amp;#34; &amp;#34;log&amp;#34; &amp;#34;os&amp;#34; &amp;#34;os/exec&amp;#34; &amp;#34;strconv&amp;#34; &amp;#34;golang.org/x/sys/unix&amp;#34; ) //go:embed binary var embeddedBinary []byte func main() { fd, err := unix.MemfdCreate(&amp;#34;embedded_binary&amp;#34;, 0) if err != nil { log.Fatal(err) } path := &amp;#34;/proc/&amp;#34; + strconv.Itoa(os.Getpid()) + &amp;#34;/fd/&amp;#34; + strconv.Itoa(int(fd)) err = os.WriteFile(path, embeddedBinary, 0755) if err !</description>
    </item>
    
    <item>
      <title>Golang通过ssh连接数据库</title>
      <link>https://czyt.tech/post/go-connect-db-via-ssh/</link>
      <pubDate>Wed, 23 Feb 2022 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/go-connect-db-via-ssh/</guid>
      <description>Mysql Postgresql </description>
    </item>
    
    <item>
      <title>golang正则表达式小札</title>
      <link>https://czyt.tech/post/golang-regxp-notes/</link>
      <pubDate>Tue, 27 Jul 2021 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/golang-regxp-notes/</guid>
      <description>准备工作 golang正则需要引入包中的regexp包。
import ( &amp;#34;regexp&amp;#34; ) 如果需要复用正则表达式对象来提高性能，可以通过Compile() 或者 MustCompile()创建一个编译好的正则表达式对象。
支持的表达式 单个匹配:
. any character, possibly including newline (flag s=true)[xyz] character class[^xyz] negated character class\d Perl character class\D negated Perl character class[[:alpha:]] ASCII character class[[:^alpha:]] negated ASCII character class\pN Unicode character class (one-letter name)\p{Greek} Unicode character class\PN negated Unicode character class (one-letter name)\P{Greek} negated Unicode character class 组合匹配:
xy x followed by yx|y x or y (prefer x) 多次匹配:</description>
    </item>
    
    <item>
      <title>golang不创建临时文件上传网络文件</title>
      <link>https://czyt.tech/post/golang-upload-network-file-with-no-tmp-file/</link>
      <pubDate>Fri, 21 May 2021 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/golang-upload-network-file-with-no-tmp-file/</guid>
      <description>func UploadFromUrl(uploadUrl string, resUrl string,postFileName string, submitField string) error { method := &amp;#34;POST&amp;#34; payload := &amp;amp;bytes.Buffer{} writer := multipart.NewWriter(payload) if res, err := http.Get(resUrl); err != nil { return err } else { defer func() { if res != nil { _ = res.Body.Close() } }() part, _ := writer.CreateFormFile(submitField, postFileName) if _, copyErr := io.Copy(part, res.Body); copyErr != nil { return copyErr } if err := writer.Close(); err != nil { return err } } client := &amp;amp;http.</description>
    </item>
    
    <item>
      <title>golang检测网络连接是否关闭</title>
      <link>https://czyt.tech/post/golang-check-netconnection/</link>
      <pubDate>Thu, 11 Jun 2020 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/golang-check-netconnection/</guid>
      <description>_, err := conn.Read(make([]byte, 0)) if err!=io.EOF{ // this connection is invalid logger.W(&amp;#34;conn closed....&amp;#34;,err) }else{ byt, _:= ioutil.ReadAll(conn); } 注意：net: don&amp;rsquo;t return io.EOF from zero byte reads issue
参考
https://stackoverflow.com/questions/12741386/how-to-know-tcp-connection-is-closed-in-net-package</description>
    </item>
    
    <item>
      <title>golang使用官方库实现i18n</title>
      <link>https://czyt.tech/post/golang-impl-i18n-with-standard-lib/</link>
      <pubDate>Wed, 10 Jun 2020 00:00:00 +0000</pubDate>
      
      <guid>https://czyt.tech/post/golang-impl-i18n-with-standard-lib/</guid>
      <description>示例 package main import ( &amp;#34;fmt&amp;#34; &amp;#34;golang.org/x/text/language&amp;#34; &amp;#34;golang.org/x/text/message&amp;#34; &amp;#34;golang.org/x/text/message/catalog&amp;#34; ) func main() { builder := catalog.NewBuilder() chTag:=language.Make(&amp;#34;zh_Hans&amp;#34;) engTag:=language.Make(&amp;#34;en&amp;#34;) builder.SetString(chTag,&amp;#34;hello&amp;#34;,&amp;#34;您好&amp;#34;) builder.SetString(engTag,&amp;#34;hello&amp;#34;,&amp;#34;Hello&amp;#34;) fmt.Println(builder.Languages()) option := message.Catalog(builder) p := message.NewPrinter(chTag,option) p.Printf(&amp;#34;hello&amp;#34;) p2 := message.NewPrinter(engTag,option) p2.Printf(&amp;#34;hello&amp;#34;) } 参考 https://zyfdegh.github.io/post/201805-translation-go-i18n https://www.alexedwards.net/blog/i18n-managing-translations https://phrase.com/blog/posts/internationalisation-in-go-with-go-i18n/ https://lokalise.com/blog/go-internationalization-using-go-i18n/ https://go.googlesource.com/proposal/+/master/design/12750-localization.md </description>
    </item>
    
  </channel>
</rss>
