作者: ianzhi

  • Go并发编程精讲:goroutine/channel原理与避坑指南

    Go并发编程精讲:goroutine/channel原理与避坑指南

    深入理解 GMP 调度模型

    Go 运行时调度器将 goroutine 映射到 OS 线程上执行,GMP 代表 G(Goroutine)、M(Machine/OS 线程)、P(Processor,执行上下文)。P 的数量默认等于 CPU 核心数,可以通过 GOMAXPROCS 调整,这是 Go 并发性能的关键参数。

    goroutine 的生命周期与状态

    goroutine 有多个状态:waiting(阻塞在 channel 或系统调用)、runnable(就绪等待调度)、running(正在执行)。理解这些状态有助于分析死锁和性能问题。

    channel 的底层实现

    channel 内部有环形队列和两个等待队列(sendq 和 recvq)。向已满的无缓冲 channel 发送会阻塞,goroutine 被挂在 sendq 上;接收时会从 recvq 唤醒一个 sender 或从队列取数据。

    常见并发陷阱

    • 向已关闭的 channel 发送数据会 panic,但接收会返回零值
    • 多个 goroutine 同时等待同一个 channel,只有 1 个会被唤醒——用 sync.WaitGroup 而非 channel 控制退出
    • for range channel 会一直阻塞直到 channel 关闭
    • context.WithCancel 是优雅退出多个 goroutine 的标准方式

    小结

    理解 GMP 调度和 channel 底层原理,才能真正写出高效的并发代码。遇到性能问题时,用 runtime.NumGoroutine() 和 pprof 分析 goroutine 的状态分布是第一步。

    来源:https://www.dnote.cn

  • 从利润表到现金流:拆解一家公司到底赚不赚钱

    从利润表到现金流:拆解一家公司到底赚不赚钱

    净利润是最容易被操纵的数字

    利润表(Income Statement)上的净利润,是按照权责发生制编制的——卖出商品就算收入,不看钱有没有到账。这意味着可以通过应收款虚增收入、通过会计估计调整来平滑利润。读懂净利润背后的故事,才是财报分析的核心。

    两个核心比率

    第一个是「经营现金流/净利润」比率(盈利质量比率)。正常公司这个比率应该大于 1,说明净利润都有真实的现金支撑。长期低于 0.8 的公司需要警惕。

    第二个是「收现比」:销售商品、提供劳务收到的现金 / 营业收入。这个比率反映每 1 元收入实际收到了多少现金。低于 0.8 说明大量收入停留在应收款里。

    案例:某消费电子公司

    某公司连续三年净利润增速超过 30%,但经营现金流持续为负。深入一看:应收账款从 10 亿增长到 40 亿——原来是通过给经销商大量赊账来「制造」收入增长。这种高增长是危险的,一旦渠道去库存,收入会断崖式下跌。

    如何用自由现金流估值

    DCF 估值本质上是对未来自由现金流的折现。计算公式:自由现金流 = 经营现金流 – 维持性资本支出。简化版可以用「经营现金流净额 × 80%(保守估算资本支出)」来估算。

    小结

    利润是会计游戏,现金流是商业现实。读财报时,永远把现金流量表放在和利润表同等重要的位置。两表对照,才能看清一家公司真正的赚钱能力。

    来源:https://www.dnote.cn

  • 用 Taro 开发小程序:答题卡网格布局的兼容性问题总结

    用 Taro 开发小程序:答题卡网格布局的兼容性问题总结

    背景

    在做一个刷题小程序时,需要实现一个答题卡界面——用网格展示所有题目状态(未答/已答/当前题),支持点击跳转。在 Web 上几行 CSS 搞定,在小程序里却踩了不少坑。

    问题一:gap 属性在小程序里不生效

    这是最常见的问题。CSS gap 属性用于设置网格/弹性盒子的间距,在主流浏览器都支持,但在微信小程序、支付宝小程序里均不支持。解决方案:

    /* ❌ 小程序不支持 */
    .grid { display: grid; gap: 16px; }
    
    /* ✅ 改用 margin 模拟 */
    .grid { display: grid; }
    .grid-item { margin-right: 16px; margin-bottom: 16px; }
    /* 最后一项去掉右边距 */
    .grid-item:last-child { margin-right: 0; }

    问题二:display: grid 在某些机型的兼容情况

    iOS 微信大部分版本支持 grid,但 Android 端部分机型(尤其是低端机)的 UC/QQ 浏览器内核不支持。推荐降级方案:用 flex + 百分比宽度实现网格。

    /* ✅ 兼容写法:flex 模拟网格 */
    .row { display: flex; flex-wrap: wrap; }
    .cell { width: 48px; height: 48px; margin: 0 4px 8px 0; }

    问题三::nth-child 在某些场景下失效

    nth-child 在动态列表(数据来自接口)时表现正常,但在用 v-for 遍历固定数量的数字时,微信开发者工具和部分真机行为不一致。解决方案是改用 v-if 或加辅助 class。

    实战答题卡组件代码

    const AnswerCard = ({ questions, currentIndex, onJump }) => {
      return (
        <View className='answer-card'>
          <View className='row'>
            {questions.map((q, i) => (
              <View
                key={q.id}
                className={`cell ${i === currentIndex ? 'current' : ''} ${q.answered ? 'done' : 'undone'}`}
                onClick={() => onJump(i)}
              >
                {i + 1}
              </View>
            ))}
          </View>
        </View>
      )
    }

    小结

    小程序开发的本质是与 CSS 兼容层打交道。遇到 display、gap、nth-child 等属性,先查 caniuse,再想降级方案。开发阶段多用真机调试,开发者工具的结果不一定准确。

    来源:https://www.dnote.cn

  • Docker 容器化 Go 服务的几个实战细节

    Docker 容器化 Go 服务的几个实战细节

    多阶段构建:让镜像小到 10MB 以内

    Go 是静态编译语言,只需要编译后的二进制文件,不需要运行时环境。多阶段构建可以分离构建环境和运行环境,最终镜像只包含二进制文件。

    # 阶段1:构建
    FROM golang:1.23-alpine AS builder
    WORKDIR /app
    COPY go.mod go.sum ./
    RUN go mod download
    COPY . .
    RUN CGO_ENABLED=0 GOOS=linux go build -ldflags='-w -s' -o server .
    
    # 阶段2:运行
    FROM alpine:3.19
    RUN addgroup -S appgroup && adduser -S appuser -G appgroup
    WORKDIR /app
    COPY --from=builder /app/server .
    RUN chmod +x server
    USER appuser
    CMD ["./server"]

    利用 Docker BuildKit 加速构建

    # 启用 BuildKit
    export DOCKER_BUILDKIT=1
    
    # 并行下载依赖,大幅加速
    docker build --progress=plain -t myapp:latest .

    健康检查:让 K8s/Compose 知道服务已就绪

    在 Dockerfile 里加上 HEALTHCHECK,让 orchestrator 在服务真正能接收请求时才将其加入负载均衡。

    HEALTHCHECK --interval=30s --timeout=5s --start-period=5s --retries=3 \
      CMD wget -qO- http://localhost:8080/health || exit 1

    环境变量注入的坑

    Go 程序默认会在 ENV 改变时重新加载,但 Docker 层会缓存 ENV。用 ENTRYPOINT 脚本或 Viper 动态读取,比硬编码 ENV 常量更灵活。

    小结

    Docker 化 Go 服务的核心是:镜像要小(多阶段构建)、构建要快(BuildKit)、健康要可感知。做到这三点,生产部署就没什么大问题了。

    来源:https://www.dnote.cn

  • 财报速读指南:拿到一份年报该从哪里开始

    财报速读指南:拿到一份年报该从哪里开始

    为什么要自己读财报

    市场上的财报解读要么太浅(只说增长了多少),要么太碎(逐字逐句读,缺乏投资视角)。真正有用的财报阅读,是以投资问题为出发点,在有限时间内找到关键答案。

    第一步:读审计意见

    打开年报先翻到「审计报告」,看审计师给的是「标准无保留意见」还是带说明段的保留意见。如果是后者,说明这家公司的财务数据存在不确定性,需要提高警惕。

    第二步:看收入与利润的趋势

    找到「合并利润表」,重点看近 3-5 年的收入增速和毛利率变化。不要只看数字,要看趋势——是加速增长、增速放缓,还是周期性波动?增速放缓的「高增长」公司是最危险的陷阱。

    第三步:读现金流量表

    利润可以造假,现金流很难。经营活动现金流净额长期低于净利润,说明利润质量差,可能是应收款堆积或关联交易在「制造」利润。自由现金流(经营现金流 – 资本支出)才是企业真正的赚钱能力。

    第四步:读资产负债表的两端

    看负债端:资产负债率是否在合理范围?是否有大量短期借款需要近期偿还?看资产端:商誉占总资产比例?应收账款是否异常增长?这些数字反映了公司的财务健康度。

    第五步:找到管理层讨论与分析(MD&A)

    这是年报中最有价值的定性内容——管理层亲口解释为什么业绩上升/下降,对行业趋势的判断,以及下一年计划。读这里比读研报更能建立对公司的真实理解。

    一个实用的年报速读流程

    • 审计意见 → 排除财务风险
    • 收入/毛利率趋势 → 判断成长性
    • 经营现金流 vs 净利润 → 判断利润质量
    • 资产负债率 + 短债压力 → 判断财务安全
    • MD&A → 理解管理层思路

    小结

    读财报不需要会计专业,核心是建立一套提问框架:这份年报能回答我的投资问题吗?如果找不到答案,就继续找下一个投资标的。财报是用来排除公司的,不是用来证明公司有多好的。

    来源:https://www.dnote.cn

  • 用 Taro 开发小程序:答题卡网格布局的兼容性问题总结

    背景

    在做一个刷题小程序时,需要实现一个答题卡界面——用网格展示所有题目状态(未答/已答/当前题),支持点击跳转。在 Web 上几行 CSS 搞定,在小程序里却踩了不少坑。

    问题一:gap 属性在小程序里不生效

    这是最常见的问题。CSS gap 属性用于设置网格/弹性盒子的间距,在主流浏览器都支持,但在微信小程序、支付宝小程序里均不支持。解决方案:

    /* ❌ 小程序不支持 */
    .grid { display: grid; gap: 16px; }
    
    /* ✅ 改用 margin 模拟 */
    .grid { display: grid; }
    .grid-item { margin-right: 16px; margin-bottom: 16px; }
    /* 最后一项去掉右边距 */
    .grid-item:last-child { margin-right: 0; }

    问题二:display: grid 在某些机型的兼容情况

    iOS 微信大部分版本支持 grid,但 Android 端部分机型(尤其是低端机)的 UC/QQ 浏览器内核不支持。推荐降级方案:用 flex + 百分比宽度实现网格。

    /* ✅ 兼容写法:flex 模拟网格 */
    .row { display: flex; flex-wrap: wrap; }
    .cell { width: 48px; height: 48px; margin: 0 4px 8px 0; }

    问题三::nth-child 在某些场景下失效

    nth-child 在动态列表(数据来自接口)时表现正常,但在用 v-for 遍历固定数量的数字时,微信开发者工具和部分真机行为不一致。解决方案是改用 v-if 或加辅助 class。

    实战答题卡组件代码

    const AnswerCard = ({ questions, currentIndex, onJump }) => {
      return (
        <View className='answer-card'>
          <View className='row'>
            {questions.map((q, i) => (
              <View
                key={q.id}
                className={`cell ${i === currentIndex ? 'current' : ''} ${q.answered ? 'done' : 'undone'}`}
                onClick={() => onJump(i)}
              >
                {i + 1}
              </View>
            ))}
          </View>
        </View>
      )
    }

    小结

    小程序开发的本质是与 CSS 兼容层打交道。遇到 display、gap、nth-child 等属性,先查 caniuse,再想降级方案。开发阶段多用真机调试,开发者工具的结果不一定准确。

    来源:https://www.dnote.cn

  • 从利润表到现金流:拆解一家公司到底赚不赚钱

    净利润是最容易被操纵的数字

    利润表(Income Statement)上的净利润,是按照权责发生制编制的——卖出商品就算收入,不看钱有没有到账。这意味着可以通过应收款虚增收入、通过会计估计调整来平滑利润。读懂净利润背后的故事,才是财报分析的核心。

    两个核心比率

    第一个是「经营现金流/净利润」比率(盈利质量比率)。正常公司这个比率应该大于 1,说明净利润都有真实的现金支撑。长期低于 0.8 的公司需要警惕。

    第二个是「收现比」:销售商品、提供劳务收到的现金 / 营业收入。这个比率反映每 1 元收入实际收到了多少现金。低于 0.8 说明大量收入停留在应收款里。

    案例:某消费电子公司

    某公司连续三年净利润增速超过 30%,但经营现金流持续为负。深入一看:应收账款从 10 亿增长到 40 亿——原来是通过给经销商大量赊账来「制造」收入增长。这种高增长是危险的,一旦渠道去库存,收入会断崖式下跌。

    如何用自由现金流估值

    DCF 估值本质上是对未来自由现金流的折现。计算公式:自由现金流 = 经营现金流 – 维持性资本支出。简化版可以用「经营现金流净额 × 80%(保守估算资本支出)」来估算。

    小结

    利润是会计游戏,现金流是商业现实。读财报时,永远把现金流量表放在和利润表同等重要的位置。两表对照,才能看清一家公司真正的赚钱能力。

    来源:https://www.dnote.cn

  • Go 并发编程:Goroutine 与 Channel 实战指南

    为什么 Go 的并发模型值得专门学

    Go 的并发哲学来自 C.A.R. Hoare 的 CSP 理论,与传统线程模型完全不同。理解这套模型,是写出高性能 Go 服务的基础。

    Goroutine 到底是什么

    goroutine 是由 Go 运行时管理的轻量级线程,创建成本极低(约 2KB 栈空间),可以轻松创建数万个 goroutine 而不耗尽系统资源。与 OS 线程的 1:1 模型不同,Go 使用 M:N 调度——M 个 OS 线程上运行 N 个 goroutine,由 Go 运行时 GOMAXPROCS 控制并行度。

    一个简单的 goroutine 示例

    // 启动一个 goroutine
    go func() {
        fmt.Println("running in goroutine")
    }()
    
    // 主 goroutine 继续执行,不等待子 goroutine
    fmt.Println("main exits")

    Channel:goroutine 之间的通信桥梁

    channel 是 goroutine 间传递数据的管道,有带缓冲(buffered)和不带缓冲(unbuffered)两种。推荐优先使用无缓冲 channel,这样发送与接收必须配对,强制调用方思考同步问题,避免隐藏的竞态。

    ch := make(chan int)         // 无缓冲
    ch <- 42                       // 发送(阻塞直到有人接收)
    value := <-ch                  // 接收
    
    // 带缓冲 channel(队列)
    bufCh := make(chan int, 100)  // 最多缓存 100 条,不阻塞

    select:多路复用的并发协调

    select 关键字让一个 goroutine 可以同时监听多个 channel,就跟 select 系统调用监听多个 fd 一样。配合 default case 可以实现非阻塞发送/接收。

    select {
    case msg := <-ch1:
        fmt.Println("received from ch1:", msg)
    case msg := <-ch2:
        fmt.Println("received from ch2:", msg)
    case <-time.After(time.Second):
        fmt.Println("timeout")
    default:
        fmt.Println("no message available")
    }

    常见踩坑与最佳实践

    • 不要用 channel 传递所有数据——共享内存(sync.Mutex/sync.Map)有时更简单
    • 永远不要关闭由别人发送的 channel,避免 panic
    • 使用 context.Context 来控制 goroutine 的生命周期,而不是用 channel 硬传退出信号
    • 在生产环境加上 -race 参数跑单元测试,检查数据竞争

    总结

    Go 的并发模型用起来简单,但要真正用好,需要理解 goroutine 的调度原理、channel 的阻塞语义,以及 context 在多层调用中的传递方式。掌握这些,你就能写出既高效又安全的并发代码。

    来源:dnote.cn

  • WordPress 6.9.4 正式发布:更新内容速览

    WordPress 6.9.4 已于 2026年04月15日 正式发布。以下是本次更新的主要内容整理,供站长参考。

    ⚠️ 安全版本:本次更新包含安全修复,建议所有用户尽快升级。

    本次 6.9.4 是一个安全维护版本,修复了 10 个安全问题。WordPress 安全团队发现此前版本中部分安全修复未完全生效,因此紧急发布 6.9.4 补丁。

    🔒 安全修复

    • 路径穿越漏洞(PclZip 组件)
    • 授权绕过漏洞
    • XXE(XML 外部实体注入)漏洞

    如何升级

    登录 WordPress 后台 → 仪表盘 → 更新,点击「立即更新」即可完成升级。建议升级前先备份数据库和文件。

    参考链接

    本文由自动化脚本监测到 WordPress 新版本后自动生成,仅供参考。

  • 迈瑞医疗2025年财报深度解读:上市首次下滑背后,国际化转型提速与估值底部机会

    迈瑞医疗2025年财报深度解读:上市首次下滑背后,国际化转型提速与估值底部机会

    2026年3月30日晚,迈瑞医疗(300760)正式披露2025年年度报告。这份财报给市场带来了不小的震动:这是公司2018年A股上市以来,营收和净利润首次出现年度同比下滑。然而,数字背后,是一个医疗器械龙头在政策寒冬中艰难转型、蓄力待发的真实写照。

    一、核心财务数据一览

    指标2025年2024年同比变化
    营业收入332.82亿元367.26亿元▼ -9.38%
    归母净利润81.36亿元116.68亿元▼ -30.28%
    扣非归母净利润80.69亿元114.45亿元▼ -29.48%
    经营活动现金流101.45亿元124.34亿元▼ -18.40%
    研发费用35.79亿元36.66亿元▼ -2.37%
    销售费用51.45亿元52.83亿元▼ -2.61%
    每股收益(EPS)6.71元9.64元▼ -30.4%
    拟每10股派息3.10元(含税)

    乍看之下,这组数字相当难看。但读懂这份财报,需要穿透数字,看清楚究竟发生了什么。

    二、业绩下滑的真实原因:不是竞争,是政策

    国内业务:政策叠加冲击,下滑22.97%

    2025年国内业务收入156.32亿元,同比下降22.97%,是业绩大幅下滑的核心原因。压力主要来自三个方向:

    • 医院采购预算缩减:受医院整体经营压力影响,设备采购处于弱复苏阶段
    • 体外诊断试剂双重打压:DRG/DIP支付方式改革叠加集中带量采购,试剂用量和价格双双下行
    • 检验结果互认政策:减少了重复检验需求,直接压缩试剂市场规模

    值得注意的是,迈瑞在国内市场的份额并未丢失,反而是逆势提升。这意味着整个蛋糕缩小了,而迈瑞分到了更大的比例——这是长期竞争力的体现。

    国际业务:逆势增长,占比首次超50%

    与国内形成鲜明对比,国际业务实现收入176.50亿元,同比增长7.40%,占总收入比重升至53%,首次超过国内业务。

    区域表现
    欧洲市场同比增长17%(在2024年高增长基础上继续提速)
    新兴市场新突破近90家国际重点战略客户,含17家全球前100名医院
    国际新兴业务增长近30%

    迈瑞正在加速成为一家真正的全球化医疗器械公司,这一转变从长远来看意义重大。

    三、财务健康度:盈利质量仍属优秀

    尽管利润大幅下滑,迈瑞的财务结构依然坚实:

    财务指标2025年
    毛利率60.32%
    净利率25.39%
    ROE(净资产收益率)22.00%
    ROA(总资产收益率)15.91%
    资产负债率27.43%(极低,财务稳健)
    流动比率2.36(偿债能力强)
    经营现金流101.45亿元(净利润覆盖率124%)

    毛利率60%+、净利率25%+、ROE 22%——在如此大的盈利下滑背景下,迈瑞依然保持着这样的财务质量,足以说明其商业模式的护城河深度。经营活动现金流达101亿元,远超归母净利润,说明公司盈利含金量极高,没有水分。

    四、新兴业务:下一个增长极

    2025年迈瑞新兴业务收入53.78亿元,同比增长38.85%,占总收入约16%,是整体财报中最亮眼的部分。

    新兴业务进展
    微创外科超声刀、吻合器等集采中标,进入上百家头部医院
    微创介入(惠泰医疗)三维房颤PFA/RFA系统获批,进入临床
    动物医疗海外收入占比约80%,增速亮眼
    AI大模型”启元生态”重症医学大模型5秒完成患者24小时病情梳理

    新兴业务的高速成长,让迈瑞从单纯依赖传统三大业务(体外诊断+生命信息支持+医学影像)转型为多赛道驱动,抗风险能力大幅提升。

    五、历史业绩纵览:首次下滑,但趋势不变

    年份营业收入归母净利润EPS
    2021年252.70亿元80.02亿元6.59元
    2022年303.66亿元96.07亿元7.94元
    2023年349.32亿元115.82亿元9.56元
    2024年367.26亿元116.68亿元9.64元
    2025年332.82亿元81.36亿元6.71元

    2025年是迈瑞上市以来的首次年度下滑,主要由国内政策性因素导致,并非企业竞争力丧失。从2021年到2025年,利润整体仍保持增长趋势,只是2025年出现了阶段性回调。

    六、估值分析:当前位置在哪里?

    截至2026年3月31日,迈瑞医疗A股股价约164.66元,总市值约1,996亿元

    估值指标当前值参考意义
    PE(TTM)约24.5倍基于2025年盈利,历史中位数约35-40倍
    PB约5.24倍ROE 22%,PB合理
    PS(TTM)约6.0倍医疗器械龙头正常水平
    股价较高点约较2025年初250元高点下跌34%估值已大幅压缩

    从历史估值来看,迈瑞在高速成长期PE常年维持在35-50倍区间。当前约24.5倍PE对应的是公司阶段性低谷年份的盈利,若2026年国内业务如期恢复正增长,利润回升到100亿+水平,当前市值隐含的实际估值会更低。

    七、投资视角:该如何看待迈瑞?

    看多的理由

    • 政策压力是阶段性的,不是永久性的:DRG改革、集采是一次性冲击,医院预算最终会恢复,检验需求不会消失
    • 国际化战略提前突围:国际收入首超50%,提供了天然对冲,长期来看降低了对国内政策的依赖
    • 护城河极深:60%毛利率、22% ROE说明定价权强、复购黏性高,这是普通制造业无法比拟的
    • 新兴业务38.85%的高速增长将在未来3-5年贡献越来越大的增量
    • 管理层明确预期2026年国内正增长、2027年加速
    • 当前估值处于历史低位区间,距离高点已回调34%

    需要关注的风险

    • 政策不确定性:若集采范围进一步扩大,或医院采购恢复不及预期,2026年业绩可能再度承压
    • 国际竞争加剧:进入欧美高端市场面临飞利浦、西门子、GE的强力竞争
    • 汇率风险:国际收入占比提升后,人民币升值会对营收产生负面影响
    • 新兴业务规模尚小:53.78亿的新兴业务虽然增速喜人,但尚不足以完全弥补主业波动

    综合判断

    迈瑞医疗2025年的业绩下滑是外因主导的阶段性低点,而非竞争力衰退。公司基本面依然出色,财务质量健康,国际化转型按部就班,新兴业务高速成长。

    对于中长期投资者:当前位置(约165元,PE约25倍)已经接近历史底部估值区间,具备相当的安全边际。如果相信国内医疗政策会逐步归于正常、相信迈瑞的全球化战略能够持续兑现,那么目前的位置提供了不错的中长期布局机会。

    对于短期投资者:需要等待国内业务恢复正增长的明确信号,预计2026年中报可能是一个重要的观察节点。

    目标价参考:假设2026年净利润恢复至95-100亿,给予25-30倍PE,对应合理市值区间约2,375-3,000亿,相当于每股195-248元,相对当前股价有20%-50%的潜在上行空间


    免责声明:本文仅为财报分析,不构成任何投资建议。股市有风险,投资需谨慎。请在做出任何投资决策前进行独立研究或咨询专业人士。

  • 中国移动2025年财报深度解读:营收破万亿,算力转型加速,股息率近5%值得关注

    中国移动2025年财报深度解读:营收破万亿,算力转型加速,股息率近5%值得关注

    2026年3月26日,中国移动(股票代码:600941.SH / 00941.HK)正式发布2025年全年业绩。作为全球最大的移动通信运营商,中国移动在复杂的外部经济环境下交出了一份稳中有进的成绩单。本文将从财务数据、业务亮点、估值分析等多个维度,对这份财报进行深度解读。


    一、核心财务数据一览

    营收与利润

    指标 2025年 2024年 同比变化
    营业总收入 10,502亿元 10,408亿元 +0.9%
    营业利润 1,784亿元 1,763亿元 +1.2%
    利润总额 1,756亿元 1,784亿元 -1.6%
    归母净利润 1,371亿元 1,384亿元 -0.9%
    EBITDA 3,415亿元 3,381亿元 +1.0%
    基本每股收益 6.35元 6.45元 -1.6%

    解读:营收突破1万亿元大关,但净利润小幅下滑。这一现象主要源于非经营性收益减少和所得税波动,实际经营层面(EBITDA)仍保持增长,公司核心盈利能力稳健。

    关键财务指标

    指标 2025年 2024年
    ROE(净资产收益率) 9.97% 10.39%
    ROA(总资产收益率) 8.35% 8.70%
    毛利率 28.87% 29.02%
    净利率 13.07% 13.31%
    资产负债率 33.22% 34.33%
    每股净资产 64.37元 63.05元

    现金流

    项目 2025年 2024年
    经营活动现金净流入 2,329亿元 3,157亿元
    投资活动现金净流出 -1,904亿元 -1,852亿元
    筹资活动现金净流出 -1,121亿元 -1,052亿元
    自由现金流 1,031亿元 3,726亿元

    注意:自由现金流同比大幅下降,主要是因为2024年该项数字异常偏高(含特殊处置收益),2025年回归正常区间,实际造血能力仍然强劲。


    二、业务亮点:从”管道”到”智能底座”

    1. 算力服务:最亮的增长极

    2025年,算力服务收入达898亿元,同比增长11.1%,其中智算服务收入增速高达279%。这是中国移动战略转型最具说服力的数据——公司正在从传统”流量管道”蜕变为AI时代的”算力底座”。

    截至2025年末,中国移动智算规模达92.5 EFLOPS,已在全国完成”东数西算”架构布局,支撑大模型训练、推理业务的基础设施日趋完善。

    2. 智能服务:AI+产品矩阵初具规模

    智能服务收入908亿元,同比增长5.3%,推出超百款AI+产品及解决方案,覆盖政务、医疗、教育、工业等核心场景。算力+智能两大新兴业务合计占主营收入比重提升至20.2%,成为公司增长的核心驱动力。

    3. 5G网络:规模全球领先

    5G基站规模超277万个,实现全国乡镇以上连续覆盖;千兆光网覆盖达5.3亿户。5G用户渗透率持续提升,为企业级应用(工业互联网、远程医疗等)打下坚实网络基础。

    4. 国际业务:超预期增长

    国际市场收入293亿元,同比增长28.5%,”一带一路”沿线布局加速变现,是营收增长最快的板块之一。

    5. 分红持续慷慨

    2024年度(在2025年实施)每股现金分红2.2916元(税前),连续多年保持增长。最新公告显示派息率为75%,以当前股价(约93元)计算,股息率约为4.93%,远超同期银行存款利率,是价值投资者重要的持有理由。


    三、估值分析:贵还是便宜?

    估值指标 当前值(2026/3/28) 评估
    股价(A股) 93.4元 较年初115元高位回调约19%
    PE(市盈率) 约14.7倍(2025年EPS 6.35元) 历史低位区间
    PB(市净率) 1.45倍(BPS 64.37元) 略高于净资产,溢价合理
    股息率 约4.9% 高于10年期国债利率约3倍
    总市值 约2,300亿元(A股流通) ——

    从历史估值来看,中国移动A股PE在12-20倍之间震荡,当前14-15倍处于中低位水平。考虑到业绩稳定性、高分红以及AI算力转型带来的潜在溢价,当前估值具备一定吸引力。

    券商分析师普遍给出”买入”或”增持”评级,目标价区间在110-125元,较当前股价(约93元)有约20-35%的上行空间。


    四、风险与挑战

    短期风险

    • 宏观经济压力:消费端增速放缓可能影响ARPU(每用户平均收入)提升空间
    • 资本开支高企:2026年资本开支计划1,366亿元,算力网络投资占比超37%,短期净利润承压
    • A股与H股价差:A股相对H股溢价约25%,存在一定估值压力

    中长期风险

    • 技术迭代风险:AI算力竞争激烈,阿里云、腾讯云、华为云均在抢占市场
    • 收入增速天花板:传统通信业务增速接近饱和,依赖新业务驱动的转型需时间验证
    • 监管政策:数据安全、反垄断等监管趋严可能增加合规成本

    五、投资观点:稳健价值 + 算力转型期权

    综合以上分析,我对中国移动的投资判断如下:

    适合的投资者

    • 追求稳定股息的长期投资者:每年约5%的股息率,叠加净资产稳步增长,是抗通胀的优质资产
    • 看好AI算力基础设施的投资者:智算收入279%的增速证明公司已切入AI产业链核心位置
    • 偏好国央企低波动资产的配置型资金:政策背书强、市场地位稳固、现金流可预期

    不适合的投资者

    • ❌ 追求高弹性成长的成长股投资者:净利润增速个位数,不是”翻倍股”逻辑
    • ❌ 短线交易者:从年初高点回调19%后,短期缺乏强催化剂

    我的综合判断

    中性偏乐观,关注回调买点。
    当前PE约15倍、股息率约5%,估值合理偏低。算力服务和智能服务正在重塑公司增长逻辑,但转型成效需2-3年充分体现。建议在90-95元区间逢低建仓,以”持有吃股息 + 等待算力估值重估”的长期视角参与。


    六、小结

    中国移动2025年财报整体符合预期:营收稳健增长、EBITDA创新高、分红力度不减,算力与智能服务双轮驱动的转型路径日益清晰。虽然净利润因非经营性因素小幅下滑,但核心经营能力并未受损。

    在通信运营商普遍面临传统业务天花板的背景下,中国移动选择以”算力基础设施运营商”为方向突围,逻辑清晰、执行有力。这是一家值得长期跟踪的优质公司,当前价位对稳健投资者具有一定的配置价值。

    ⚠️ 免责声明:本文仅为个人财报分析记录,不构成任何投资建议。投资有风险,入市须谨慎。

  • 小米集团2025年全年业绩深度解析:营收破4500亿,汽车业务首次盈利

    小米集团2025年全年业绩深度解析:营收破4500亿,汽车业务首次盈利

    发布时间:2026年3月26日 | 数据来源:小米集团官方财报(2026.03.24发布)

    核心亮点速览

    指标2025年2024年同比变化
    总营收4,572.9亿元3,659.1亿元+25.0%
    毛利润1,018.1亿元765.6亿元+33.0%
    毛利率22.3%20.9%+1.4ppt
    经营利润479.0亿元245.0亿元+95.5%
    经调整净利润391.7亿元272.3亿元+43.8%
    研发投入331.3亿元240.5亿元+37.8%

    一、业绩总览:五年蜕变,2025创历史新高

    小米集团于2026年3月24日发布了经审计的2025年全年财报,各项核心指标均刷新历史记录。总营收突破4500亿元大关,达到4,572.9亿元,同比增长25%;经调整净利润达到391.7亿元,同比大增43.8%。这是小米上市以来表现最为亮眼的一份成绩单。

    纵观小米五年财务轨迹,可以清晰看出其从”高速扩张→调整蛰伏→价值重构”的转型弧线:

    财年总营收(亿元)经调整净利润(亿元)净利率
    2020年2,458.7130.15.3%
    2021年3,283.1220.46.7%
    2022年2,800.485.23.0%
    2023年2,710.7192.77.1%
    2024年3,659.1272.37.4%
    2025年4,572.9391.78.6%

    2022年是小米的”至暗时刻”:全球智能手机市场需求萎缩、疫情冲击供应链,营收较2021年下滑14.7%,经调整净利润腰斩。但小米选择了”向内蓄力”——持续加码研发、启动汽车业务、推进高端化战略,这些投入在2024-2025年集中兑现。

    二、业务结构:双轮驱动格局初步形成

    2.1 手机×AIoT:稳中有升,结构优化

    传统核心业务”手机×AIoT”全年实现营收3,512.2亿元(同比+5.4%),占总营收比例从91%降至76.8%,比例下降主要因为汽车业务的快速壮大,绝对规模仍在增长。

    业务线2025年营收2024年营收同比毛利率
    智能手机1,864.4亿元1,917.6亿元-2.8%10.9%(↓1.7ppt)
    IoT及生活消费产品1,232.0亿元1,041.0亿元+18.3%23.1%(↑2.8ppt)
    互联网服务374.4亿元341.2亿元+9.7%76.5%(持平)

    智能手机:量减价升,高端化战略初见成效。受全球智能手机大盘增速放缓及国补退出影响,手机营收小幅下滑2.8%,毛利率也从12.6%降至10.9%。但值得注意的是,Q4智能手机ASP(平均售价)已达1,176元/台,环比Q3(1,063元/台)提升10.7%,小米17 Pro、17 Pro Max等高端机型热销是主要驱动力。

    IoT及生活消费产品:本年最大惊喜。营收突破千亿达1,232亿元,毛利率更从20.3%大幅提升至23.1%,主要得益于可穿戴设备等高附加值品类收入占比提升。小米的”家居生态”正在产生复利效应。

    互联网服务:高利润压舱石。374亿元营收对应76.5%的超高毛利率,是整个集团的”利润奶牛”。随着小米设备保有量持续扩大,这一业务的天花板仍在抬升。

    2.2 智能电动汽车:从0到1再到盈利,速度超预期

    这是本份财报最具含金量的部分。小米汽车及AI等创新业务全年实现营收1,060.7亿元(同比+223.8%),占总营收23.2%,且年度经营收益首次转正——这对于一个成立仅三年的汽车品牌而言,几乎是不可思议的速度。

    指标2025年2024年增幅
    汽车营收1,033亿元321亿元+221.8%
    汽车交付量411,082辆136,854辆+200.4%
    汽车ASP25.1万元/辆23.4万元/辆+7.1%
    汽车毛利率24.3%18.5%+5.8ppt

    2025年小米交付了411,082辆汽车,是2024年交付量的3倍。SU7 Ultra的成功发布(52.99万元定价)将品牌拉升至豪华赛道;新一代SU7上市34分钟锁单超15,000辆;YU7系列的推出进一步拓宽了产品矩阵。

    更值得关注的是毛利率:从2024年的18.5%跃升至24.3%,超过绝大多数传统车企,已接近特斯拉最辉煌时期的水平。这一数字说明小米汽车具备可持续盈利能力,而非依靠补贴支撑。

    三、盈利质量:研发驱动,护城河持续加深

    2025年小米研发投入达331.3亿元,同比增长37.8%,占营收比例为7.2%。这是小米连续第五年保持研发投入双位数增长。研发方向涵盖:自研芯片(澎湃O1)、AI大模型(MiMo)、自动驾驶(Xiaomi HAD)、操作系统(澎湃OS)。

    从费用结构来看,2025年三大费用(研发+销售+管理)共计731亿元,但因毛利润大幅增长,费用率整体可控,经营杠杆效应明显——经营利润同比增幅高达95.5%,远超营收增速。

    四、Q4单季度:压力下的韧性

    第四季度是全年稍显”美中不足”之处。Q4营收1,169.2亿元(同比+7.3%),但经调整净利润为63.5亿元(同比-23.7%)。下滑原因主要是:

    • 国内国补政策调整导致手机销量季节性下滑
    • 海外市场促销力度减弱,出货量收缩
    • 研发和销售费用同比大幅增加(研发+29%,销售+28%)
    • 金融工具公允价值变动收益减少

    不过汽车业务Q4大幅改善:单季交付145,115辆(环比+33.4%),汽车营收达362.6亿元,为全年最高单季。

    五、前景展望:三大看点

    看点一:汽车目标提速。2026年小米汽车计划年交付量突破60万辆,新一代SU7发布即锁单3万辆,YU7持续放量。汽车业务若能维持24%+的毛利率,贡献利润将进一步提升整体盈利水平。

    看点二:AI全面赋能。小米自研大模型MiMo-V2-Flash已开源,HyperOS 3搭载全系AI助手,澎湃O1芯片量产落地。AI不仅是产品差异化的来源,更是互联网服务变现效率提升的催化剂。

    看点三:出海深化。卢伟冰启动欧洲首站布局,全球化市场拓展加速。海外市场(尤其是印度、东南亚、欧洲)手机份额稳固,是抵御国内竞争压力的重要缓冲。

    六、结语

    小米2025年财报的核心信息只有一条:战略已经兑现。三年前业界对”雷军造车”持怀疑态度,如今这个业务贡献了超过千亿营收并实现年度盈利;五年前小米被认为是”低端机品牌”,如今高端机型ASP突破1,176元并持续攀升。

    当然,挑战也同样清晰:手机业务毛利率下行压力、Q4利润承压、全球宏观不确定性。但从中长期视角看,小米正在构建一个”手机×AIoT×汽车×AI服务”的四轮驱动体系,每一条业务线都有独立的增长逻辑和协同空间。

    对于关注科技成长股的投资者,小米2025年财报是一份值得细细品味的答卷。


    免责声明:本文仅为财报解读与信息整理,不构成任何投资建议。投资有风险,决策需谨慎。

  • Dnote网站深度诊断报告:发现的问题与优化建议

    Dnote网站深度诊断报告:发现的问题与优化建议

    前言

    最近对个人博客网站 dnote.cn 进行了一次全面的结构分析和诊断,发现了一些值得关注的问题。本文将详细记录发现的问题并提供相应的优化建议。

    一、网站基础数据

    • 文章总数:100篇
    • 分类数:3个(编程95篇、投资18篇、未分类3篇)
    • 标签数:22个
    • 页面数:3个(关于、小玩意儿、搜索)
    • 媒体文件:50个

    二、发现的问题

    1. 内容分类严重失衡

    在100篇文章中,编程类占据了95篇,比例高达95%,而投资类仅有18篇。这反映出内容定位过于单一,建议:

    • 将部分技术文章重新归类,细化分类标签
    • 考虑增加新的分类维度,如”产品”、”创业”、”生活”
    • 将”未分类”的3篇文章尽快归类

    2. SEO基础优化不足

    通过分析发现以下SEO问题:

    • 缺少结构化数据:未发现JSON-LD富媒体标记,错失搜索展示机会
    • 内链锚文本单一:多为”查看更多→”,应使用关键词锚文本
    • 文章摘要较短:部分文章描述信息不足,影响搜索结果吸引力

    3. 性能优化空间

    • 未使用CDN:静态资源未通过CDN分发
    • 缺少Gzip压缩:建议开启以减少传输体积
    • 缺少浏览器缓存配置:应设置合理的缓存策略

    4. 标签使用混乱

    22个标签中,部分标签存在重复或过细的问题,如同时存在”SQL”和”MySQL”、”Docker”和”Linux”等,建议进行标签整合。

    5. 文章日期异常

    所有文章显示发布日期为2026年3月13日(部分甚至显示2025年),这可能是:

    • 批量导入时的伪日期
    • 系统时间配置问题
    • WordPress时区设置问题

    建议核查并修正,避免搜索引擎误判内容为过期内容。

    三、优化建议汇总

    优先级 问题 建议方案
    分类失衡 重新划分分类,增加3-5个新分类
    日期异常 检查WordPress时区设置,修正文章日期
    SEO元标签 添加JSON-LD结构化数据
    内链优化 使用关键词作为锚文本
    性能优化 接入CDN,配置Gzip和缓存

    四、结语

    整体而言,网站技术架构合理,WordPress运行稳定,内容质量较高。主要问题集中在内容组织结构和SEO基础优化上。解决这些问题后,网站的搜索可见性和用户体验都会有明显提升。

    后续我会逐步进行优化并记录改进效果,敬请期待。

  • 国内值得充值的VIP

    国内值得充值的VIP

    淘宝88VIP

    88元/年,性价比高(网易云+夸克+优酷)。

    网易云还好一点,夸克作为娱乐盘还行,作为工作负载,缺少的功能实在是太多了。

    优酷相对爱奇艺/腾讯视频,视频库也相对差了一些。

    但是我不是很敢深度使用,不知道为什么我总觉得阿里家用户态的东西给人缺乏持续性的感觉,总有可能被kill的风险。

    当然这句话可能有失偏颇,可能并不能说是单纯阿里的问题,其他公司可能也是存在的。

    百度网盘

    大部分时间处于175~188元/年之间。

    国内网盘很难评价,矮子里拔高个,百度网盘确实算还不错了。

    只要不打开客户端,同步和备份体验还不错,打开就一股恶心感,打算用Nas+夸克换掉,视频资源用夸克,同步用Nas。

    微信读书

    大部分时间处于158~168元/年之间。

    强烈好评。

  • 在electron中基于容器和服务提供者扩展应用核心能力

    在electron中基于容器和服务提供者扩展应用核心能力

    应用自身可能提供多种不同的能力,结合服务提供者概念和容器,我们可以实现类似插件的扩展机制,并且通过容器来统一管理服务对象,方便后续扩展。

    一、容器

    容器提供注册同步/异步工厂的方法、同步/异步获取指定服务对象的方法,移除某服务的方法和清空全部服务对象的方法。

    export class Container {
      private instances: Map<string, any> = new Map()
      private factories: Map<string, () => any> = new Map()
      private asyncFactories: Map<string, () => Promise<any>> = new Map()
      private resolvingPromises: Map<string, Promise<any>> = new Map()
      private singleton: Set<string> = new Set()
    
      // 同步注册工厂(默认为单例)
      register<T>(token: string, factory: () => T, options: { singleton?: boolean } = { singleton: true }) {
        this.factories.set(token, factory)
        if (options.singleton) {
          this.singleton.add(token)
        } else {
          this.singleton.delete(token)
        }
      }
    
      // 异步注册工厂(默认为单例)
      registerAsync<T>(token: string, factory: () => Promise<T>, options: { singleton?: boolean } = { singleton: true }) {
        this.asyncFactories.set(token, factory)
        if (options.singleton) {
          this.singleton.add(token)
        } else {
          this.singleton.delete(token)
        }
      }
    
      // 同步解析
      resolve<T>(token: string): T {
        // 如果是单例且已存在实例,直接返回
        if (this.singleton.has(token) && this.instances.has(token)) {
          return this.instances.get(token)
        }
    
        // 查找工厂函数
        const factory = this.factories.get(token)
        if (!factory) {
          // 如果没有工厂但有实例,可能是异步实例已完成
          if (this.instances.has(token)) {
            return this.instances.get(token)
          }
          throw new Error(`Service not found: ${token}`)
        }
    
        // 创建实例
        const instance = factory()
    
        // 如果是单例,保存实例
        if (this.singleton.has(token)) {
          this.instances.set(token, instance)
        }
    
        return instance
      }
    
      // 异步解析
      async resolveAsync<T>(token: string): Promise<T> {
        // 如果是单例且已存在实例,直接返回
        if (this.singleton.has(token) && this.instances.has(token)) {
          return this.instances.get(token)
        }
    
        // 检查是否已经有正在解析的Promise
        let resolvingPromise = this.resolvingPromises.get(token)
        if (resolvingPromise) {
          // 如果有,直接返回这个Promise的结果
          return resolvingPromise
        }
    
        // 先检查是否有异步工厂
        const asyncFactory = this.asyncFactories.get(token)
        if (asyncFactory) {
          // 创建一个新的解析Promise并存储
          resolvingPromise = (async () => {
            try {
              const resolved = await asyncFactory()
              // 如果是单例,保存实例
              if (this.singleton.has(token)) {
                this.instances.set(token, resolved)
              }
              return resolved
            } finally {
              // 解析完成后从resolvingPromises中移除
              this.resolvingPromises.delete(token)
            }
          })()
    
          // 如果是单例,存储Promise以避免重复创建
          if (this.singleton.has(token)) {
            this.resolvingPromises.set(token, resolvingPromise)
          }
          return resolvingPromise
        }
    
        // 再检查是否有同步工厂
        const factory = this.factories.get(token)
        if (factory) {
          try {
            const resolved = factory()
            // 如果是单例,保存实例
            if (this.singleton.has(token)) {
              this.instances.set(token, resolved)
            }
            return resolved
          } catch (error) {
            if (error instanceof Error) {
                throw new Error(`Failed to resolve service '${token}': ${error.message}`)
            } else {
                throw error
            }
          }
        }
    
        // 最后检查是否已有实例(可能是之前异步解析完成的)
        if (this.instances.has(token)) {
          return this.instances.get(token)
        }
    
        throw new Error(`Service not found: ${token}`)
      }
    
      // 检查是否存在指定token的服务
      has(token: string): boolean {
        return this.instances.has(token) ||
               this.factories.has(token) ||
               this.asyncFactories.has(token)
      }
    
      // 清除指定服务的实例(不移除工厂)
      clearInstance(token: string): void {
        this.instances.delete(token)
        this.resolvingPromises.delete(token)
      }
    
      // 移除服务(包括工厂和实例)
      remove(token: string): void {
        this.instances.delete(token)
        this.factories.delete(token)
        this.asyncFactories.delete(token)
        this.resolvingPromises.delete(token)
        this.singleton.delete(token)
      }
    }
    

    二、服务提供者

    服务提供者接口比较简单,区分register和boot主要是为了确保boot中可以调用任何其他提供者。

    import type { Container } from "../container"
    
    export default interface ServiceProvider {
        /**
         * 应用启动后立即调用
         * 建议仅用于注册服务,不要执行其他操作,其他操作可以放在boot方法中
         *
         * @param container
         */
        register?(container: Container): void
    
        /**
         * boot函数在所有服务注册完成后调用
         * 可以执行一些初始化操作
         *
         * @param container
         */
        boot?(container: Container): void | Promise<void>
    }
    

    三、应用对象

    import { Container } from './container'
    
    export default class APP {
    
        /**
         * 应用实例,用来保持单例
         */
        private static _ins: APP
    
        /**
         * 容器对象
         */
        private container: Container
    
        /**
         * 服务提供者列表
         */
        private providers: ServiceProvider[] = []
    
        /**
         * 运行应用
         */
        static run() {
            if (APP._ins == null) {
                APP._ins = new APP()
            }
    
            return APP._ins
        }
    
        constructor() {
            // 初始化容器并注册服务提供者
            this.container = new Container()
    
            // 注册服务
            this.registerProviders()
    
            // 启动服务
            this.bootProviders()
        }
    
        registerProviders() {
            for (const provider of this.providers) {
                provider.register?.(this.container)
            }
        }
    
        bootProviders() {
            return Promise.all(
                this.providers.map(provider => provider.boot?.(this.container))
            )
        }
    }
    
  • Caddy配置sts(Strict-Transport-Security)

    Caddy配置sts(Strict-Transport-Security)

    example.com {
        # 启用 HSTS,有效期 1 年(31536000 秒)
        header {
            Strict-Transport-Security max-age=31536000
        }
    
        # 其他配置...
        reverse_proxy localhost:8080
    }
    
  • 创建strapi插件

    创建strapi插件

    需要开发一个插件来实现一些自定义功能,官方文档写的实在是难以理解了。

    1. 创建基础的目录结构

    # 作为项目根目录
    mkdir xxx
    
    # 进入项目目录
    cd xxx
    
    # 创建strapi 项目
    npx create-strapi@latest strapi
    
    # 创建插件
    npx @strapi/sdk-plugin init strapi-plugin
    

    2. 配置工作区

     # xxx目录中添加workspace配置
    {
         "workspaces": [
             "strapi",
             "strapi-plugin"
         ],
         "dependencies": [
             "strapi-plugin": "workspace:*"
         ]
     }
    

    3. strapi目录引入依赖

     {
         ...
         "dependencies": {
             ...
             "strapi-plugin": "0.0.0"
         }
     }
    

    4. 插件目录监听文件修改

    # 根目录执行
    npm run watch --workspace=strapi-plugin
    

    5. 运行strapi

    npm run develop --workspace=strapi
    
  • 未来20年最具颠覆性的科技变革

    未来20年最具颠覆性的科技变革

    1. 通用量子计算机
    2. 人工智能加量子计算
    3. 受控核聚变
    4. 材料突破,为能源技术,信息技术和生物医学提供坚实基础

  • 李想谈大佬的共性

    李想谈大佬的共性

    1. 选的长,做长期的事,做难的事,做时间的朋友
    2. 选的准,选择比努力重要
    3. 在很长,很成功的赛道里,高速的迭代
  • Parse Platform任务调度

    Parse Platform任务调度

    说起来也挺奇怪的,Parse Platform本身基于js实现,Node生态里的任务调度实现起来并不麻烦,Parse却选择了不集成,使用第三方提供的任务调度。这里使用node-cron来实现Parse Server中的Job调度。

    一、Cloud Code定义Job

    Parse.Cloud.job("test", async (request) =>  {
        // params: passed in the job call
        // headers: from the request that triggered the job
        // log: the ParseServer logger passed in the request
        // message: a function to update the status message of the job object
        const { message } = request
        message('done')
    })
    

    二、定义一个调用Job的函数,方便后面使用

    async function callParseJob(parseServerUrl: string, name: string, data?: any) {
      console.log(`node-cron: callParseJob ${name}`)
      const options: RequestInit = {
        method: 'POST',
        headers: {
          'X-Parse-Application-Id': process.env.APP_ID ?? '',
          'X-Parse-Master-Key': process.env.MASTER_KEY ?? ''
        }
      }
      if (data != null) {
        options.body = JSON.stringify(data)
      }
      const res = await fetch(`${parseServerUrl}/jobs/${name}`, options)
      console.log(`node-cron: job ${name} finished, ${res.statusText}`)
      return await res.json()
    }
    

    三、使用node-cron调度Job

    这里选择通过单独的进程来运行调度程序

    if (cluster.isPrimary) {
      cron.schedule('* * * * *', async () => await callParseJob(process.env.SERVER_URL ?? '', 'test'))
      cluster.fork() // 根据cpu个数fork子进程
    
      cluster.on('exit', function(worker, code, signal) {
        console.log('worker ' + worker.process.pid + ' exited')
        cluster.fork() //新建一个worker
      })
    } else {
      const app = express()
        //...启动Server相关的代码,这里省略
    }