Ent Go 框架谓词(Predicates)完全指南:字段过滤、边查询、自定义 SQL 与 JSON 谓词实战
Ent Go 框架谓词Predicates完全指南字段过滤、边查询、自定义 SQL 与 JSON 谓词实战【免费下载链接】entAn entity framework for Go项目地址: https://gitcode.com/gh_mirrors/en/entEnt 是面向 Go 的实体框架Entity Framework其生成的查询 API 通过谓词Predicates提供类型安全、可组合的过滤能力。本文以官方文档 doc/md/predicates.md 为骨架深入拆解 Ent 谓词体系从字段谓词、边谓词到 NOT / OR / AND 逻辑组合再到可完全掌控 SQL 的自定义谓词与官方sqljson包提供的 JSON 列查询能力。读完本文你将能够熟练编写从简单等值过滤到复杂子查询、JSON 路径匹配在内的各类 Ent 查询并理解其底层的 SQL 生成原理。字段谓词Field PredicatesEnt 为每种字段类型生成对应的谓词函数调用方式是Type.FieldOp(value)例如user.NameEQ(a8m)、pet.AgeGT(3)。谓词函数接受一个或多个参数返回一个可用于Where(...)的谓词值。不同类型的字段支持的谓词由代码生成器按类型严格裁剪其操作符集合定义在 entc/gen/predicate.go 中const ( EQ Op iota // NEQ // GT // GTE // LT // LTE // IsNil // IS NULL / has NotNil // IS NOT NULL / hasNot In // within NotIn // without EqualFold // equals case-insensitive Contains // containing ContainsFold // containing case-insensitive HasPrefix // startingWith HasSuffix // endingWith )同一文件中还定义了各类型可用的操作符集合entc/gen/predicate.goboolOps []Op{EQ, NEQ} enumOps append(boolOps, In, NotIn) numericOps append(enumOps, GT, GTE, LT, LTE) stringOps append(numericOps, Contains, HasPrefix, HasSuffix) nillableOps []Op{IsNil, NotNil}由此可以得出各字段类型的完整谓词能力矩阵字段类型支持的谓词Bool,!即EQ/NEQNumericint、float 等,!,,,,以及IN,NOT INTime,!,,,,以及IN,NOT INString,!,,,,IN,NOT INContains,HasPrefix,HasSuffixContainsFold,EqualFold为SQL 方言专属大小写不敏感匹配JSON,!嵌套值JSON path上的,!,,,,与ContainsHasKey,LenP嵌套值的null检查详见下文 JSON 谓词一节Optional可空字段IsNil,NotNil对应 SQL 的IS NULL/IS NOT NULL说明IN与NOT IN是变参操作符Variadic接受一个值列表IsNil/NotNil是零参操作符Niladic无需传值。代码生成模板 entc/gen/template/dialect/sql/predicate.tmpl 会根据这两个特性决定生成调用时的参数形态如ids...展开。使用示例// 等值与比较 client.User.Query().Where(user.NameEQ(a8m)).All(ctx) client.Pet.Query().Where(pet.AgeGT(3), pet.AgeLTE(10)).All(ctx) // 集合匹配 client.User.Query().Where(user.IDIn(1, 2, 3)).All(ctx) client.User.Query().Where(user.NameNotIn(a8m, foo)).All(ctx) // 字符串模式 client.Pet.Query().Where(pet.NameContains(ri)).All(ctx) client.Pet.Query().Where(pet.NameHasPrefix(Ari)).All(ctx) client.Pet.Query().Where(pet.NameHasSuffix(a)).All(ctx) // 可空字段 client.User.Query().Where(user.PhoneIsNil()).All(ctx) client.User.Query().Where(user.PhoneNotNil()).All(ctx)其中In/NotIn的空参数列表被底层 dialect/sql/builder.go 特殊处理In无参数时生成FALSE常量NotIn无参数时生成NOT FALSE避免产生非法 SQLIN ()。边谓词Edge Predicates边谓词用于按关联关系过滤查询是 Ent 图遍历能力的核心入口其模板实现位于 entc/gen/template/dialect/sql/predicate.tmpl。HasEdgeHasEdge检查实体是否存在某条关联边。例如对Pet类型的名为owner的边查询所有有主人的宠物client.Pet. Query(). Where(pet.HasOwner()). All(ctx)从底层实现看HasOwner()会构建一个sqlgraph.Step并调用sqlgraph.HasNeighbors见 dialect/sql/sqlgraph/graph.go。根据边的关系类型HasNeighbors会生成不同的 SQL多对多边通过中间表生成IN (SELECT ...)子查询反向单边检查外键列是否为NOT NULL正向单边生成EXISTS (SELECT ...)子查询。HasEdgeWithHasEdgeWith在HasEdge基础上允许对边的另一端实体追加谓词过滤。例如查询主人名为a8m的所有宠物client.Pet. Query(). Where(pet.HasOwnerWith(user.Name(a8m))). All(ctx)HasEdgeWith会调用sqlgraph.HasNeighborsWith见 dialect/sql/sqlgraph/graph.go把传入的谓词应用到邻居表的Selector上再通过IN子查询或EXISTS组合进主查询。HasEdgeWith支持传入多个谓词它们之间是 AND 关系。逻辑组合否定NOT、析取OR与合取ANDWhere接受多个谓词时默认按 AND 组合但 Ent 还提供了显式的逻辑组合函数用于表达更复杂的布尔条件。否定 NOTclient.Pet. Query(). Where(pet.Not(pet.NameHasPrefix(Ari))). All(ctx)pet.Not将内部谓词取反等价于 SQL 的NOT (...)。它同样可以包裹pet.Or(...)、pet.And(...)等组合谓词。析取 ORclient.Pet. Query(). Where( pet.Or( pet.HasOwner(), pet.Not(pet.HasFriends()), ) ). All(ctx)pet.Or接收多个谓词任一为真即匹配等价于(... OR ...)。合取 ANDclient.Pet. Query(). Where( pet.And( pet.HasOwner(), pet.Not(pet.HasFriends()), ) ). All(ctx)pet.And要求所有谓词同时为真等价于(... AND ...)。底层通过 dialect/sql/builder.go 的Or/And实现组合谓词会用括号包裹以避免运算符优先级问题。三种逻辑组合可以任意嵌套例如pet.Or(pet.And(pet.HasOwner(), pet.AgeGT(2)), pet.Not(pet.HasFriends()))。自定义谓词Custom Predicates当生成的标准谓词无法满足需求——例如需要编写方言专属逻辑或完全控制生成的查询时Ent 允许通过Where(func(s *sql.Selector) { ... })传入一个操作sql.Selector的闭包。这是整个谓词体系中最强大也最灵活的入口sql.Selector的完整 API 定义在 dialect/sql/builder.go 中。示例 1按 ID 列表过滤IN 子句获取用户 1、2、3 的宠物pets : client.Pet. Query(). Where(func(s *sql.Selector) { s.Where(sql.InInts(pet.FieldOwnerID, 1, 2, 3)) }). AllX(ctx)sql.InInts是IN谓词的 int 专用版本见 dialect/sql/builder.go。上述代码生成的 SQLSELECT DISTINCT pets.id, pets.owner_id FROM pets WHERE owner_id IN (1, 2, 3)示例 2JSON 字段路径检查统计URL字段包含Scheme键的用户数count : client.User. Query(). Where(func(s *sql.Selector) { s.Where(sqljson.HasKey(user.FieldURL, sqljson.Path(Scheme))) }). CountX(ctx)生成的 SQL 按方言不同而不同-- PostgreSQL SELECT COUNT(DISTINCT users.id) FROM users WHERE url-Scheme IS NOT NULL -- SQLite 和 MySQL SELECT COUNT(DISTINCT users.id) FROM users WHERE JSON_EXTRACT(url, $.Scheme) IS NOT NULL方言差异由sqljson.HasKey内部实现见 dialect/sql/sqljson/sqljson.goPostgreSQL 使用-操作符MySQL/SQLite 使用JSON_EXTRACTSQLite 实际用JSON_TYPE判断非 NULL。示例 3关联子查询的三种等价写法查询所有拥有Tesla汽车的用户的普通 Ent 写法users : client.User.Query(). Where(user.HasCarWith(car.Model(Tesla))). AllX(ctx)该查询可以用IN、JOIN、EXISTS三种 SQL 形式等价重写// IN 版本。 users : client.User.Query(). Where(func(s *sql.Selector) { t : sql.Table(car.Table) s.Where( sql.In( s.C(user.FieldID), sql.Select(t.C(user.FieldID)).From(t).Where(sql.EQ(t.C(car.FieldModel), Tesla)), ), ) }). AllX(ctx) // JOIN 版本。 users : client.User.Query(). Where(func(s *sql.Selector) { t : sql.Table(car.Table) s.Join(t).On(s.C(user.FieldID), t.C(car.FieldOwnerID)) s.Where(sql.EQ(t.C(car.FieldModel), Tesla)) }). AllX(ctx) // EXISTS 版本。 users : client.User.Query(). Where(func(s *sql.Selector) { t : sql.Table(car.Table) p : sql.And( sql.EQ(t.C(car.FieldModel), Tesla), sql.ColumnsEQ(s.C(user.FieldID), t.C(car.FieldOwnerID)), ) s.Where(sql.Exists(sql.Select().From(t).Where(p))) }). AllX(ctx)三者生成等价结果的 SQL-- IN 版本。 SELECT DISTINCT users.id, users.age, users.name FROM users WHERE users.id IN (SELECT cars.owner_id FROM cars WHERE cars.model Tesla) -- JOIN 版本。 SELECT DISTINCT users.id, users.age, users.name FROM users JOIN cars ON users.id cars.owner_id WHERE cars.model Tesla -- EXISTS 版本。 SELECT DISTINCT users.id, users.age, users.name FROM users WHERE EXISTS (SELECT * FROM cars WHERE cars.model Tesla AND users.id cars.owner_id)EXISTS版本中使用的sql.Exists/sql.NotExists实现位于 dialect/sql/builder.go。三种写法在语义上等价实际选择取决于表大小、索引与优化器行为。示例 4自定义 LIKE 模式生成代码提供了HasPrefix、HasSuffix、Contains、ContainsFold谓词但如果需要LIKE运算符的自定义模式如通配符_、%可以这样做pets : client.Pet.Query(). Where(func(s *sql.Selector){ s.Where(sql.Like(pet.Name, _B%)) }). AllX(ctx)sql.Like实现见 dialect/sql/builder.go。生成的 SQLSELECT DISTINCT pets.id, pets.owner_id, pets.name, pets.age, pets.species FROM pets WHERE name LIKE _B%示例 5使用内置 SQL 函数DATE 等需要使用DATE()等内置 SQL 函数时有两种方式方式 1方言感知的谓词函数sql.Pusers : client.User.Query(). Select(user.FieldID). Where(func(s *sql.Selector) { s.Where(sql.P(func(b *sql.Builder) { b.WriteString(DATE().Ident(last_login_at).WriteByte()).WriteOp(OpGTE).Arg(value) })) }). AllX(ctx)生成的 SQLSELECT id FROM users WHERE DATE(last_login_at) ?方式 2内联表达式sql.ExprPusers : client.User.Query(). Select(user.FieldID). Where(func(s *sql.Selector) { s.Where(sql.ExprP(DATE(last_login_at) ?, value)) }). AllX(ctx)生成的 SQL 相同SELECT id FROM users WHERE DATE(last_login_at) ?sql.P与sql.ExprP均定义于 dialect/sql/builder.gosql.P接受一个操作sql.Builder的闭包可在闭包内使用WriteString、Ident、WriteOp、Arg等构建方法按方言拼接任意表达式sql.ExprP则直接接收一个带?占位符的表达式字符串与参数列表。前者更灵活可按方言分支后者更简洁。JSON 谓词sqljson 包JSON 谓词不会作为代码生成的一部分默认生成。Ent 提供了官方包sqljson源码位于 dialect/sql/sqljson/sqljson.go用于配合上文的自定义谓词能力对 JSON 列进行查询。使用时将返回的*sql.Predicate传给s.Where(...)即可。比较 JSON 值sqljson.ValueEQ(user.FieldData, data) sqljson.ValueEQ(user.FieldURL, https, sqljson.Path(Scheme)) sqljson.ValueNEQ(user.FieldData, content, sqljson.DotPath(attributes[1].body.content)) sqljson.ValueGTE(user.FieldData, status.StatusBadRequest, sqljson.Path(response, status))ValueEQ/ValueNEQ/ValueGT/ValueGTE/ValueLT/ValueLTE分别对应、!、、、、比较。Path按段指定 JSON 路径DotPath则接受a.b[2].c形式的点分字符串解析器ParsePath见 dialect/sql/sqljson/sqljson.go支持引号、数组索引等。对 PostgreSQL比较非字符串参数时会自动附加类型转换如Cast(int)、Cast(bool)以避免 missing type casts 错误这是normalizePG函数dialect/sql/sqljson/sqljson.go的职责。检查 JSON 键是否存在sqljson.HasKey(user.FieldData, sqljson.Path(attributes, [1], body)) sqljson.HasKey(user.FieldData, sqljson.DotPath(attributes[1].body))注意值为null字面量的键也会匹配该操作HasKey判定的是键存在且非 NULL。检查 JSONnull字面量sqljson.ValueIsNull(user.FieldData) sqljson.ValueIsNull(user.FieldData, sqljson.Path(attributes)) sqljson.ValueIsNull(user.FieldData, sqljson.DotPath(attributes[1].body))注意ValueIsNull仅在值是JSONnull字面量时返回 true而不是数据库NULL。若需检查数据库 NULL 或键是否存在应使用sql.IsNull或sqljson.HasKey见 dialect/sql/sqljson/sqljson.go 的实现说明。比较 JSON 数组长度sqljson.LenEQ(user.FieldAttrs, 2) sql.Or( sqljson.LenGT(user.FieldData, 10, sqljson.Path(attributes)), sqljson.LenLT(user.FieldData, 20, sqljson.Path(attributes)), )长度谓词族包括LenEQ、LenNEQ、LenGT、LenGTE、LenLT、LenLTE见 dialect/sql/sqljson/sqljson.go。底层按方言生成JSONB_ARRAY_LENGTHPostgreSQL、JSON_LENGTHMySQL或JSON_ARRAY_LENGTHSQLite。sqljson还提供OrderLen/OrderLenDesc按 JSON 长度排序以及ValuePath/OrderValue按 JSON 值排序的辅助函数。检查 JSON 值包含另一个值sqljson.ValueContains(user.FieldData, data) sqljson.ValueContains(user.FieldData, attrs, sqljson.Path(attributes)) sqljson.ValueContains(user.FieldData, code, sqljson.DotPath(attributes[0].status_code))实现见 dialect/sql/sqljson/sqljson.goMySQL 生成JSON_CONTAINS(...)PostgreSQL 生成包含操作符SQLite 则通过JSON_EACH展开后做等值匹配。检查 JSON 字符串的前缀、后缀与子串sqljson.StringContains(user.FieldURL, github, sqljson.Path(host)) sqljson.StringHasSuffix(user.FieldURL, .com, sqljson.Path(host)) sqljson.StringHasPrefix(user.FieldData, 20, sqljson.DotPath(attributes[0].status_code))这三个函数内部会自动附加Unquote(true)选项去除 JSON 字符串的引号后再做模式匹配见 dialect/sql/sqljson/sqljson.go。检查 JSON 值是否属于列表sqljson.ValueIn(user.FieldURL, []any{https, ftp}, sqljson.Path(Scheme)) sqljson.ValueNotIn(user.FieldURL, []any{github, gitlab}, sqljson.Path(Host))ValueNotIn在参数为空时退化为sql.NotIn(column)见 dialect/sql/sqljson/sqljson.go若参数全是字符串会自动附加Unquote(true)。字段间比较Comparing Fieldsdialect/sql包还提供一组字段与字段比较的函数用于比较同一行内两个字段列的大小关系而不是与常量比较。这些函数定义在 dialect/sql/sql.go 中。client.Order.Query(). Where( sql.FieldsEQ(order.FieldTotal, order.FieldTax), sql.FieldsNEQ(order.FieldTotal, order.FieldDiscount), ). All(ctx) client.Order.Query(). Where( order.Or( sql.FieldsGT(order.FieldTotal, order.FieldTax), sql.FieldsLT(order.FieldTotal, order.FieldDiscount), ), ). All(ctx)完整的字段间比较函数族包括FieldsEQ、FieldsNEQ、FieldsGT、FieldsGTE、FieldsLT、FieldsLTE以及FieldsHasPrefix、FieldsHasSuffix、FieldsContains、FieldsContainsFold、FieldsEqualFold等字符串变体。它们底层复用sql.ColumnsEQ、sql.ColumnsGT等列间比较谓词见 dialect/sql/builder.go 的ColumnsOp并可通过sql.FieldsEQ(...)与order.Or(...)/order.And(...)组合嵌套。注意这些函数返回的是func(*Selector)可直接作为Where的参数。谓词与代码生成的关系理解谓词体系后可以顺带理清其与代码生成的联系每个实体类型如User、Pet的谓词常量user.FieldName、pet.FieldOwnerID等与谓词函数pet.NameHasPrefix、pet.HasOwner都由entc代码生成器产出模板位于 entc/gen/template/dialect/sql/predicate.tmpl 与 entc/gen/template/dialect/sql/where.tmpl。标准字段谓词最终映射为sql.FieldEQ、sql.FieldGT等底层函数dialect/sql/sql.go而边谓词映射为sqlgraph.HasNeighbors/sqlgraph.HasNeighborsWithdialect/sql/sqlgraph/graph.go。pet.And、pet.Or、pet.Not由模板生成时引用sql.AndPredicates、sql.OrPredicates、sql.NotPredicates见 entc/gen/template/dialect/sql/predicate.tmpl。因此无论是使用生成的类型安全谓词还是直接操作sql.Selector编写自定义 SQL 逻辑最终都汇聚到dialect/sql与dialect/sql/sqlgraph这两个底层包这也是 Ent 谓词 API 既保持类型安全、又能完整下探到原生 SQL 的原因所在。更多谓词与查询的配套用法分页、聚合、遍历等可进一步参考仓库中的 doc/md/crud.mdx、doc/md/paging.mdx 与 doc/md/predicates.md 原文。【免费下载链接】entAn entity framework for Go项目地址: https://gitcode.com/gh_mirrors/en/ent创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

