Zero value time.Time em Go: armadilhas que matam seu código

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Introdução: O bug que todo desenvolvedor Go já enfrentou

\n\n

Você já viu a data 0001-01-01 00:00:00 +0000 UTC nos logs e pensou: "De onde isso veio? Eu não inicializei nada!"? Parabéns, você encontrou o zero value de time.Time em Go. Essa é uma armadilha clássica que gera milhares de visualizações no Stack Overflow e horas de debugging no mundo todo.

\n\n

Neste artigo, vamos explorar o que é o zero value para time.Time, por que ele se comporta de forma inesperada, como diferenciar uma data "vazia" de uma real e, principalmente, como evitar esses problemas em produção. Se você programa em Go e trabalha com datas, este conteúdo vai te salvar de muita dor de cabeça.

\n\n

O que é zero value em Go e por que time.Time é um caso especial

\n\n

Em Go, cada tipo tem um valor zero (zero value). Para números, é 0; para strings, é ""; para ponteiros, é nil. A lógica é simples: se você declarou uma variável sem inicializá-la, ela recebe um valor "vazio". Mas com time.Time, a coisa é mais complicada.

\n\n

O valor zero de time.Time não é o Unix timestamp 0 (1970-01-01), como seria de se esperar. É 0001-01-01 00:00:00 +0000 UTC. Por quê? Porque internamente, time.Time armazena nanossegundos desde 1º de janeiro do ano 1 (pelo calendário gregoriano). O zero nessa representação resulta no ano 1.

\n\n
package main\n\nimport (\n    "fmt"\n    "time"\n)\n\nfunc main() {\n    var t time.Time\n    fmt.Println(t) // 0001-01-01 00:00:00 +0000 UTC\n    fmt.Println(t.Unix()) // -62135596800 (número negativo!)\n}\n
\n\n

Já percebeu o problema? Se você tentar verificar if t == 0 ou comparar com o Unix zero, seu código vai quebrar. Vamos analisar os principais erros com zero value time.Time e como evitá-los.

\n\n

Top 5 erros com o valor zero de time.Time

\n\n

1. Comparação com Unix timestamp 0

\n\n

O erro mais comum é tentar verificar se o tempo está "vazio" comparando-o com time.Unix(0, 0). Isso não funciona, porque o valor zero não é o ano 1970.

\n\n
// ❌ Erro: nunca será true\nvar t time.Time\nif t == time.Unix(0, 0) {\n    fmt.Println("Tempo vazio")\n}\n\n// ✅ Correto: use o método IsZero()\nif t.IsZero() {\n    fmt.Println("Tempo vazio")\n}\n
\n\n

O método IsZero() é sua principal ferramenta. Ele retorna true apenas para o valor zero, e não para qualquer data "antiga".

\n\n

2. Serialização em JSON: null inesperado

\n\n

Ao serializar uma struct com time.Time para JSON, o valor zero se transforma na string "0001-01-01T00:00:00Z". Isso quebra APIs, frontends e bancos de dados. Os clientes veem uma data estranha, em vez de null.

\n\n
type Event struct {\n    Name      string    `json:"name"`\n    StartTime time.Time `json:"start_time"`\n}\n\nfunc main() {\n    e := Event{Name: "teste"}\n    data, _ := json.Marshal(e)\n    fmt.Println(string(data))\n    // {"name":"teste","start_time":"0001-01-01T00:00:00Z"}\n    // ❌ Deveria ser null ou o campo deveria estar ausente\n}\n
\n\n

Solução: use um ponteiro para time.Time (*time.Time) ou um tipo personalizado com lógica de serialização.

\n\n
// ✅ Opção com ponteiro\ntype Event struct {\n    Name      string     `json:"name"`\n    StartTime *time.Time `json:"start_time,omitempty"`\n}\n\n// ✅ Ou tipo personalizado com omitempty\ntype CustomTime struct {\n    time.Time\n}\n\nfunc (ct CustomTime) MarshalJSON() ([]byte, error) {\n    if ct.IsZero() {\n        return []byte("null"), nil\n    }\n    return json.Marshal(ct.Time)\n}\n
\n\n

3. Problemas com bancos de dados (SQL)

\n\n

Ao inserir um time.Time zero no PostgreSQL ou MySQL, você obterá a data 0001-01-01, o que causará um erro de restrição de intervalo (o ano 1 está fora do intervalo permitido).

Blogs

Book Recommendations