Noções Básicas de Entrega Empresarial
10 exemplos para você começar com Entrega Empresarial - 7 básicos e 3 intermediários.
Busque em todas as páginas da documentação
10 exemplos para você começar com Entrega Empresarial - 7 básicos e 3 intermediários.
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.Carimba o SHA do git no binário para correlação de deploy e respostas /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 quando construído com informações de módulo (go build de um repositório git).-ldflags "-X main.version=..." para carimbar explicitamente em CI.Relacionado: Enviando Serviços Go em Escala Empresarial com Segurança - visão geral de entrega
Um passo mínimo de pipeline que falha o build em falhas de teste ou de race.
#!/usr/bin/env bash
set -euo pipefail
go version
go test ./... -count=1 -race -timeout 5m
go vet ./...-race captura data races antes da produção - vale o tempo de CI no código do serviço.-count=1 desabilita o cache de testes para que a CI sempre reexecute.Relacionado: Métricas DORA para Equipes Go - medindo a saúde do pipeline
Compila em um estágio de builder; envia uma imagem de runtime 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 produz um binário estático adequado para distroless.-trimpath remove caminhos locais dos binários para reprodutibilidade.:latest, no seu registro.Relacionado: Estratégia de Lançamento: Blue-Green & Canary para Go - implantando imagens
Separe a liveness barata da readiness verificada por dependência.
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 e readinessProbe.Relacionado: Entrega Progressiva e Verificação Automatizada - verificações automatizadas
Drena requisições em andamento antes do SIGKILL durante a terminação do 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 por handlers ativos até o timeout.terminationGracePeriodSeconds com a duração da sua pior requisição.Relacionado: Runbooks de Rollback para Deployments Go - recuperação durante rollouts ruins
Mesmo binário entre staging e produção; configuração apenas do ambiente.
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: Gerenciamento de Mudanças e Portões de Conformidade - mudanças controladas em produção
Um pequeno binário de teste que a CI executa contra o staging após o deploy.
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 Progressiva e Verificação Automatizada - profundidade de verificação
Implante novo código com comportamento desativado até que a operação ative a flag.
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 padrão na configuração de produção.Relacionado: Feature Flags em Serviços Go - SDKs de flags de produção
Exponha labels de versão para que os dashboards marquem os limites de deploy.
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 requisição.go_build_info para linhas de deploy.Relacionado: Métricas DORA para Equipes Go - taxa de falha de mudança
Verifique a compatibilidade do esquema antes de servir tráfego em uma nova versão.
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 quando uma nova versão depende de uma coluna expandida.Relacionado: Runbooks de Rollback para Deployments Go - passos de rollback de esquema
Versões da Stack: Esta página foi escrita para Go 1.26.x (padrão GC Green Tea, go fix modernizers - verifique o patch na construção), chi (última versão - verifique na construção), gin (última versão - verifique na construção), echo (última versão - verifique na construção), google.golang.org/grpc (última versão - verifique na construção), sigs.k8s.io/controller-runtime (última versão - verifique na construção), kubebuilder (última versão - verifique na construção), tinygo (última versão - verifique os alvos de placa na construção), wazero (última versão - verifique na construção) e golangci-lint (última versão - verifique o conjunto de linters na construção).
Revisado por Chris St. John·Última atualização: 19 de jul. de 2026