AI辅助前端编码效率提升指南:从提示词工程到AI Agent实践

AI辅助前端编码效率提升指南:从提示词工程到AI Agent实践

写前端代码这些年,我最早接触AI辅助编码的时候,心态特别朴素——“帮我写个登录页”“帮我写个轮播图”,复制粘贴,跑不通再问一把,能用就行。后来真正把AI用出效率,是在某个版本迭代压力很大的阶段&#xf…

2026/9/23 10:11:34 阅读更多 →
在 Linux CPU 环境下从源码构建并安装 MXNet R 语言绑定:`make rpkg` 完整指南

在 Linux CPU 环境下从源码构建并安装 MXNet R 语言绑定:`make rpkg` 完整指南

深度学习机器学习人工智能 【免费下载链接】mxnet Lightweight, Portable, Flexible Distributed/Mobile Deep Learning with Dynamic, Mutation-aware Dataflow Dep Scheduler; for Python, R, Julia, Scala, Go, Javascript and more 项目地址: https://gitcode.c…

2026/9/24 1:23:42 阅读更多 →
Nomad 插件启动器(nomad-plugin-launcher)使用指南:直接交互与可视化设备插件数据

Nomad 插件启动器(nomad-plugin-launcher)使用指南:直接交互与可视化设备插件数据

