Fundamentos de Entrega Empresarial
10 ejemplos para empezar con Entrega Empresarial - 7 básicos y 3 intermedios.
Busca en todas las páginas de la documentación
10 ejemplos para empezar con Entrega Empresarial - 7 básicos y 3 intermedios.
mkdir deliverylab && cd deliverylab && go mod init example.com/deliverylab.go get github.com/open-feature/go-sdk/openfeature github.com/prometheus/client_golang/prometheus.Sella el SHA de git en el binario para correlación de despliegues y respuestas de /healthz.
package main
import (
"fmt"
"runtime/debug"
)
func main() {
fmt.Println("version:", buildVersion())
}
func buildVersion() string {
info, ok := debug.ReadBuildInfo()
if !ok {
return "dev"
}
for _, s := range info.Settings {
if s.Key == "vcs.revision" {
if len(s.Value) >= 7 {
return s.Value[:7]
}
return s.Value
}
}
return "unknown"
}debug.ReadBuildInfo funciona cuando se compila con información de módulo (go build desde un repositorio git).-ldflags "-X main.version=..." para sellado explícito en CI.Relacionado: Envío Seguro de Servicios Go a Escala Empresarial - descripción general de la entrega
Un paso mínimo de pipeline que falla la compilación en fallos de prueba o de carrera.
#!/usr/bin/env bash
set -euo pipefail
go version
go test ./... -count=1 -race -timeout 5m
go vet ./...-race detecta carreras de datos antes de producción - vale la pena el tiempo de CI en el código del servicio.-count=1 deshabilita la caché de pruebas para que CI siempre se reejecute.Relacionado: Métricas DORA para Equipos Go - medición de la salud del pipeline
Compila en una etapa de constructor; envía una imagen de tiempo de ejecución mínima.
FROM golang:1.26-bookworm AS builder
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -trimpath -ldflags="-s -w" -o /out/app ./cmd/api
FROM gcr.io/distroless/static-debian12
COPY --from=builder /out/app /app
USER nonroot:nonroot
ENTRYPOINT ["/app"]CGO_ENABLED=0 produce un binario estático adecuado para distroless.-trimpath elimina rutas locales de los binarios para reproducibilidad.:latest, en tu registro.Relacionado: Estrategia de Lanzamiento: Blue-Green y Canary para Go - despliegue de imágenes
Separa la latencia barata de la preparación comprobada de dependencias.
package main
import (
"database/sql"
"net/http"
"os"
_ "github.com/jackc/pgx/v5/stdlib"
)
func main() {
db, _ := sql.Open("pgx", os.Getenv("DATABASE_URL"))
mux := http.NewServeMux()
mux.HandleFunc("GET /healthz", func(w http.ResponseWriter, _ *http.Request) {
w.WriteHeader(http.StatusOK)
})
mux.HandleFunc("GET /readyz", func(w http.ResponseWriter, _ *http.Request) {
if err := db.Ping(); err != nil {
http.Error(w, "db down", http.StatusServiceUnavailable)
return
}
w.WriteHeader(http.StatusOK)
})
http.ListenAndServe(":8080", mux)
}livenessProbe y readinessProbe.Relacionado: Entrega Progresiva y Verificación Automatizada - comprobaciones automatizadas
Drena las solicitudes en curso antes de SIGKILL durante la terminación del pod.
package main
import (
"context"
"log/slog"
"net/http"
"os"
"os/signal"
"syscall"
"time"
)
func main() {
srv := &http.Server{Addr: ":8080", Handler: http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
time.Sleep(2 * time.Second)
w.WriteHeader(http.StatusOK)
})}
go func() { _ = srv.ListenAndServe() }()
quit := make(chan os.Signal, 1)
signal.Notify(quit, syscall.SIGTERM, syscall.SIGINT)
<-quit
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
defer cancel()
if err := srv.Shutdown(ctx); err != nil {
slog.Error("shutdown", "err", err)
}
}Shutdown espera a los manejadores activos hasta el tiempo de espera.terminationGracePeriodSeconds con la duración de tu solicitud en el peor de los casos.Relacionado: Runbooks de Reversión para Despliegues Go - recuperación durante despliegues fallidos
El mismo binario en staging y producción; la configuración solo desde el entorno.
package main
import (
"log/slog"
"os"
)
type Config struct {
Port string
DatabaseURL string
LogLevel string
}
func loadConfig() Config {
return Config{
Port: envOr("PORT", "8080"),
DatabaseURL: os.Getenv("DATABASE_URL"),
LogLevel: envOr("LOG_LEVEL", "info"),
}
}
func envOr(key, def string) string {
if v := os.Getenv(key); v != "" {
return v
}
return def
}
func main() {
cfg := loadConfig()
slog.Info("starting", "port", cfg.Port, "log_level", cfg.LogLevel)
}Relacionado: Gestión de Cambios y Puertas de Cumplimiento - cambios controlados en producción
Un binario de prueba Go diminuto que CI ejecuta contra staging después del despliegue.
package main
import (
"fmt"
"net/http"
"os"
"time"
)
func main() {
base := os.Getenv("SMOKE_BASE_URL")
if base == "" {
base = "http://localhost:8080"
}
client := &http.Client{Timeout: 5 * time.Second}
for _, path := range []string{"/healthz", "/readyz"} {
resp, err := client.Get(base + path)
if err != nil || resp.StatusCode != http.StatusOK {
fmt.Fprintf(os.Stderr, "smoke failed %s: %v status=%v\n", path, err, resp)
os.Exit(1)
}
resp.Body.Close()
}
fmt.Println("smoke ok")
}Relacionado: Entrega Progresiva y Verificación Automatizada - profundidad de verificación
Despliega código nuevo con el comportamiento desactivado hasta que operaciones lo activen.
package main
import (
"context"
"os"
)
type Flags interface {
Bool(ctx context.Context, key string, defaultVal bool) bool
}
type EnvFlags struct{}
func (EnvFlags) Bool(_ context.Context, key string, defaultVal bool) bool {
if v := os.Getenv("FLAG_" + key); v == "true" {
return true
}
if v == "false" {
return false
}
return defaultVal
}
func runNewCheckout(ctx context.Context) error { return nil }
func runLegacyCheckout(ctx context.Context) error { return nil }
func handleCheckout(ctx context.Context, flags Flags) error {
if flags.Bool(ctx, "NEW_CHECKOUT", false) {
return runNewCheckout(ctx)
}
return runLegacyCheckout(ctx)
}false por defecto en la configuración de producción.Relacionado: Flags de Funcionalidad en Servicios Go - SDKs de flags en producción
Expón etiquetas de versión para que los dashboards marquen los límites de despliegue.
package main
import (
"net/http"
"runtime"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
var buildInfo = prometheus.NewGaugeVec(
prometheus.GaugeOpts{Name: "go_build_info", Help: "Build metadata"},
[]string{"version", "goversion"},
)
func main() {
prometheus.MustRegister(buildInfo)
buildInfo.WithLabelValues("abc1234", runtime.Version()).Set(1)
http.Handle("/metrics", promhttp.Handler())
http.ListenAndServe(":9090", nil)
}main, nunca por solicitud.go_build_info para líneas de despliegue.Relacionado: Métricas DORA para Equipos Go - tasa de fallo de cambio
Comprueba la compatibilidad del esquema antes de servir tráfico en una nueva versión.
package main
import (
"database/sql"
"errors"
)
func assertColumnExists(db *sql.DB, table, column string) error {
var exists bool
q := `SELECT EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_name = $1 AND column_name = $2
)`
if err := db.QueryRow(q, table, column).Scan(&exists); err != nil {
return err
}
if !exists {
return errors.New("missing required column: " + table + "." + column)
}
return nil
}/readyz cuando una nueva versión depende de una columna expandida.Relacionado: Runbooks de Reversión para Despliegues Go - pasos de reversión de esquema
Versiones de la Pila: Esta página fue escrita para Go 1.26.x (predeterminado de GC Green Tea, modernizadores de
go fix- verifica el parche en la compilación), chi (última versión - verifica en la compilación), gin (última versión - verifica en la compilación), echo (última versión - verifica en la compilación), google.golang.org/grpc (última versión - verifica en la compilación), sigs.k8s.io/controller-runtime (última versión - verifica en la compilación), kubebuilder (última versión - verifica en la compilación), tinygo (última versión - verifica los objetivos de la placa en la compilación), wazero (última versión - verifica en la compilación) y golangci-lint (última versión - verifica el conjunto de linters en la compilación).
Revisado por Chris St. John·Última actualización: 19 jul 2026