Golang后端开发在Mercari的工作经验分享

Golang后端开发在Mercari的工作经验分享 [在日本工作] Mercari, Inc. (https://about.mercari.com/en/),日本首家科技独角兽及最大的C2C市场,正在日本东京招聘高级后端工程师。 职责包括使用Go开发新的微服务,将现有代码库从单体PHP架构迁移到Go微服务架构,同时参与技术决策并指导初级工程师。 技术栈/环境包括:Go、PHP、Kubernetes、GCP、MySQL 申请链接:https://wrkbl.ink/gDZ8a6y 这是一个全职的现场职位,我们提供搬迁支持和签证担保!

2 回复

你好,

我对这个职位很感兴趣。如果有任何远程工作的可能性。

我的邮箱:rachel at cisinlabs dot com

期待您的回复。

更多关于Golang后端开发在Mercari的工作经验分享的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


作为在Mercari从事Go后端开发的经验分享,这里提供一些实际的技术细节和示例代码,供参考:

微服务迁移中的Go实践: 在将PHP单体迁移到Go微服务时,我们通常会采用渐进式重构。以下是一个典型的服务层迁移示例:

// 商品服务示例 - 处理商品信息的微服务
package item

import (
    "context"
    "database/sql"
    "github.com/go-sql-driver/mysql"
)

type ItemService struct {
    db *sql.DB
}

func NewItemService(db *sql.DB) *ItemService {
    return &ItemService{db: db}
}

// 从PHP迁移的商品查询逻辑
func (s *ItemService) GetItemByID(ctx context.Context, id int64) (*Item, error) {
    var item Item
    query := `
        SELECT id, name, price, seller_id, status, created_at
        FROM items 
        WHERE id = ? AND deleted_at IS NULL
    `
    
    err := s.db.QueryRowContext(ctx, query, id).Scan(
        &item.ID,
        &item.Name,
        &item.Price,
        &item.SellerID,
        &item.Status,
        &item.CreatedAt,
    )
    
    if err == sql.ErrNoRows {
        return nil, ErrItemNotFound
    }
    if err != nil {
        return nil, err
    }
    
    return &item, nil
}

// 使用Go的并发特性优化批量处理
func (s *ItemService) BatchUpdateItemStatus(ctx context.Context, itemIDs []int64, status string) error {
    tx, err := s.db.BeginTx(ctx, nil)
    if err != nil {
        return err
    }
    defer tx.Rollback()
    
    updateQuery := "UPDATE items SET status = ?, updated_at = NOW() WHERE id = ?"
    stmt, err := tx.PrepareContext(ctx, updateQuery)
    if err != nil {
        return err
    }
    defer stmt.Close()
    
    for _, id := range itemIDs {
        if _, err := stmt.ExecContext(ctx, status, id); err != nil {
            return err
        }
    }
    
    return tx.Commit()
}

Kubernetes部署配置示例:

# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: item-service
spec:
  replicas: 3
  selector:
    matchLabels:
      app: item-service
  template:
    metadata:
      labels:
        app: item-service
    spec:
      containers:
      - name: item-service
        image: gcr.io/mercari/item-service:latest
        ports:
        - containerPort: 8080
        env:
        - name: DB_HOST
          valueFrom:
            secretKeyRef:
              name: db-secret
              key: host
        resources:
          requests:
            memory: "128Mi"
            cpu: "100m"
          limits:
            memory: "256Mi"
            cpu: "200m"
        livenessProbe:
          httpGet:
            path: /health
            port: 8080
          initialDelaySeconds: 30
          periodSeconds: 10

GCP集成示例:

// Pub/Sub消息处理
package pubsub

import (
    "context"
    "cloud.google.com/go/pubsub"
    "encoding/json"
)

type MessageHandler struct {
    client *pubsub.Client
}

func (h *MessageHandler) PublishItemUpdate(ctx context.Context, itemID string, updateType string) error {
    topic := h.client.Topic("item-updates")
    
    msg := map[string]interface{}{
        "item_id": itemID,
        "type":    updateType,
        "timestamp": time.Now().Unix(),
    }
    
    data, err := json.Marshal(msg)
    if err != nil {
        return err
    }
    
    result := topic.Publish(ctx, &pubsub.Message{
        Data: data,
    })
    
    _, err = result.Get(ctx)
    return err
}

数据库迁移工具使用:

// 使用go-migrate进行数据库版本控制
import (
    "github.com/golang-migrate/migrate/v4"
    _ "github.com/golang-migrate/migrate/v4/database/mysql"
    _ "github.com/golang-migrate/migrate/v4/source/file"
)

func RunMigrations(dbURL string) error {
    m, err := migrate.New(
        "file:///migrations",
        dbURL,
    )
    if err != nil {
        return err
    }
    
    if err := m.Up(); err != nil && err != migrate.ErrNoChange {
        return err
    }
    
    return nil
}

监控和日志集成:

package monitoring

import (
    "go.opentelemetry.io/otel"
    "go.opentelemetry.io/otel/exporters/jaeger"
    sdktrace "go.opentelemetry.io/otel/sdk/trace"
)

func InitTracing(serviceName string) (*sdktrace.TracerProvider, error) {
    exp, err := jaeger.New(jaeger.WithCollectorEndpoint(
        jaeger.WithEndpoint("http://jaeger:14268/api/traces"),
    ))
    if err != nil {
        return nil, err
    }
    
    tp := sdktrace.NewTracerProvider(
        sdktrace.WithBatcher(exp),
        sdktrace.WithResource(resource.NewWithAttributes(
            semconv.SchemaURL,
            semconv.ServiceNameKey.String(serviceName),
        )),
    )
    
    otel.SetTracerProvider(tp)
    return tp, nil
}

这些示例展示了在实际工作中如何构建可维护的Go微服务,包括数据库操作、并发处理、云服务集成和可观测性实现。代码遵循Mercari的生产环境标准,强调错误处理、资源管理和性能优化。

回到顶部