Nomad 插件启动器(nomad-plugin-launcher)使用指南:直接交互与可视化设备插件数据 【免费下载链接】nomad Nomad is an easy-to-use, flexible, and performant workload orchestrator that can deploy a mix of microservice, batch, contai…

2026/9/24 2:19:55 阅读更多 →

最新新闻

从 Codex CLI 到知识库:TaoToken 统一 Key 驱动的 AI 代理个人知识管理全流程

从 Codex CLI 到知识库:TaoToken 统一 Key 驱动的 AI 代理个人知识管理全流程

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

2026/9/25 4:58:52 阅读更多 →
Python寒假作业实战指南:从环境搭建到代码调试全流程

Python寒假作业实战指南:从环境搭建到代码调试全流程

拿到“Python第一次作业(寒假)”这个标题,我第一反应是想起自己当年第一次提交Python作业的样子——表面上是写几段代码,实际上一大半时间都耗在装环境、调报错、纠结“为什么输出和我想要的不一样”上面。这篇文章就是给同样在寒…

2026/9/25 4:58:52 阅读更多 →
STM32 I2C CubeMX配置四大致命陷阱与信号完整性避坑指南

STM32 I2C CubeMX配置四大致命陷阱与信号完整性避坑指南

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

2026/9/25 4:58:52 阅读更多 →
树莓派4B变身AI牛马:8GB内存跑本地大模型的实践与避坑指南

