第一章:北京Golang兼职市场结构性洗牌的底层动因
北京Golang兼职生态正经历一场静默而深刻的重构——驱动这场洗牌的并非短期供需波动,而是技术演进、企业用工逻辑与开发者职业路径三重力量的共振。
开源基础设施成熟度跃迁
过去三年,CNCF毕业项目中Go语言主导的组件占比达68%(如Kubernetes、etcd、Prometheus),大幅降低中小团队自研中间件门槛。企业不再为“能否用Go写高并发服务”付费,转而聚焦“能否用Go快速集成云原生栈”。这直接导致兼职需求从基础CRUD开发,转向Service Mesh配置治理、eBPF可观测性插件开发等高阶能力。
企业用工模型精细化升级
传统按人天计费的外包模式正在瓦解,取而代之的是成果交付契约。典型案例如:
- 某AI SaaS公司发布「API网关限流策略迁移」任务,明确要求提交含OpenTelemetry埋点的Go模块+性能压测报告(wrk -t4 -c100 -d30s http://localhost:8080/api);
- 招标方自动执行CI验证:
go test -race -coverprofile=coverage.out ./... && go tool cover -func=coverage.out | grep "total:",覆盖率低于85%即拒收。
开发者能力认证体系去中心化
| GitHub Star数与PR合并量已成硬通货。观察2024年Q2北京Golang兼职平台数据: | 能力信号 | 兼职邀约率提升 | 关键动作示例 |
|---|---|---|---|
| 主导开源项目维护 | +210% | git log --author="name" --oneline | wc -l ≥500 |
|
| Go泛型实战应用 | +175% | 代码中出现type Container[T any]结构 |
这种结构性位移意味着:仅掌握net/http和goroutine基础语法的开发者,正被自动过滤出主流需求池。真正的入场券,是能用Go工具链解决云原生场景中的具体摩擦点——比如用gopls定制化诊断规则,或通过go:embed优化静态资源热更新流程。
第二章:从CRUD接单者到领域建模工程师的能力跃迁路径
2.1 DDD核心概念在Golang项目中的落地实践:值对象、聚合根与仓储接口设计
值对象:不可变与相等性语义
值对象应无身份标识,仅由属性组合定义相等性。Golang中通过结构体+私有字段+构造函数实现:
type Money struct {
amount int64 // 单位:分(避免浮点误差)
currency string // 如 "CNY"
}
func NewMoney(amount int64, currency string) Money {
return Money{amount: amount, currency: currency}
}
func (m Money) Equals(other Money) bool {
return m.amount == other.amount && m.currency == other.currency
}
amount 使用 int64 避免浮点精度问题;currency 限定为 ISO 4217 标准码;Equals 方法确保值语义比较,不依赖指针地址。
聚合根:强一致性边界
订单(Order)作为聚合根,内聚管理订单项(OrderItem),禁止外部直接修改其子实体:
type Order struct {
id OrderID
items []OrderItem // 只读切片,仅通过AddItem变更
status OrderStatus
createdAt time.Time
}
func (o *Order) AddItem(productID ProductID, quantity uint) error {
if o.status != Draft {
return errors.New("cannot modify order in non-draft status")
}
o.items = append(o.items, NewOrderItem(productID, quantity))
return nil
}
AddItem 封装业务规则(如状态校验),保障聚合内数据一致性;items 不暴露 setter,防止越界修改。
仓储接口:面向领域契约
仓储抽象需聚焦领域语义,而非技术细节:
| 方法签名 | 语义说明 | 实现约束 |
|---|---|---|
Save(ctx context.Context, order *Order) error |
持久化整个聚合(含一致性校验) | 必须保证原子性与版本控制 |
FindByID(ctx context.Context, id OrderID) (*Order, error) |
按聚合根ID加载完整聚合 | 不得返回部分数据或裸DB模型 |
数据同步机制
领域事件驱动最终一致性:
graph TD
A[OrderCreated] --> B[InventoryService]
A --> C[NotificationService]
B --> D[UpdateStock]
C --> E[SendEmail]
事件发布由聚合根触发,仓储实现负责事务内事件注册,确保“先落库、再发事件”。
2.2 基于Go泛型与接口抽象的限界上下文划分与跨域通信实现
限界上下文(Bounded Context)在DDD中需通过清晰契约隔离领域边界。Go泛型配合接口抽象,可构建类型安全、可复用的跨域通信骨架。
领域事件泛型接口定义
// Event[T] 是跨上下文传递的强类型事件基底
type Event[T any] interface {
AggregateID() string
Timestamp() time.Time
Payload() T
}
// 示例:订单已支付事件
type OrderPaid struct {
OrderID string `json:"order_id"`
Amount float64 `json:"amount"`
Currency string `json:"currency"`
}
该设计确保事件结构统一、反序列化类型安全;Payload() 方法解耦具体业务数据,避免上下文间直接依赖实体。
跨域通信契约表
| 组件 | 职责 | 实现约束 |
|---|---|---|
| Publisher | 发布领域事件 | 仅依赖 Event[T] 接口 |
| EventBus | 路由至订阅上下文 | 泛型注册 func(e Event[T]) |
| Subscriber | 实现上下文专属处理逻辑 | 接收具体 OrderPaid 类型 |
数据同步机制
graph TD
A[OrderContext] -->|OrderPaid Event| B[EventBus]
B --> C[InventoryContext]
B --> D[NotificationContext]
C -->|DecrementStock| E[(Inventory DB)]
D -->|SendSMS| F[(Third-party SMS API)]
2.3 Golang微服务中事件风暴建模到CQRS模式的代码映射全流程
事件风暴是领域驱动设计(DDD)中提炼业务语义的关键实践。在Golang微服务中,需将识别出的领域事件、命令与聚合根,精准映射为CQRS架构中的读写分离组件。
领域事件定义与结构化建模
// OrderPlaced 作为风暴中识别的核心事件,携带业务上下文
type OrderPlaced struct {
ID string `json:"id"` // 全局唯一订单ID(由命令生成)
CustomerID string `json:"customer_id"`
Items []Item `json:"items"`
Timestamp time.Time `json:"timestamp"`
}
// Item 是值对象,不可变,体现事件溯源完整性
type Item struct {
SKU string `json:"sku"`
Qty int `json:"qty"`
Price float64 `json:"price"`
}
该结构严格遵循事件不可变性原则;ID 由命令侧生成并传递,确保事件溯源链可追溯;Timestamp 由事件发布方注入,统一时序基准。
CQRS组件映射关系
| 风暴产出元素 | CQRS角色 | Go实现载体 |
|---|---|---|
| 命令(PlaceOrder) | Command Handler | cmd.PlaceOrderHandler |
| 聚合根(Order) | Write Model | domain.Order(含Apply/Validate) |
| 事件(OrderPlaced) | Event Stream | eventstore.WriteEvent() |
| 查询(GetOrderByID) | Query Handler | query.OrderReadRepository |
数据同步机制
使用github.com/ThreeDotsLabs/watermill构建事件驱动管道:
// 订阅OrderPlaced事件,触发读模型更新
router.AddHandler(
"order-placed-handler",
"orders",
"processed-orders",
&OrderProjection{},
)
OrderProjection 实现 watermill.Handler 接口,将事件状态反向同步至PostgreSQL只读表,保障最终一致性。
2.4 使用Wire+DDD分层架构重构遗留CRUD项目的实战案例拆解
某电商订单管理模块原为Spring Boot单体CRUD,耦合严重、扩展困难。重构目标:解耦核心域逻辑,提升可测试性与演进弹性。
领域分层映射
interface/:HTTP API与DTO转换application/:用例编排(如CreateOrderUseCase)domain/:聚合根Order+ 值对象OrderId、Moneyinfrastructure/:JPA适配器 + Redis库存预扣减
Wire依赖注入关键片段
// wire.go
func InitializeOrderApp() (*App, error) {
wire.Build(
repository.NewOrderRepository,
application.NewCreateOrderUseCase,
interface.NewOrderHandler,
wire.Struct(new(App), "*"),
)
return nil, nil
}
逻辑分析:Wire在编译期生成无反射的DI代码;
NewOrderRepository接收*gorm.DB参数,由wire.Value()或wire.ProviderSet注入;避免运行时错误,提升启动性能。
分层职责对比(重构前后)
| 维度 | 遗留CRUD | Wire+DDD重构 |
|---|---|---|
| 业务逻辑位置 | Controller内嵌 | Domain聚合根方法 |
| 数据访问 | Service直连Mapper | Repository接口隔离 |
| 依赖方向 | 上层依赖下层+循环 | 严格依赖倒置(六边形) |
graph TD
A[HTTP Handler] –> B[UseCase]
B –> C[Domain Service]
C –> D[Repository Interface]
D –> E[(DB/Cache)]
E -.->|适配实现| D
2.5 北京典型外包团队DDD转型失败复盘:技术债、组织墙与领域语言断层
技术债的雪球效应
团队在核心订单模块仍依赖单体SQL Server存储过程,耦合支付、库存、物流逻辑:
-- ❌ 违反限界上下文边界:跨域逻辑硬编码
CREATE PROCEDURE UpdateOrderStatus
@OrderId INT,
@NewStatus VARCHAR(20) -- 'PAID'/'SHIPPED'/'CANCELLED'
AS
BEGIN
UPDATE Orders SET Status = @NewStatus WHERE Id = @OrderId;
-- ⚠️ 直接调用库存DB更新,绕过InventoryContext契约
EXEC InventoryDB.dbo.DecreaseStock @OrderId;
END
该存储过程隐式承担了订单状态机、库存扣减、物流触发三重职责,导致Order聚合根无法封装业务不变量,每次状态变更都需协调三方数据库事务,最终引发分布式一致性故障。
组织墙与领域语言断层
| 角色 | 使用术语 | 实际含义 |
|---|---|---|
| 外包开发 | “下单成功” | OrderCreated事件未发布 |
| 客户BA | “已发货” | 物流系统ShipmentId为空 |
| 运维DBA | “主键冲突” | OrderId在支付/订单库重复生成 |
转型阻塞根因
graph TD
A[客户只签功能交付合同] --> B[无领域建模工时预算]
C[外包团队按人天计费] --> D[拒绝重构旧代码]
B & D --> E[统一语言无法落地]
E --> F[限界上下文边界持续模糊]
第三章:可观测性不是运维的事——Golang开发者必须掌握的三大支柱
3.1 OpenTelemetry Go SDK深度集成:Trace上下文透传与Span生命周期管理
Trace上下文透传机制
Go SDK通过context.Context携带span与traceID,实现跨goroutine、HTTP、gRPC等边界传递。关键依赖otel.GetTextMapPropagator().Inject()与.Extract()完成W3C TraceContext序列化。
Span生命周期管理要点
- Span创建后必须显式结束(
span.End()),否则内存泄漏 WithSpanFromContext()可安全复用父Span上下文- 异步任务需使用
otel.WithSpan()确保上下文绑定
HTTP请求透传示例
func handler(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
// 从HTTP Header提取trace上下文
spanCtx := otel.GetTextMapPropagator().Extract(ctx, r.Header)
ctx = trace.ContextWithRemoteSpanContext(ctx, spanCtx)
// 创建子Span
tracer := otel.Tracer("example/http")
ctx, span := tracer.Start(ctx, "handle-request")
defer span.End() // 必须调用,触发上报与清理
// ...业务逻辑
}
tracer.Start()返回带新Span的ctx;span.End()触发状态快照、属性刷新及异步导出。未调用则Span滞留于内存中,且无法被Exporter采集。
| 方法 | 作用 | 是否必需 |
|---|---|---|
Start() |
创建并激活Span | ✅ |
End() |
终止Span并提交数据 | ✅ |
RecordError() |
标记错误状态 | ⚠️(推荐) |
graph TD
A[HTTP Request] --> B[Extract Context]
B --> C[Start Span]
C --> D[Business Logic]
D --> E[Record Metrics/Logs]
E --> F[End Span]
F --> G[Export via BatchSpanProcessor]
3.2 Prometheus指标建模实战:从HTTP请求延迟直方图到业务语义指标(如“订单履约耗时P95”)
直方图基础:HTTP延迟采集
Prometheus histogram 天然支持分位数估算,需预先定义桶(buckets):
# http_request_duration_seconds_bucket{le="0.1"} 1200
# http_request_duration_seconds_bucket{le="0.2"} 1850
# http_request_duration_seconds_bucket{le="+Inf"} 2000
http_request_duration_seconds_bucket{path="/api/order", le="0.2"} 1850
http_request_duration_seconds_sum{path="/api/order"} 342.6
http_request_duration_seconds_count{path="/api/order"} 2000
le 标签表示“小于等于该值的请求数”,sum 与 count 支持计算平均延迟;但原始桶数据无法直接表达“订单履约P95”。
业务语义映射:从桶到P95
使用 histogram_quantile() 函数提取业务指标:
# 计算订单接口95分位延迟(秒)
histogram_quantile(0.95, sum by (le) (
rate(http_request_duration_seconds_bucket{job="order-service", path="/api/fulfill"}[5m])
))
rate(...[5m])消除计数器重置影响sum by (le)聚合所有实例/副本的桶数据0.95为分位数目标,结果自动插值(非原始桶边界)
关键建模原则
- ✅ 指标命名体现业务域(
order_fulfillment_duration_seconds) - ✅ 标签设计支持多维下钻(
status_code,region,product_type) - ❌ 避免在客户端硬编码分位数——交由PromQL动态计算
| 维度 | 建议标签值示例 | 用途 |
|---|---|---|
| 履约阶段 | validate, pick, pack |
定位瓶颈环节 |
| 订单类型 | normal, rush, return |
差异化SLA监控 |
| 渠道来源 | app, web, partner |
渠道性能对比 |
语义增强:P95指标注册为独立指标
# 在Exporter中主动暴露语义指标(可选增强)
order_fulfillment_p95_seconds{region="cn-east", tier="gold"} 4.21
此举提升告警与看板可读性,但需权衡存储开销与实时性。
3.3 日志结构化与上下文注入:Zap+OpenTelemetry LogBridge在K8s环境中的调试价值
在Kubernetes动态调度场景下,传统文本日志难以关联Pod漂移前后的请求链路。Zap通过zap.String("trace_id", traceID)原生支持字段注入,配合OpenTelemetry LogBridge可将trace_id、span_id、service.name等上下文自动注入日志条目。
数据同步机制
LogBridge通过OTLP/gRPC将Zap日志转换为LogRecord协议格式,并与Trace/Metric信号对齐时间戳与资源属性:
// 初始化带OTel上下文的Zap logger
logger := zap.New(zapcore.NewCore(
otelzap.NewCoreEncoder(), // 自动注入trace_id等字段
zapcore.AddSync(&otlplog.Exporter{}),
zapcore.DebugLevel,
))
// 注入当前span上下文(需在span活跃生命周期内调用)
ctx := context.WithValue(context.Background(), otelzap.SpanContextKey, span.SpanContext())
logger.WithOptions(zap.AddContext(ctx)).Info("request processed")
上述代码中,
otelzap.NewCoreEncoder()重写了编码逻辑,在序列化时自动提取SpanContext中的TraceID()和SpanID();AddContext确保跨goroutine传递上下文,避免K8s Pod重启导致的上下文丢失。
关键字段映射表
| Zap字段名 | OTel语义约定 | K8s调试价值 |
|---|---|---|
trace_id |
trace_id |
关联分布式追踪与日志时间线 |
pod_name |
k8s.pod.name |
快速定位异常Pod实例 |
namespace |
k8s.namespace.name |
按命名空间隔离日志分析范围 |
graph TD
A[Zap Logger] -->|结构化JSON| B[LogBridge]
B -->|OTLP/gRPC| C[OTel Collector]
C --> D[Jaeger UI + Loki]
D --> E[Trace-ID联动检索]
第四章:北京Golang兼职市场的硬核能力验证体系
4.1 面向交付的DDD能力自测表:10道场景题覆盖战略设计到战术编码
场景题示例:订单超时自动取消
当订单创建30分钟后未支付,需触发状态变更与库存释放:
// 基于领域事件的超时处理(使用Spring State Machine + Saga)
@DomainEvent
public record OrderPaymentTimeout(OrderId orderId) {}
@Component
public class OrderTimeoutHandler {
public void handle(OrderPaymentTimeout event) {
orderRepository.findById(event.orderId())
.ifPresent(order -> {
order.expire(); // 调用聚合根内建业务逻辑
inventoryService.releaseHold(order.items()); // 外部服务协同
publish(new InventoryReleased(event.orderId())); // 发布补偿事件
});
}
}
该实现体现聚合边界清晰性(order.expire()封装状态迁移)、防腐层隔离(inventoryService抽象外部依赖)及最终一致性保障(事件驱动而非强事务)。
自测维度分布(节选)
| 维度 | 题号 | 覆盖层级 |
|---|---|---|
| 边界上下文划分 | 1–3 | 战略设计 |
| 聚合设计合理性 | 4–6 | 战术建模 |
| 领域服务协作 | 7–9 | 编码实践 |
| 事件溯源落地 | 10 | 架构演进 |
核心判断逻辑流
graph TD
A[识别业务动因] --> B{是否跨限界上下文?}
B -->|是| C[引入防腐层/发布集成事件]
B -->|否| D[在聚合内完成状态变更]
D --> E[校验不变量]
E --> F[触发领域事件]
4.2 可观测性实操考核:给定一段含panic的Gin中间件,要求补全TraceID注入+Error分类上报+Metrics打点
中间件骨架与panic触发点
func RecoveryWithObservability() gin.HandlerFunc {
return func(c *gin.Context) {
defer func() {
if err := recover(); err != nil {
// TODO: 注入TraceID、分类上报错误、记录metrics
log.Printf("panic: %v", err)
}
}()
c.Next()
}
}
关键能力补全清单
- ✅ 从
c.Request.Header提取或生成X-Request-ID(TraceID) - ✅ 将panic按类型分为
system_panic/logic_panic/third_party_panic三类上报至统一错误平台 - ✅ 使用Prometheus
CounterVec记录http_panic_total{type="system",route="/api/v1/users"}
Metrics打点示例
var panicCounter = promauto.NewCounterVec(
prometheus.CounterOpts{Namespace: "app", Name: "panic_total"},
[]string{"type", "route"},
)
// 在recover块中调用:
panicCounter.WithLabelValues("system_panic", c.FullPath()).Inc()
该行将panic按语义类型与路由路径双维度聚合,支撑根因定位。TraceID通过opentelemetry-go的trace.SpanFromContext(c.Request.Context())安全获取,避免nil panic。
4.3 北京真实兼职需求解析:某跨境电商SaaS后台重构需求的技术响应模板(含架构图+关键接口签名)
架构演进路径
原单体Java应用(Spring Boot 2.3)耦合订单、库存、跨境报关逻辑;重构采用领域驱动分层+事件驱动编排,核心模块解耦为order-core、inventory-adapter、customs-gateway三个独立服务,通过Kafka Topic order.created.v2 实现最终一致性。
// 关键接口签名:跨境订单创建入口(幂等+防重)
@PostMapping("/v2/orders")
public ResponseEntity<OrderResponse> createCrossBorderOrder(
@RequestBody @Valid OrderCreateRequest request, // 含HS编码、目的国、收货人清关资质ID
@RequestHeader("X-Trace-ID") String traceId) { // 强制链路追踪标识
return orderService.createAsync(request, traceId);
}
该接口强制校验request.customsCertId有效性(调用/certs/validate同步鉴权),并触发本地事务写入orders表后发布Kafka事件。traceId用于全链路日志聚合与异常回溯。
数据同步机制
| 模块 | 同步方式 | 延迟容忍 | 触发条件 |
|---|---|---|---|
| 库存扣减 | Kafka Event + 补偿任务 | ≤2s | order.created.v2 → inventory.deduct |
| 报关单生成 | HTTP同步调用(超时800ms) | 0ms | 订单状态变更为CONFIRMED |
graph TD
A[Web Gateway] -->|POST /v2/orders| B[Order-Core]
B -->|TX commit + Kafka publish| C[(Kafka: order.created.v2)]
C --> D[Inventory-Adapter]
C --> E[Customs-Gateway]
D -->|ACK| B
E -->|HTTP 201| B
4.4 兼职报价与价值锚定:基于DDD复杂度系数与可观测性实施成本的双向定价模型
传统按人天报价易忽视领域建模深度与运维负债。我们引入双向锚定机制:左侧锚定DDD复杂度系数(DCC),量化限界上下文数量、聚合根耦合度、领域事件扇出比;右侧锚定可观测性实施成本(OIC),覆盖指标采集粒度、链路追踪覆盖率、日志结构化等级。
DCC计算示例
def calculate_dcc(bounded_contexts: int,
avg_aggregate_coupling: float,
event_fanout_ratio: float) -> float:
# 基础复杂度:上下文数 × 耦合衰减因子(0.8~1.2)
base = bounded_contexts * (1.0 + (avg_aggregate_coupling - 1.0) * 0.5)
# 事件放大效应:每单位扇出增加0.3复杂度权重
return round(base + event_fanout_ratio * 0.3, 2)
逻辑分析:avg_aggregate_coupling取值范围[0.5, 2.0],反映聚合间依赖强度;event_fanout_ratio为单事件平均触发下游服务数,直接抬升调试与一致性保障成本。
OIC成本维度
| 维度 | L1(基础) | L2(标准) | L3(生产级) |
|---|---|---|---|
| 指标采集 | Prometheus默认指标 | 自定义业务指标+SLI | 实时异常检测+预测告警 |
| 链路追踪 | 单服务入口埋点 | 全链路透传 | 跨云/跨协议无损追踪 |
双向定价公式
graph TD
A[DCC输入] --> B[领域建模深度评估]
C[OIC输入] --> D[可观测性基建负载]
B & D --> E[加权融合:Price = DCC×12k + OIC×8k]
报价最终由二者线性加权生成,确保技术深度与运维可持续性同步定价。
第五章:写在洗牌之后:一个理性、可持续的Golang兼职生态正在形成
过去三年,Golang兼职市场经历了剧烈震荡:2021年“高薪抢人潮”催生大量虚假项目与空壳外包工作室;2022年多家平台因资金链断裂关停,超1700名自由开发者遭遇尾款拖欠;2023年Q4起,监管介入+甲方预算收紧+技术栈理性回归,倒逼生态自我净化。如今,一个以真实交付能力为锚点、以长期协作信任为纽带的新生态已具雏形。
真实案例:杭州「云栈工坊」的闭环协作模型
该团队由6名全职Golang工程师与12名经背调认证的兼职开发者组成,专注SaaS后台微服务重构。其核心机制是:所有兼职任务必须绑定可验证的Git提交记录(含CI/CD流水线ID)、API契约文档(OpenAPI 3.0规范)及压测报告(Locust生成)。2024年Q1完成14个交付,客户复购率达85.7%,平均单项目结算周期缩短至9.2天。
平台规则演进对比表
| 维度 | 旧模式(2021) | 新生态(2024) |
|---|---|---|
| 需求发布门槛 | 无技术审核,仅需支付押金 | 必须上传架构图+接口草稿+测试用例模板 |
| 结算方式 | 全额预付/完工后一次性打款 | 分阶段:设计确认(20%)、核心模块交付(50%)、UAT通过(30%) |
| 争议处理 | 平台仲裁,无技术复核 | 引入第三方Gopher评审团(含3名CNCF成员) |
技术债治理成为兼职新刚需
某跨境电商客户委托重构其订单履约服务,原系统存在严重goroutine泄漏(pprof显示每小时新增12k+ idle goroutine)。兼职开发者@liwei 使用 go tool trace 定位到 sync.Pool 误用场景,并提交PR附带性能对比数据:
// 修复前(泄漏源)
var pool = sync.Pool{New: func() interface{} { return &OrderProcessor{} }}
// 修复后(显式生命周期管理)
func NewProcessor() *OrderProcessor {
p := &OrderProcessor{}
runtime.SetFinalizer(p, func(pp *OrderProcessor) { /* 清理资源 */ })
return p
}
开源协作反哺兼职能力验证
越来越多甲方将GitHub Star数、PR合并率、issue响应时效纳入候选人评估维度。例如,成都某金融科技公司招聘支付网关兼职维护者时,直接要求提供其在gin-gonic/gin仓库中近半年的贡献记录截图,并现场演示如何基于ginkgo编写并发安全的中间件单元测试。
合同条款的技术化升级
最新版《Golang兼职服务协议》明确约定:
- 性能SLA写入合同(如
/api/v1/orderP95 ≤ 120ms) - 数据一致性违约金按
log10(异常事务数)×日均交易额阶梯计算 - 代码所有权归属甲方,但开发者保留在个人作品集中展示脱敏架构图的权利
据GoCN社区2024年Q1调研,具备完整CI/CD配置能力的兼职开发者接单均价较2022年上涨37%,而单纯“写CRUD接口”的报价下降52%。这种价格分化印证了市场正从人力套利转向价值交付。
