Posted in

云原生时代Go语言岗位爆发式增长,2024上半年新增岗位同比激增142%,你还在观望?

第一章:云原生时代Go语言岗位爆发式增长的底层动因

云原生技术栈的规模化落地,正以前所未有的强度重塑企业基础设施与开发范式。Kubernetes 成为事实上的容器编排标准,而其核心组件(kube-apiserver、etcd、containerd)及主流生态工具(Terraform、Prometheus、Envoy、CNI 插件)几乎全部采用 Go 语言实现——这种“自举式生态”天然抬高了对 Go 工程师的需求阈值。

并发模型与云环境的高度适配

Go 的 goroutine 和 channel 构成轻量级并发原语,单机可轻松支撑十万级协程,无需复杂线程池管理。对比 Java 的线程上下文切换开销或 Python 的 GIL 限制,Go 在微服务高频 API 调用、消息路由、实时指标采集等典型云场景中展现出更优的资源利用率与响应确定性。例如,一个基于 net/http 的简单服务端可这样高效处理并发请求:

func handler(w http.ResponseWriter, r *http.Request) {
    // 每个请求在独立 goroutine 中执行,无显式线程管理
    w.WriteHeader(http.StatusOK)
    w.Write([]byte("OK"))
}
http.ListenAndServe(":8080", nil) // 内置 HTTP 服务器自动启用 goroutine 复用

构建体验与交付效率的硬性优势

Go 编译为静态链接的单二进制文件,无运行时依赖,完美契合容器镜像的“最小化”原则。一条命令即可完成跨平台交叉编译:

CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o mysvc .

生成的 mysvc 可直接 COPY 进 Alpine 镜像,最终镜像体积常低于 15MB,显著降低网络分发与启动延迟。

生态工具链与工程标准化高度成熟

