你好,欢迎来到我的博客 👋

记录技术探索、工程实践与个人成长。

AI对话-gitignore用法

Git 忽略 conf/conf.ini 未生效问题排查与修复指引 背景/症状 你在 .gitignore 中已添加了 conf/conf.ini 的忽略规则,但 git status 仍显示该文件有变更。 根因 .gitignore 只对“未被跟踪”的文件生效。conf/conf.ini 之前已经被提交(被 Git 索引跟踪),因此忽略规则对它不起作用。 快速诊断 查看 .gitignore 中确有规则(多处重复无碍但冗余) 确认文件已被跟踪: git ls-files conf/conf.ini 若输出包含 `conf/conf.ini`,说明该文件已被跟踪。 - 当前状态: ```bash git status --porcelain 会看到该文件被标记为修改(如 M conf/conf.ini)。 解决步骤 从 Git 索引中移除该文件,但保留本地文件: git rm –cached conf/conf.ini 2. 之后 `.gitignore` 的忽略规则将开始生效。 #### 验证 - 再次查看状态: ```bash git status 会看到 deleted: conf/conf.ini 作为待提交变更(这表示从版本库删除,但不会删除你本地工作区文件)。 提交变更(可选,但推荐) 提交索引移除操作,让团队成员也不再跟踪该文件: git commit -m “chore: stop tracking conf/conf.ini and respect .gitignore” ...

August 11, 2025 · 2 min · cyp

AI对话-边车模式和服务网格

服务网格和边车模式什么意思? 边车模式(Sidecar Pattern) 将日志、流量控制、服务注册、熔断限流等“控制类”能力,从业务进程中剥离到独立的边车进程/容器,与主服务同生命周期运行。 好处:业务与控制解耦,主服务只写业务逻辑。 服务网格(Service Mesh) 在大规模微服务中,为每个服务配一个边车代理,所有边车组成网状网络。 数据平面:各个 sidecar 处理转发、限流、熔断、TLS、可观测性等。 控制平面:集中下发策略与配置,统一路由、限流、流量治理等。 对应用零侵入,开发只写业务。 一句话:边车模式是“给每个服务配助手”,服务网格是“让所有助手组成智能网络”。 在 Go 后端服务里,边车模式怎么和业务代码工作?需要开放统一端口吗? 典型方式:主服务监听本地端口(如 :8080),sidecar 作为反向代理监听对外端口(如 :8081),两者通过 localhost 通信。 Go 主服务仅需像平时一样启动 HTTP 服务,不需要关心认证、限流、日志等控制逻辑。 示例(主服务,仅处理业务): package main import ( "log" "net/http" ) func main() { mux := http.NewServeMux() mux.HandleFunc("/ping", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("pong")) }) log.Println("app listening on :8080") http.ListenAndServe(":8080", mux) } 示例(sidecar,反向代理到主服务): package main import ( "net/http" "net/http/httputil" "net/url" ) func main() { target, _ := url.Parse("http://127.0.0.1:8080") proxy := httputil.NewSingleHostReverseProxy(target) http.ListenAndServe(":8081", proxy) } 在 Kubernetes 中,二者位于同一 Pod,共享网络命名空间,sidecar 直接转发到 127.0.0.1:8080。 使用服务网格(如 Istio)时,Envoy 会自动作为 sidecar 注入并接管流量,Go 服务只需监听本地端口。 8080 是跟 sidecar 约定的吗?如果没有约定端口,sidecar 怎么跟 Go 服务通信? 不是“天然约定”,而是部署时显式声明。常见方式: ...

August 11, 2025 · 4 min · cyp

Go singleflight 源码分析

User 这是什么原因 Cursor 我需要查看当前打开的文件内容以及相关的错误信息来帮助您诊断问题。让我先检查一下您当前正在查看的文件。 我看到您的光标在第73行,这是一个panic错误处理的位置。让我检查一下是否有任何编译错误或运行时错误信息。 让我检查一下项目的构建状态和可能的错误: User 翻一下 Cursor 我看到您在查看 singleflight 包的代码。让我帮您翻译一下您选中的这段注释: // Do executes and returns the results of the given function, making // sure that only one execution is in-flight for a given key at a // time. If a duplicate comes in, the duplicate caller waits for the // original to complete and receives the same results. // The return value shared indicates whether v was given to multiple callers. 中文翻译: ...

August 7, 2025 · 21 min · cyp

Go 内存分配、逃逸分析与优化机制详解

1. interface{} 的类型断言与底层实现 1.1 类型断言的语法和用途 input.(type) 只能用于 type switch 语句中,用于判断 interface{} 变量的实际类型,并做类型分支处理。 例如: var input interface{} = 123 switch v := input.(type) { case int: // v 是 int 类型 case string: // v 是 string 类型 } 1.2 interface{} 的底层结构 interface{} 在 Go 底层实现为一个结构体,包含两个指针: _type:指向类型元数据(类型描述信息) data:指向实际数据的指针 type eface struct { _type *_type data unsafe.Pointer } 1.3 类型断言的底层实现 当你写 input.(type) 或 input.(SomeType) 时,Go 运行时会: 读取 interface{} 变量的 _type 指针。 将其与 case 分支中的类型元数据做比较。 匹配则进入对应分支,并将 data 指针转换为目标类型。 不匹配则继续下一个 case。 相关源码在 Go 的 runtime 包(如 iface.go)中,类型断言的核心函数有 runtime.assertE2I、runtime.assertE2T 等。 1.4 性能影响 类型断言的性能损耗极小,通常只涉及指针比较和类型表查找。 只有在极端高频调用下才可能成为瓶颈,绝大多数业务场景可以放心使用。 2. interface{} 数据的存储位置 2.1 interface{} 变量本身 interface{} 变量本身(即 eface 结构体)通常分配在栈上。 2.2 interface{} 指向的数据 interface{} 指向的数据,可能分配在栈上,也可能分配在堆上,由逃逸分析决定。 逃逸分析会根据变量的生命周期和使用方式,自动决定分配位置。 2.3 影响逃逸的常见场景 如果 interface{} 指向的数据只在当前函数内使用,且没有被返回或跨 goroutine 传递,通常会分配在栈上。 如果 interface{} 指向的数据被返回、传递到其他 goroutine、或生命周期不明确,则会分配到堆上。 3. 逃逸分析与分配规则 3.1 逃逸分析的作用 Go 编译器通过逃逸分析(escape analysis)判断变量是否需要分配到堆上。 逃逸分析的目标是尽量减少堆分配,提高程序性能。 3.2 逃逸分析的常见规则 struct 返回值:大概率逃逸到堆上,尤其是大 struct 或返回指针时,但有优化空间(如返回值优化)。 普通类型返回值:如 int、float、bool 等,通常分配在栈上,除非返回的是指针。 interface{} 返回值:即使是普通类型,也可能逃逸到堆上,因为 interface{} 需要存储类型信息和数据指针,编译器有时会保守处理。 3.3 逃逸分析的命令 你可以用如下命令查看逃逸分析结果: ...

April 27, 2025 · 2 min · cyp