Posted in

【信创替代倒计时90天】:Go语言国产系统迁移路线图(含存量Java/Python模块Go重写优先级矩阵)

第一章:信创替代倒计时90天:Go语言国产系统迁移战略总览

距离国家信创工程关键节点仅剩90天,Go语言作为高性能、强生态、低侵入的现代编程语言,正成为政务云、金融核心与能源调度等关键领域国产化迁移的首选技术栈。其静态编译特性规避了glibc版本兼容难题,CGO可控开关机制可有效适配麒麟V10、统信UOS、中科方德等主流国产操作系统内核及安全加固模块。

迁移适配核心维度

  • 运行时兼容性:优先采用Go 1.21+版本(原生支持LoongArch64、SW64架构),禁用GOOS=linux GOARCH=amd64交叉编译,改用目标平台本地构建;
  • 依赖治理:通过go mod graph | grep -E "(cgo|sys|unix)"识别含C依赖模块,替换为纯Go实现(如用golang.org/x/sys/unix替代github.com/mattn/go-sqlite3);
  • 安全合规:启用-buildmode=pie -ldflags="-s -w -buildid="生成位置无关可执行文件,满足等保2.0三级对二进制加固要求。

国产系统构建验证流程

# 在麒麟V10 SP1服务器上执行(需预装Go 1.21.6)
export GOROOT=/opt/go
export GOPATH=$HOME/gopath
export PATH=$GOROOT/bin:$PATH

# 清理缓存并强制使用国产镜像源
go env -w GOPROXY=https://goproxy.mirrors.ustc.edu.cn,direct
go clean -cache -modcache

# 构建并校验符号表(确保无外部glibc动态链接)
go build -o app-linux-arm64 -trimpath -ldflags="-s -w" .
readelf -d ./app-linux-arm64 | grep NEEDED  # 输出应仅含ld-linux-aarch64.so.1(系统自带)

主流国产OS适配状态速查表

操作系统 内核版本 Go原生支持 典型问题 应对方案
麒麟V10 SP1 4.19.90 ✅ 完全支持 SELinux策略拦截网络绑定 setsebool -P container_connect_any 1
统信UOS V20 5.10.0 ✅ 完全支持 systemd服务启动超时 .service中添加TimeoutStartSec=300
中科方德FK2112 4.19.117 ⚠️ 需补丁 /proc/sys/net/core/somaxconn 权限受限 启动前执行sudo sysctl -w net.core.somaxconn=65535

第二章:国产化Go技术栈选型与合规性验证体系

2.1 国产CPU架构(鲲鹏/飞腾/海光/兆芯)下Go编译器适配实践

Go 1.21+ 原生支持 arm64(鲲鹏、飞腾)、amd64(海光、兆芯),但需显式指定目标平台:

# 鲲鹏(ARM64)交叉编译
GOOS=linux GOARCH=arm64 CGO_ENABLED=1 CC=aarch64-linux-gnu-gcc go build -o app-arm64 .

# 兆芯(x86_64兼容,需启用SSE4.2+指令集)
GOARCH=amd64 GOAMD64=v3 go build -o app-zx .

GOAMD64=v3 启用AVX/SSE4.2,适配兆芯KX-6000系列;飞腾D2000需设置 CC=ft-aarch64-linux-gnu-gcc 并链接私有libc。

架构 Go原生支持 关键适配点 典型代表芯片
ARM64 ✅ 1.17+ 禁用-march=armv8.2-a外挂指令 鲲鹏920、飞腾FT-2000+/64
AMD64 ✅ 默认 GOAMD64=v3强制向量化 海光Hygon C86、兆芯KX-6000
graph TD
    A[Go源码] --> B{GOARCH=arm64?}
    B -->|是| C[调用aarch64-gcc + libgo.a]
    B -->|否| D[GOARCH=amd64 → GOAMD64=v3]
    D --> E[生成AVX2/SSE4.2优化指令]

2.2 国产操作系统(统信UOS、麒麟V10、OpenEuler)运行时环境调优

国产操作系统在企业级部署中,JVM与内核协同优化是性能关键。以下聚焦通用调优路径:

JVM内存与GC策略适配

统信UOS(基于Debian)与麒麟V10(基于CentOS)默认启用cgroup v1,需显式启用容器感知:

# 启动Java应用时启用cgroup内存限制识别
java -XX:+UseContainerSupport \
     -XX:MaxRAMPercentage=75.0 \
     -XX:+UseG1GC \
     -jar app.jar

-XX:+UseContainerSupport 启用容器资源感知;MaxRAMPercentage 避免OOMKilled;G1GC在多核国产CPU(如鲲鹏920、飞腾D2000)上吞吐更稳。

内核参数协同调优

参数 推荐值 作用
vm.swappiness 1 抑制非必要swap,保障实时性
net.core.somaxconn 65535 提升高并发连接接纳能力

运行时依赖对齐

OpenEuler 22.03 LTS 默认使用OpenJDK 17(欧拉构建版),需校验JVM与glibc版本兼容性:

ldd $(readlink -f $(which java)) | grep libc
# 输出应匹配:libc.so.6 => /lib64/libc.so.6 (0x0000ffff...)

缺失匹配将导致Illegal instruction——常见于未适配ARM64向量指令的JDK构建。

2.3 国密SM2/SM3/SM4算法在Go标准库与第三方crypto模块的合规集成

Go 标准库原生不支持国密算法,需依赖经国家密码管理局认证的第三方模块(如 github.com/tjfoc/gmsm)实现合规集成。

核心依赖对比