树莓派4B变身AI牛马:8GB内存跑本地大模型的实践与避坑指南

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

2026/9/25 4:58:52 阅读更多 →
OpenClaw驱动SolidWorks二次开发:自然语言建模与自动化导出实战

OpenClaw驱动SolidWorks二次开发:自然语言建模与自动化导出实战

最近我把 OpenClaw 这个本地 AI Agent 框架和 SolidWorks 的二次开发链路打通了,现在能做到用自然语言直接驱动一部分建模、改参和导出操作。这套组合的定位不是拿 AI 替代 CAD 软件,而是让 AI 当“一个能听懂人话的调度员”,把重复的 API 调…

2026/9/25 4:58:52 阅读更多 →
深入理解 Sinon 的 `spyCall.firstArg`:读取单次调用首个参数的正确姿势

深入理解 Sinon 的 `spyCall.firstArg`:读取单次调用首个参数的正确姿势

测试开发工具 【免费下载链接】sinon Test spies, stubs and mocks for JavaScript. 项目地址: https://gitcode.com/gh_mirrors/si/sinon 点击查看 免费下载 spyCall.firstArg 是 Sinon 中 spy call 对象的一个核心只读属性,用于获取某一次函数调用传入…

2026/9/25 4:57:52 阅读更多 →

日新闻