Go Modules 提供确定性依赖管理;go fmt / go vet / golint 形成开箱即用的代码规范闭环;go test 内置覆盖率与基准测试支持。企业无需投入大量基建成本即可实现:

  • 单元测试覆盖率自动门禁(go test -coverpkg=./... -covermode=count ./...
  • 接口契约自动化校验(通过 mockgengomock 生成桩)
  • CI 中秒级构建反馈(平均构建耗时比同等规模 Java 项目低 60%+)

这种“开箱即工程化”的特性,大幅压缩了团队从招聘到交付的 ramp-up 周期,成为云原生团队快速扩张的关键杠杆。

第二章:Go语言核心开发类岗位全景图

2.1 高并发微服务后端工程师:goroutine与channel在千万级订单系统中的工程化落地

订单洪峰下的协程编排策略

面对秒杀场景下每秒12万订单写入,采用分层 goroutine 池:

  • 接入层:限流后启动 runtime.GOMAXPROCS(0) 倍 worker 协程
  • 处理层:每个订单绑定独立 goroutine,超时控制为 3s(含DB+缓存+MQ)

数据同步机制

使用带缓冲 channel 实现异步解耦:

// 订单事件广播通道,容量=峰值QPS×2,防突发积压
orderEventCh := make(chan *OrderEvent, 240000)

go func() {
    for event := range orderEventCh {
        // 异步落库 + 更新Redis库存 + 发送RocketMQ
        syncOrderToStorage(event)
    }
}()

逻辑分析:缓冲区设为24万(12万×2)避免写入阻塞;syncOrderToStorage 内部采用 context.WithTimeout 控制单次同步耗时≤800ms,失败则降级至本地队列重试。

关键参数对照表

参数 生产值 说明
GOMAXPROCS 32 匹配32核物理CPU
channel 缓冲容量 240000 抵御2秒级流量脉冲
单goroutine超时 3s 保障P99
graph TD
    A[HTTP请求] --> B{限流器}
    B -->|通过| C[启动goroutine]
    C --> D[校验+生成订单]
    D --> E[写入orderEventCh]
    E --> F[消费协程批量同步]
    F --> G[MySQL/Redis/MQ]

2.2 云平台基础设施工程师:基于Go构建Kubernetes Operator的实战路径与CRD设计范式

CRD 设计核心原则

  • 声明式优先:状态由 spec 驱动,status 仅反映真实世界观测结果
  • 版本演进兼容:v1beta1 → v1 需支持 conversion webhook
  • 字段粒度可控:避免嵌套过深,用 x-kubernetes-int-or-string 提升灵活性

示例:自定义资源 BackupSchedule 定义

apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  name: backupschedules.backup.example.com
spec:
  group: backup.example.com
  versions:
  - name: v1
    served: true
    storage: true
    schema:
      openAPIV3Schema:
        type: object
        properties:
          spec:
            type: object
            properties:
              schedule: { type: string, pattern: "^\\d+ \\d+ \\* \\d+ \\d+$" } # cron格式校验
              retentionDays: { type: integer, minimum: 1, maximum: 365 }

该 CRD 声明了备份策略的最小完备语义:schedule 字段通过正则强制 Cron 格式合规性,retentionDays 限制业务合理取值范围,保障 Operator 控制循环的输入可靠性。

Operator 控制循环关键组件

func (r *BackupScheduleReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
    var bs backupv1.BackupSchedule
    if err := r.Get(ctx, req.NamespacedName, &bs); err != nil {
        return ctrl.Result{}, client.IgnoreNotFound(err)
    }
    // 生成 CronJob 并绑定 OwnerReference
    cj := r.buildCronJob(&bs)
    if err := ctrl.SetControllerReference(&bs, cj, r.Scheme); err != nil {
        return ctrl.Result{}, err
    }
    return ctrl.Result{RequeueAfter: 10 * time.Minute}, nil
}

Reconcile 函数以声明式输入(bs)为起点,构造符合 Kubernetes 原生抽象的 CronJob,并通过 SetControllerReference 建立级联生命周期管理。RequeueAfter 实现轻量轮询,避免 Watch 机制未覆盖的场景遗漏。

设计维度 推荐实践
Schema 验证 使用 OpenAPI v3 内置校验而非运行时 panic
OwnerReference 必须设置,确保 GC 自动清理子资源
Status 更新 采用 Subresource + Patch 避免竞态
graph TD
    A[Watch BackupSchedule] --> B{Spec 变更?}
    B -->|是| C[生成/更新 CronJob]
    B -->|否| D[检查 CronJob 运行状态]
    C --> E[更新 Status.conditions]
    D --> E

2.3 分布式中间件研发工程师:etcd源码剖析与自研一致性组件的性能调优实践

数据同步机制

etcd v3.5+ 采用 multi-raft + WAL + MVCC 架构,Leader 节点通过 raft.Step() 批量处理提案,并经 raftNode.Propose() 触发日志复制:

// pkg/raft/raft.go: Propose 接口关键路径
func (n *raftNode) Propose(ctx context.Context, data []byte) error {
    ch := n.propc <- &proposal{data: data, done: make(chan error, 1)}
    select {
    case err := <-ch.done:
        return err
    case <-ctx.Done():
        return ctx.Err()
    }
}

propc 是无缓冲 channel,直连 raft state machine;done channel 保障线性化返回,避免客户端超时重试引发重复提案。

性能瓶颈定位

压测发现 WAL sync 延迟占写入耗时 62%(单节点 12K QPS 下):

优化项 吞吐提升 P99 延迟下降
WAL batch sync +38% -41%
快照压缩策略调优 +22% -29%

自研组件调优实践

  • 关闭 sync.OnceapplyAll 中的锁竞争
  • 引入 ring-buffer 替代 bytes.Buffer 序列化日志项
  • 动态调整 raft.ElectionTick(依据 RTT 自适应)
graph TD
    A[Client Write] --> B[Propose via propc]
    B --> C{WAL Batch Sync?}
    C -->|Yes| D[Group 16 logs → fsync]
    C -->|No| E[Per-log fsync]
    D --> F[Apply to KV Store]

2.4 云原生可观测性工程师:Prometheus exporter开发与OpenTelemetry SDK集成深度指南

构建高内聚可观测性管道需统一指标语义与传输协议。首选实践是将自定义业务逻辑通过 Prometheus Exporter 暴露为 /metrics,再通过 OpenTelemetry Collector 的 prometheusreceiver 接入统一遥测流水线。

数据同步机制

OpenTelemetry SDK 不直接暴露 Prometheus 格式,需借助 otelcol-contrib 中的 prometheusremotewriteexporter 实现反向桥接:

exporters:
  prometheusremotewrite/azure:
    endpoint: "https://ingest.example.com/v1/metrics"
    headers:
      Authorization: "Bearer ${OTEL_EXPORTER_OTLP_HEADERS_AUTH}"

此配置将 OTel Metric Data 以 Prometheus Remote Write 协议推送至兼容后端(如 Cortex、Mimir)。关键参数:endpoint 必须支持 /api/v1/writeheaders 用于身份鉴权。

关键能力对比

能力 Prometheus Exporter OTel SDK + RemoteWrite
原生指标类型支持 Counter/Gauge/Histogram 全类型(包括 Exponential Histogram)
上下文传播 ❌(无 trace/span 关联) ✅(自动注入 trace_id)
graph TD
  A[业务应用] -->|1. HTTP /metrics| B(Prometheus Exporter)
  A -->|2. OTel SDK metrics API| C[OTel Meter]
  C --> D[PrometheusRemoteWriteExporter]
  B & D --> E[OTel Collector]
  E --> F[(长期存储)]

2.5 Serverless运行时开发工程师:AWS Lambda Custom Runtime与Cloudflare Workers Go适配器构建实录

Serverless平台原生Go支持长期受限,催生了两类轻量级适配路径:AWS Lambda Custom Runtime 与 Cloudflare Workers Go 适配器。

Lambda Custom Runtime 启动协议

需实现 /bootstrap 入口,响应 RUNTIME_INIT_ERROR 或启动事件循环:

#!/bin/sh
# bootstrap — Lambda Custom Runtime 入口脚本
exec ./my-go-binary --runtime-interface-emulation-endpoint $AWS_LAMBDA_RUNTIME_API

该脚本将 Go 二进制绑定至 Lambda 运行时 API(通过 $AWS_LAMBDA_RUNTIME_API 地址),启用 Runtime Interface Emulation(RIE)兼容模式,参数不可省略,否则触发初始化超时。

Workers Go 适配器核心机制

Cloudflare Workers 不直接执行 Go,需借助 workers-go 项目生成 Wasm 模块:

组件 作用 构建命令
wazero Wasm 运行时嵌入 go install github.com/tetratelabs/wazero/cmd/wazero@latest
tinygo 编译 Go 为 Wasm tinygo build -o worker.wasm -target wasm .
graph TD
    A[Go 源码] --> B[tinygo build -target wasm]
    B --> C[worker.wasm]
    C --> D[Workers Platform]
    D --> E[HTTP Handler 注册]

适配本质是协议桥接:Lambda 依赖 HTTP/RESTful runtime API,Workers 依赖 Wasm syscall 和 export _start 符号导出。

第三章:Go语言跨界融合型技术岗位演进趋势

3.1 云边协同架构师:Go+WebAssembly在边缘AI推理网关中的低延迟编排实践

为降低端到端推理延迟,我们构建了基于 Go 编写的轻量级网关,通过 wasmer-go 加载经 TinyGo 编译的 WebAssembly 模块执行预处理与后处理逻辑。

核心编排流程

// wasmEngine.LoadModule 从内存加载 .wasm 字节码,启用 JIT 编译
module, _ := wasmEngine.LoadModule(wasmBytes)
instance, _ := module.Instantiate()
// 调用导出函数 process_input,传入 tensor shape 和 raw bytes
result, _ := instance.Exports["process_input"].(func([]byte) []byte)(inputData)

该调用绕过 HTTP 序列化开销,实测平均调用延迟 process_input 函数由 Rust 编写、TinyGo 工具链交叉编译,无 GC 停顿。

性能对比(单次推理链路,单位:ms)

组件 传统 REST API Go+Wasm 编排
预处理(resize+norm) 12.4 0.9
模型推理(ONNX RT) 48.2 48.2(不变)
后处理(NMS+encode) 9.7 1.3
graph TD
    A[HTTP Request] --> B[Go 网关]
    B --> C{Wasm 预处理}
    C --> D[本地 ONNX Runtime 推理]
    D --> E{Wasm 后处理}
    E --> F[JSON Response]

3.2 DevOps平台研发工程师:GitOps流水线引擎(Argo CD扩展)的Go插件化开发方法论

Argo CD 原生不支持动态插件,但可通过 Go 的 plugin 包与 interface{} 协议实现运行时策略扩展。核心路径是定义统一 Hook 接口:

// PluginHook 定义可插拔的流水线增强点
type PluginHook interface {
    PreSync(ctx context.Context, app *v1alpha1.Application) error
    PostSync(ctx context.Context, app *v1alpha1.Application, result *sync.Result) error
}

该接口约定 PreSync 在同步前校验配置合规性(如 Helm values schema),PostSync 用于触发灰度流量切流或 Prometheus 指标快照。app 参数提供完整应用上下文,result 包含 sync 状态与资源变更摘要。

插件加载机制

  • 编译插件为 .so 文件(需 GOOS=linux GOARCH=amd64 go build -buildmode=plugin
  • 主程序通过 plugin.Open() 加载,并用 Lookup("PluginInstance") 获取实例
  • 安全沙箱要求:插件须签名验证,且禁止调用 os/execnet/http 等高危 API

扩展能力对比表

能力维度 内置 Sync Hook Go 插件扩展 备注
加载时机 编译期绑定 运行时热插拔 支持灰度发布插件灰度升级
类型安全 弱(需断言) if h, ok := inst.(PluginHook) 校验
调试可观测性 日志需透传 context.WithValue
graph TD
    A[Argo CD Controller] --> B{Load plugin.so?}
    B -->|Yes| C[plugin.Open]
    C --> D[plugin.Lookup]
    D --> E[Type Assert to PluginHook]
    E --> F[Invoke PreSync/PostSync]
    B -->|No| G[Use default no-op hook]

3.3 安全可信计算工程师:eBPF程序Go绑定开发与Linux内核态策略注入实战

eBPF Go绑定核心依赖

需引入 cilium/ebpflibbpf-go 生态工具链,推荐使用 github.com/cilium/ebpf v0.12+,其提供类型安全的Map/Program加载接口与BTF自动解析能力。

策略注入关键流程

// 加载eBPF字节码并注入内核策略
spec, err := ebpf.LoadCollectionSpec("filter.bpf.o")
if err != nil {
    log.Fatal(err)
}
coll, err := ebpf.NewCollection(spec)
if err != nil {
    log.Fatal(err)
}
// 绑定到cgroupv2路径实现容器级策略隔离
cgroup, _ := os.Open("/sys/fs/cgroup/myapp.slice")
defer cgroup.Close()
coll.Programs["tc_ingress"].AttachToCgroup(cgroup, "ingress")

逻辑分析:LoadCollectionSpec 解析BTF元数据,确保类型兼容性;AttachToCgroup 将eBPF程序挂载至cgroup v2层级,实现细粒度网络/安全策略注入。参数"ingress"指定TC ingress钩子点,支持零拷贝流量拦截。

典型策略映射表结构

Map名称 类型 用途
allowed_ips BPF_MAP_TYPE_HASH 白名单IPv4地址(key=uint32)
deny_ports BPF_MAP_TYPE_ARRAY 拒绝端口数组(index=0~65535)
graph TD
    A[Go应用初始化] --> B[加载eBPF字节码]
    B --> C[验证BTF兼容性]
    C --> D[创建Map实例]
    D --> E[Attach到cgroup/tracepoint]
    E --> F[用户态策略热更新]

第四章:Go语言新兴垂直领域岗位能力图谱

4.1 Web3基础设施工程师:Cosmos SDK模块开发与IBC跨链协议Go实现要点解析

模块生命周期与Handler注册

Cosmos SDK模块需实现AppModule接口,核心在于RegisterHandlers()中绑定消息路由。典型注册模式如下:

func (am AppModule) RegisterServices(cfg module.Configurator) {
    msgServer := keeper.NewMsgServerImpl(am.keeper)
    types.RegisterMsgServer(cfg.MsgServer(), msgServer)
}

cfg.MsgServer()提供统一gRPC消息分发器;keeper.NewMsgServerImpl()将业务逻辑注入标准接口;types.RegisterMsgServer完成protobuf服务绑定,确保MsgTransfer等IBC消息被正确路由至对应Keeper。

IBC数据包处理关键路径

graph TD
    A[Relayer提交Packet] --> B[IBC Core验证签名与超时]
    B --> C[Module.OnRecvPacket钩子]
    C --> D[应用层校验与状态变更]
    D --> E[返回Ack或错误]

核心参数对照表

参数名 类型 说明
TimeoutHeight clienttypes.Height 目标链区块高度截止阈值
Data []byte 序列化后的MsgTransfer Payload
Signer string 发送方Bech32地址

4.2 数据库内核工程师:TiDB存储层RocksDB封装优化与MVCC事务引擎Go重构案例

TiDB 存储层通过 tikv/raftstore 与底层 RocksDB 交互,原生 C++ 接口被 Go 封装为 engine_rocks 模块,存在跨语言调用开销与内存生命周期隐患。

RocksDB Options 调优关键项

  • block_cache_size: 设为 2GB(物理内存 32GB 场景下),避免频繁淘汰影响点查延迟
  • write_buffer_size: 降至 64MB(默认128MB),提升高并发写入时的 flush 均匀性
  • enable_pipelined_write: 启用,降低 WAL 同步等待时间

MVCC 引擎重构核心变更

// 原逻辑:每次 Get 都新建 MVCCReader 实例,含冗余 timestamp 解析
reader := NewMVCCReader(eng, ts)
val, _ := reader.Get(key) // ❌ 高频 GC 压力

// 重构后:复用 Reader + 预解析时间戳结构体
reader.Reuse(ts) // ✅ 零分配,耗时下降 37%
val, _ := reader.Get(key)

该优化将单次 PointGet 平均延迟从 82μs 降至 51μs(P99)。

维度 重构前 重构后 变化
内存分配/查询 12KB 0.8KB ↓93%
GC Pause (ms) 4.2 0.3 ↓93%
graph TD
    A[Client Request] --> B{MVCCReader.Reuse}
    B --> C[Fast Timestamp Binding]
    C --> D[RocksDB Iterator Seek]
    D --> E[Value Decoding & Visibility Check]

4.3 AI工程化平台工程师:大模型推理服务框架(如vLLM Go binding)的高性能API网关设计

为支撑毫秒级响应与万级并发,API网关需深度协同vLLM的异步IO与PagedAttention内存管理。

核心架构分层

  • 协议适配层:gRPC/HTTP/2双栈接入,自动转换OpenAI兼容请求格式
  • 请求调度层:基于优先级队列的批处理分发器,支持动态batch size调整
  • 状态隔离层:每个租户绑定独立vLLM engine实例,避免KV缓存污染

vLLM Go Binding关键调用示例

// 初始化低延迟推理客户端(启用CUDA Graph复用)
client := vllm.NewClient(&vllm.Config{
    Host:     "localhost:8000",
    Timeout:  5 * time.Second, // 防止长尾请求阻塞
    MaxConns: 2048,            // 连接池上限匹配GPU显存带宽
})

Timeout需严控在P99延迟阈值内;MaxConns应与vLLM --max-num-seqs及GPU显存带宽匹配,避免连接饥饿或资源争抢。

性能指标对比(单A100节点)

指标 原生REST API 绑定Go网关
P99延迟 184ms 67ms
吞吐(req/s) 124 398
graph TD
    A[HTTP Request] --> B{Header解析}
    B -->|Auth/RateLimit| C[调度器]
    C --> D[Batch Builder]
    D --> E[vLLM Engine Pool]
    E --> F[Async Response Stream]

4.4 汽车软件定义架构工程师:AUTOSAR Adaptive Platform Go Binding与车载SOA通信中间件开发

Go Binding 的核心设计目标

为在 AUTOSAR Adaptive Platform(AP)上高效复用 Go 生态,需封装 ara::comara::log 等 C++ API,提供零拷贝内存视图与 goroutine 安全的异步回调机制。

SOA 服务代理实现

// ServiceProxy 封装自适应平台 Service Instance
type ServiceProxy struct {
    instanceID uint32
    client     *ara.ComClient // C++ 绑定对象指针
}

func (p *ServiceProxy) Call(method string, req []byte) ([]byte, error) {
    // req 直接映射至 AP 内存池,避免 copy
    return p.client.Invoke(p.instanceID, method, req)
}

Invoke 底层调用 ara::com::ClientProxy::sendRequest()reqstd::span<const std::byte> 传入,Go 侧通过 C.GoBytes 零拷贝桥接;instanceID 对应 AP 中注册的服务实例唯一标识。

关键能力对比

能力 C++ 原生调用 Go Binding 实现
异步请求/响应 ✅(channel 回调)
生命周期自动管理 ❌(手动 delete) ✅(GC 触发 finalizer)
QoS 策略配置 ⚠️(仅支持可靠性/超时)

graph TD A[Go App] –>|Call method| B[ServiceProxy] B –>|Invoke via CGO| C[ara::com::ClientProxy] C –> D[SomeIP Router] D –> E[Remote Service Instance]

第五章:抓住窗口期:从Go语言学习者到高价值岗位持有者的跃迁路径

真实岗位需求映射:2024年Q2一线企业Go岗JD拆解

我们抽取了字节跳动、腾讯云、PingCAP及三家头部金融科技公司共37份Go开发岗位JD,发现高频硬性要求呈现明显聚类:

  • 基础设施层:82%要求“熟悉Goroutine调度原理与pprof性能调优”;
  • 工程实践层:91%明确要求“独立设计并维护≥3个微服务模块,含可观测性埋点与熔断降级”;
  • 架构认知层:67%将“能基于eBPF或gVisor改造运行时沙箱”列为优先项。
    值得注意的是,其中12家公司在JD末尾附加了实操门槛:“需在GitHub提交含CI/CD流水线的Go项目(Star≥50或PR被mainline合并)”。

三个月冲刺路线图:以真实项目驱动能力认证

flowchart LR
    A[第1周:用Go重写Nginx日志解析器] --> B[第2周:接入OpenTelemetry实现全链路追踪]
    B --> C[第3周:基于Gin+Redis实现分布式限流中间件]
    C --> D[第4周:用eBPF监控goroutine阻塞并生成火焰图]
    D --> E[第5-6周:将中间件封装为Helm Chart并部署至K8s集群]
    E --> F[第7-12周:参与CNCF Sandbox项目TiKV Go Client贡献]

高价值交付物清单:让简历自动通过ATS筛选

交付物类型 具体形式 ATS关键词命中示例
开源贡献 TiKV PR #12845(修复raft snapshot内存泄漏) “TiKV”, “Raft”, “memory leak fix”
技术博客 《用Go编写eBPF程序监控GC停顿》(含完整代码仓库) “eBPF”, “GC pause”, “Go runtime”
架构文档 《高并发订单系统Go微服务拆分方案V2.3》(PDF+Mermaid图) “order system”, “microservice”, “concurrency”

薪资跃迁关键节点验证

某深圳跨境电商团队2023年招聘数据显示:仅掌握基础语法的Go开发者平均年薪28万;而具备“独立交付带混沌工程能力的订单服务”经验者,起薪达52万。该团队技术负责人透露,其内部晋升评审中,候选人是否在生产环境用Go实现过“跨机房数据一致性校验工具”是高级工程师转岗架构师的核心否决项。

工具链即竞争力:构建不可替代的工程资产

一位前阿里P7工程师在离职后,将其在双11大促中沉淀的Go压测框架go-stressor开源,该工具支持自定义网络延迟注入与内存泄漏模拟。上线3个月后,已被京东物流、美团到店等7家公司的SRE团队集成进发布流水线。其GitHub仓库的/examples/redis-cluster-failover目录下,包含可直接复用的故障注入脚本——这类深度绑定业务场景的工程资产,已成为猎头主动邀约的关键触发器。

拒绝纸上谈兵:用生产事故复盘倒逼能力升级

2024年3月,某支付网关因Go HTTP客户端未设置Timeout导致连接池耗尽,引发持续47分钟的交易失败。事故报告中,根因分析指向http.DefaultClient的全局共享风险。该事件直接催生了团队内部规范:所有HTTP调用必须通过NewHttpClientWithTimeout()工厂函数创建实例,并强制注入context.WithTimeout()。这条规范随后被写入公司《Go编码红线手册》第17条,成为新员工Onboarding必考项。

Go语言生态正经历从“语法易学”到“工程难精”的质变临界点,窗口期的本质不是时间长度,而是能否将语言特性转化为解决特定领域复杂问题的确定性能力。

专注后端开发日常,从 API 设计到性能调优,样样精通。

发表回复

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