模块 SM2 支持 SM3 支持 SM4 支持 FIPS/GM/T0002-2020 合规
crypto/*(标准库) 不适用
gmsm v1.9+ ✅(ECDSA-like) ✅(哈希长度256bit) ✅(CBC/ECB/GCM) ✅(含商密检测报告编号)

SM2签名示例(带密钥派生)

import "github.com/tjfoc/gmsm/sm2"

priv, _ := sm2.GenerateKey() // 使用SM2曲线(y² = x³ + ax + b mod p,p为256位素数)
data := []byte("hello-sm2")
r, s, _ := priv.Sign(data, nil) // r,s为SM2标准签名分量,非随机数k泄露防护已内建

Sign() 内部调用 sm2.DeriveK() 实现确定性随机数生成(RFC 6979 变体),确保相同消息不产生重复签名;nil 参数表示使用默认摘要算法 SM3。

数据同步机制

  • 所有国密操作必须通过 gmsm 提供的 Cipher, Hash, PrivateKey 接口抽象;
  • 禁止混用 crypto/ecdsagmsm/sm2 密钥对象;
  • SM4 加密需显式指定 IV(16字节)与填充模式(PKCS#7)。

2.4 信创中间件(东方通TongWeb、普元EOS、金蝶Apusic)Go客户端SDK封装规范

为统一对接国产信创中间件,SDK需遵循协议抽象→适配隔离→能力收敛三层封装原则。

核心接口契约

type MiddlewareClient interface {
    Invoke(ctx context.Context, service string, payload []byte) ([]byte, error)
    HealthCheck() bool
}

Invoke 统一封装HTTP/REST与私有RPC调用;payload 为序列化后字节流,由各适配器负责编解码;service 格式为 tongweb://appname/svc,标识中间件类型与逻辑服务路径。

适配器注册表

中间件 协议类型 默认端口 认证方式
TongWeb HTTP+SSL 8443 JWT + 国密SM2
EOS TCP+TLS 6800 双向证书
Apusic HTTP 8080 Basic+SM3摘要

初始化流程

graph TD
    A[NewClient] --> B{MiddlewareType}
    B -->|TongWeb| C[TongWebAdapter]
    B -->|EOS| D[EOSAdapter]
    B -->|Apusic| E[ApusicAdapter]
    C --> F[SM2解密+JSON反序列化]

SDK强制要求所有适配器实现 WithTimeout(30*time.Second)WithRetry(3) 公共选项。

2.5 Go语言国产化工具链审计:govendor→goproxy+私有镜像仓+SBOM生成流水线

随着信创合规要求深化,Go项目依赖管理正从已停更的 govendor 迁移至符合国产化审计要求的组合方案。

架构演进路径

  • goproxy 代理所有上游模块(如 proxy.golang.orggoproxy.cn
  • ✅ 私有镜像仓(Harbor)托管经安全扫描的 *.zip 模块包
  • ✅ CI阶段自动注入 syft 生成 SPDX 格式 SBOM

SBOM 流水线关键步骤

# 在 GitHub Actions 或 GitLab CI 中执行
syft -o spdx-json ./ --file sbom.spdx.json

syft 默认递归扫描 go.mod 及 vendor 目录;--file 指定输出路径,确保 SBOM 可被 grype 后续漏洞匹配,且满足等保2.0软件物料清单存证要求。

三方依赖治理对比

工具 模块锁定 镜像缓存 SBOM原生支持 国产信创适配
govendor ❌(已归档)
goproxy+Harbor ✅(配合syft) ✅(全链路可控)
graph TD
    A[go build] --> B[goproxy 请求]
    B --> C{是否命中私有仓?}
    C -->|是| D[返回签名ZIP包]
    C -->|否| E[拉取上游→扫描→推入Harbor]
    D --> F[编译时注入SBOM生成]

第三章:存量Java/Python模块Go重写方法论

3.1 静态依赖图谱分析与跨语言接口契约建模(OpenAPI/Swagger→Go struct自动映射)

静态依赖图谱通过解析 OpenAPI 3.0 文档,提取服务间调用关系与数据契约,构建可追溯的跨语言接口拓扑。

数据同步机制

工具链基于 go-swaggeroapi-codegen 实现双向契约驱动:

  • 解析 YAML 中 components.schemas 生成 Go 结构体
  • 利用 x-go-type 扩展字段控制命名与嵌套策略
# openapi.yaml 片段
components:
  schemas:
    User:
      type: object
      x-go-type: "github.com/org/api/v2.User"  # 显式绑定包路径
      properties:
        id:
          type: integer
          format: int64

逻辑分析x-go-type 告知代码生成器跳过默认命名规则,直接引用已有 domain struct;format: int64 映射为 int64 而非 int,避免跨平台整型溢出。

自动生成流程

graph TD
  A[OpenAPI YAML] --> B[AST 解析]
  B --> C[Schema 依赖拓扑构建]
  C --> D[Go struct AST 注入]
  D --> E[生成带 json tag 的 struct]
字段名 OpenAPI 类型 Go 类型 序列化标签
created_at string, date-time time.Time json:"created_at"
tags array of string []string json:"tags,omitempty"

3.2 Java Spring Boot微服务向Go Zero/Gin迁移的事务一致性保障策略

核心挑战:分布式事务语义断层

Spring Boot 原生依赖 @Transactional + JTA/Seata 实现 ACID,而 Go Zero/Gin 无内置声明式事务管理,需显式编排。

最小侵入一致性方案:Saga 模式 + 补偿队列

// Go Zero 中订单创建 Saga 编排示例(基于 rpc 调用)
func (s *OrderRpc) CreateOrder(ctx context.Context, req *CreateOrderReq) (*CreateOrderResp, error) {
    // 1. 本地事务:预留库存(TCC Try)
    if err := s.inventorySvc.Reserve(ctx, req.ProductId, req.Quantity); err != nil {
        return nil, err
    }
    // 2. 异步发消息触发下游支付(最终一致)
    s.mq.Publish("order_created", &OrderEvent{OrderId: req.OrderId, Status: "CREATED"})
    return &CreateOrderResp{OrderId: req.OrderId}, nil
}

逻辑分析:Reserve() 执行幂等扣减并写入 inventory_reservations 表;Publish() 使用 RocketMQ 事务消息,确保本地库存操作与消息投递原子性。参数 ctx 携带 traceID 支持全链路追踪,req 经 ProtoBuf 序列化保证跨语言兼容。

迁移适配关键点对比

维度 Spring Boot (Seata) Go Zero (自研 Saga)
事务边界 注解驱动,自动代理 显式函数链式调用
补偿注册方式 @Compensable 注解 配置中心注册补偿 handler
日志持久化 UNDO_LOG 表 MySQL + etcd 协调状态
graph TD
    A[Spring Boot Order Service] -->|HTTP/JSON| B[Go Zero Inventory Service]
    B --> C{Try 成功?}
    C -->|Yes| D[发 Kafka 订单事件]
    C -->|No| E[触发本地回滚 Reserve]
    D --> F[Gin Payment Service 消费]

3.3 Python科学计算模块(NumPy/Pandas)在Go中通过cgo+OpenBLAS或纯Go数值库替代路径

Go生态缺乏原生的高维数组与DataFrame抽象,但可通过两种主流路径逼近NumPy/Pandas能力边界:

  • cgo + OpenBLAS路径:调用高度优化的C线性代数库,适合CPU密集型矩阵运算
  • 纯Go数值库路径:如gonum/matgorgonia/tensor,零依赖、易部署,但部分算法性能暂逊

性能与权衡对比

维度 cgo+OpenBLAS gonum/mat(纯Go)
启动开销 高(需动态链接、CGO启用) 极低(静态编译)
矩阵乘法(1024×1024) ~85 GFLOPS ~22 GFLOPS
DataFrame类支持 需自行封装 无原生支持,需组合dataframe-go
// 使用gonum/mat执行QR分解(替代NumPy.linalg.qr)
package main
import "gonum.org/v1/gonum/mat"
func main() {
    a := mat.NewDense(3, 3, []float64{
        1, 2, 3,
        4, 5, 6,
        7, 8, 10,
    })
    var qr mat.QR
    qr.Factorize(a) // 输入矩阵a被就地分解为Q·R
    // qr.QTo() / qr.RTo() 可分别提取正交/上三角矩阵
}

qr.Factorize() 执行Householder反射算法,a必须是满秩;内部自动分配临时缓冲区,无需手动管理内存。参数仅接受mat.Matrix接口,兼容*mat.Dense*mat.SymDense等。

替代演进路线图

graph TD
    A[Python NumPy/Pandas] --> B{Go迁移目标}
    B --> C[cgo+OpenBLAS:高性能核心计算]
    B --> D[gonum+dataframe-go:云原生轻量场景]
    C --> E[需CGO_ENABLED=1 & OpenBLAS系统库]
    D --> F[go build -tags purego 可跨平台静态链接]

第四章:Go重写优先级矩阵落地实施指南

4.1 四维评估模型构建:业务影响度×技术耦合度×国产中间件兼容性×重构ROI量化指标

该模型将迁移决策从经验驱动转向数据驱动,四维指标均归一化至[0,1]区间后加权合成综合得分。

评估维度定义

  • 业务影响度:基于流量占比、SLA等级、故障容忍时长计算
  • 技术耦合度:静态分析调用深度 + 运行时服务依赖图谱密度
  • 国产中间件兼容性:通过适配层探针自动识别API差异(如Dubbo→DUBBO-SOFABOOT)
  • 重构ROI(预期年降本 + 故障减少收益)/(人力+许可+测试成本)

兼容性检测代码示例

// 中间件API兼容性探针(简化版)
public CompatibilityReport checkCompatibility(String component) {
    return compatibilityRules.get(component)      // 规则库:如"rocketmq:4.9.3→openmessaging:1.0"
        .stream()
        .filter(rule -> !isDeprecated(rule.targetApi)) // 检查目标API是否已废弃
        .map(this::simulateInvocation)              // 模拟调用并捕获ClassNotFound/NoSuchMethod
        .collect(Collectors.toMap(                  // 输出兼容性置信度
            r -> r.apiName, 
            r -> 1.0 - r.breakingChangeLevel * 0.3));
}

逻辑说明:breakingChangeLevel为0~3级破坏性标识(0=完全兼容),权重0.3体现兼容性在整体模型中非决定性但具否决权;simulateInvocation通过字节码增强动态触发关键路径,规避编译期误判。

四维权重分配建议(专家校准后)

维度 权重 说明
业务影响度 0.35 高优先级核心链路强制≥0.8才准入迁移
技术耦合度 0.25 ≥0.7需启动解耦专项
兼容性 0.20 <0.6直接标记“阻塞”
ROI 0.20 <1.0需重新评估范围
graph TD
    A[原始系统] --> B{四维扫描}
    B --> C[业务影响度评分]
    B --> D[耦合度拓扑分析]
    B --> E[中间件API探针]
    B --> F[ROI财务模型]
    C & D & E & F --> G[加权融合引擎]
    G --> H[迁移优先级队列]

4.2 高优先级模块实战:统一身份认证中心(CAS→Go-OIDC+国密TLS双向认证)

为满足等保2.0与金融行业密码合规要求,将传统Java CAS服务重构为轻量、可审计的Go-OIDC服务,并集成国密SM2/SM3/SM4及双向TLS认证。

核心架构演进

  • 淘汰CAS协议中非标准Ticket校验链路
  • 采用RFC 7519 OIDC Core + PKCE增强授权码流程
  • TLS层替换为国密套件 ECC-SM2-WITH-SM4-SM3(RFC 8998扩展)

国密双向TLS握手关键配置

// server.go:启用国密证书链与客户端证书强制校验
tlsConfig := &tls.Config{
    Certificates: []tls.Certificate{sm2Cert}, // SM2私钥+SM3签名证书
    ClientAuth:   tls.RequireAndVerifyClientCert,
    ClientCAs:    sm2RootPool, // 国密根CA信任池(含SM2公钥)
    MinVersion:   tls.VersionTLS12,
    CurvePreferences: []tls.CurveID{tls.CurveP256}, // 兼容SM2基点
}

该配置强制客户端提供SM2证书并完成双向身份核验;ClientCAs 必须加载国密根证书(DER格式),否则x509: certificate signed by unknown authority错误将中断握手。

认证流程概览

graph TD
    A[用户访问业务系统] --> B[重定向至OIDC Provider]
    B --> C{国密TLS双向握手}
    C -->|成功| D[SM2证书鉴权 + ID Token签发]
    C -->|失败| E[连接拒绝]
    D --> F[JWT含SM2签名+SM3摘要]
组件 原CAS方案 新Go-OIDC方案
协议标准 自定义Ticket OIDC Authorization Code
密码算法 RSA+SHA256 SM2+SM3+SM4
证书验证 单向HTTPS 双向国密TLS

4.3 中优先级模块实战:数据同步服务(Logstash→Go编写增量Binlog解析器+Kafka Producer)

数据同步机制

传统 Logstash 同步 MySQL Binlog 存在 JVM 开销大、延迟高、难以细粒度控制等问题。本方案采用 Go 编写轻量级增量解析器,直连 MySQL 的 binlog dump 协议,实时捕获 WRITE_ROWS_EVENT/UPDATE_ROWS_EVENT

核心组件职责对比

组件 延迟 资源占用 可观测性 扩展性
Logstash + jdbc_input ≥800ms 高(JVM) 弱(日志为主) 水平扩展困难
Go Binlog Parser + Kafka Producer 低(协程复用) 强(Prometheus metrics) 易分片(按表/库 hash)

Binlog 解析核心逻辑(Go 片段)

// 使用 github.com/go-mysql-org/go-mysql/replication
cfg := replication.BinlogSyncerConfig{
    ServerID: 1001,
    Flavor:   "mysql", // 支持 MariaDB
    Host:     "mysql-primary",
    Port:     3306,
    User:     "repl",
    Password: "xxx",
}
syncer := replication.NewBinlogSyncer(cfg)
streamer, _ := syncer.StartSync(mysql.Position{binlogFile: "mysql-bin.000001", pos: 4})

for {
    ev, _ := streamer.GetEvent(context.Background())
    if ev.Header.EventType == replication.WRITE_ROWS_EVENT || 
       ev.Header.EventType == replication.UPDATE_ROWS_EVENT {
        msg := buildKafkaMsg(ev) // 提取库表名、主键、变更字段
        producer.SendMessage(&sarama.ProducerMessage{Topic: "binlog_raw", Value: sarama.StringEncoder(msg)})
    }
}

逻辑说明:BinlogSyncer 建立长连接并伪装为从库;GetEvent() 阻塞获取事件,避免轮询;buildKafkaMsg() 序列化为 JSON 并附加 table, pk, op_type, ts 字段,供下游 Flink 或 Kafka Connect 消费。ServerID 必须全局唯一,防止主从环路。

流程概览

graph TD
    A[MySQL Master] -->|BINLOG DUMP| B(Go Binlog Parser)
    B --> C{Event Filter}
    C -->|WRITE/UPDATE| D[JSON Normalize]
    D --> E[Kafka Producer]
    E --> F[binlog_raw Topic]

4.4 低优先级模块灰度策略:Python报表引擎(Jinja2+Matplotlib)容器化隔离+Go API网关透传

为保障核心链路稳定性,报表引擎作为低优先级模块被严格隔离:Python服务仅响应网关透传的 /report/* 请求,无直接公网暴露。

容器化部署约束

  • 使用 --memory=512m --cpus=0.5 限制资源
  • 启动时注入 REPORT_ENV=gray-v2 环境标识
  • 健康检查端点 /healthz 返回 {"status":"ok","env":"gray-v2"}

Go网关透传逻辑(关键片段)

// 路由匹配后透传至报表服务集群
proxy := httputil.NewSingleHostReverseProxy(
    &url.URL{Scheme: "http", Host: "report-svc:8080"},
)
proxy.Transport = &http.Transport{
    MaxIdleConns:        32,
    MaxIdleConnsPerHost: 32,
}

该代理强制添加 X-Report-Trace-ID 头,并剥离所有非白名单请求头(如 Cookie, Authorization),实现上下文净化与调用链隔离。

灰度流量分发规则

来源标签 流量比例 目标版本
user-tier:basic 100% gray-v2
user-tier:pro 0% stable
graph TD
    A[Go API Gateway] -->|Header: X-Report-Tag=gray-v2| B[Report Pod]
    B --> C[Jinja2渲染模板]
    C --> D[Matplotlib生成PNG]
    D --> E[Base64编码返回]

第五章:90天冲刺里程碑与国产Go生态共建倡议

关键里程碑达成路径

自2024年3月1日启动“Go国产化加速计划”以来,联合中科院软件所、华为云、字节跳动基础架构部及37家开源社区贡献者,已按季度节奏完成三阶段交付:

  • 第30天:发布首个兼容Go 1.22的国产可信构建工具链 gobuild-cn,支持国密SM2/SM4签名验签与RISC-V交叉编译;
  • 第60天:上线 go-china.org 生态门户,集成217个经CNCF中国区SIG审核的国产Go模块(含蚂蚁金服SOFARegistry Go SDK、腾讯TKE Operator v0.8.3);
  • 第90天:完成《国产Go应用安全白皮书V1.0》并获等保2.0三级适配认证,覆盖内存安全审计、供应链SBOM生成、依赖包国产镜像源自动替换等12项硬性指标。

社区共建机制落地实录

杭州某政务云项目在迁移50万行Go微服务时,采用共建倡议中的“双轨制依赖治理”方案:

# 启用国产镜像代理(自动 fallback 至 goproxy.cn)
export GOPROXY="https://goproxy.cn,direct"
# 注入国产安全扫描插件
go install github.com/gocn/secscan@v1.4.0
go secscan ./...

该实践使第三方包漏洞平均修复周期从17.3天压缩至3.2天,国产镜像源缓存命中率达92.6%。

跨组织协作成效数据

主体类型 参与项目数 提交PR数 国产模块采纳率 平均响应时效
央企研究院 14 287 68.4% 4.1h
地方政务平台 33 152 81.7% 2.9h
高校实验室 9 89 43.2% 8.7h
初创科技公司 26 311 76.9% 3.5h

企业级落地案例深度剖析

中信证券交易网关系统(Q3 2024上线)基于共建倡议完成全栈国产化改造:

  • 替换原gRPC-Gateway为国产grpc-gw-cn(支持国密TLS 1.3握手);
  • 使用tidb-go-driver v2.1替代MySQL驱动,TPS提升23%,事务一致性通过金融级压测(10万笔/秒持续6小时无丢包);
  • 构建流水线嵌入go-cve-checker插件,自动拦截含CVE-2023-45852风险的golang.org/x/crypto旧版本。

开源治理基础设施演进

mermaid
flowchart LR
A[开发者提交PR] –> B{CI网关}
B –>|含govendor.lock| C[国产依赖解析器]
C –> D[匹配goproxy.cn镜像索引]
C –>|缺失包| E[触发人工审核工单]
D –> F[注入SM4哈希校验头]
F –> G[推送至私有Harbor集群]
G –> H[自动触发K8s灰度发布]

人才协同培养体系

联合浙江大学、电子科技大学开设“Go系统编程特训营”,90天内完成:

  • 编写《国产Go工程实践手册》(含13个真实故障复盘案例);
  • 建立Go语言国产化能力认证(GCAC)考试题库,覆盖RISC-V汇编调试、eBPF扩展开发、国密算法集成等7大能力域;
  • 向21家金融机构输送认证工程师157名,其中89人主导完成核心交易系统Go模块重构。

热爱 Go 语言的简洁与高效,持续学习,乐于分享。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注