AI元人文:从工具使用到思维重构的深度探索

AI元人文:从工具使用到思维重构的深度探索

最近半年我一直在琢磨一件事:AI元人文到底是什么?说白了,就是“用元视角重新审视人与AI的关系”,也在“探索AI如何反向逼着我们发现自己的思考边界”。标题里的“元探索”,在我看就是一层套一层的追问——当你用AI解决…

2026/9/25 0:00:41 阅读更多 →
Python+CNN车牌识别实战:从数据预处理到模型训练与部署

Python+CNN车牌识别实战:从数据预处理到模型训练与部署

简介:基于Python与卷积神经网络的车牌识别项目,面向计算机视觉初学者及智能交通开发者,目标是帮助用户掌握从数据预处理、模型构建到实际部署的完整流程。压缩包共25个文件,包含jpg/png图像样本、py训练脚本、md说明文档、dat数据…

2026/9/25 0:00:41 阅读更多 →
Vim基础操作全攻略:保存退出、模式切换与高频命令实战

Vim基础操作全攻略:保存退出、模式切换与高频命令实战

1. 项目概述1.1 核心需求解析今天聊聊Vim。写这个题目的原因是:几乎每个后端开发者、运维人员、数据工程师某天都会遇到一个场景——深夜加班,服务器登录界面只有黑底白字,编辑器只有vi/vim,你必须在五分钟内完成一次配置修改并保…

2026/9/25 0:00:41 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/24 14:34:13 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/24 9:10:42 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/24 14:33:56 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/24 12:50:34 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/24 14:33:48 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/24 12:49:17 阅读更多 →