Tag: Public
Mostrando todas as entradas e posts com a tag "Public"
Entradas do Diário
Reflexão sobre organização de código
Reflexão sobre organização de código
Há uma reflexão interessante sobre como organizar o código.
Faz muito tempo que deixei de me preocupar com estruturas de diretórios, tamanhos de arquivos ou localização física do código. Isso porque minha organização não depende da estrutura no disco, mas sim da própria estrutura da linguagem - pacotes, funções e módulos. Além disso, uso ferramentas que me levam diretamente ao ponto do código que quero editar.
Por exemplo, em vez de procurar manualmente por arquivos ou pastas, configurei meu editor para que, ao pressionar Enter sobre o nome de uma função ou objeto, ele vá diretamente para sua definição, e ao pressionar Backspace, volte ao ponto anterior. Tenho vários outros atalhos semelhantes, que me permitem navegar pelo código - não pelos arquivos.
Esse modo de trabalho tem alguns efeitos. Qualquer forma de indireção no código torna a navegação menos fluida, por isso evito o uso de interfaces quando não são realmente necessárias.
Prefiro navegar pela lógica do código e não pelo sistema de arquivos, pois isso reduz a carga cognitiva durante a escrita e, principalmente, durante a depuração. Há muitos anos estudo maneiras de reduzir essa carga, eliminando distrações e mantendo o foco na tarefa.
Sistemas de arquivos não são código, nem se transformam em código - são apenas mais uma camada de indireção, e toda indireção tem um custo.
Esse método funciona bem para mim porque foi moldado para o meu modo de pensar. Outras pessoas têm abordagens diferentes que fazem mais sentido para elas. Ainda assim, percebo que, cada vez mais, bons programadores tendem a organizar-se com base na estrutura do código, e não na estrutura dos arquivos.
Habilitar QUIC/HTTP3.
Habilitar QUIC/HTTP3.
Para quem usa o Caddy versão >= 2.6, basta liberar o acesso UDP na porta 443 no firewall do servidor. O Caddy já vem com suporte nativo ao HTTP/3.
Testei com curl e com alguns navegadores e funcionou perfeitamente.
curl -I --http3 https://empreendedor.dev
Se o navegador não suportar HTTP/3, ele volta para HTTP/2 automaticamente.
Git Blame
Git Blame
Git blame para uma linha específica ou um intervalo de linhas em um arquivo.
git blame -L 102,102 main.go
git blame -L 100,110 main.go
O resultado será algo como:
a1b2c3d4 (Cesar Gimenes 2025-09-10 102) valor := calc()
Onde a1b2c3d4 é o hash do commit.
Para ver o commit completo:
git show a1b2c3d4
Isso mostrará todas as alterações feitas naquele commit específico.
Limpa campo de documento
Limpa campo de documento
Você tem um campo com o CPF ou CNPJ e quer limpar tudo que não for número?
func RemoveNonDigits(s string) string {
var r string
for _, c := range s {
if unicode.IsDigit(c) {
r += string(c)
}
}
return r
}
PostgreSQL: Subselect para array
PostgreSQL: Subselect para array
Para criar um array a partir de um subselect em PostgreSQL use a função ARRAY junto com COALESCE para garantir que o resultado seja um array vazio caso não haja resultados.
Exemplo:
SELECT
id,
...,
coalesce(ARRAY(
SELECT t2.some_field
from table2 as t2
where t1.id = t2.t1_id
),'{}'::text[]) as array_field
FROM table1 as t1
Neste exemplo, array_field será um array contendo os valores de some_field da table2 relacionados ao id da table1. Se não houver correspondências, o campo será um array vazio ('{}'::text[]).
The most effective debugging tool
The most effective debugging tool
The most effective debugging tool is still careful thought, coupled with judiciously placed print statements.
- Brian W. Kernighan, in the paper Unix for Beginners (1979)
len no Bash
len no Bash
Script Bash para retornar o tamanho de uma string, muito útil para uso rápido no terminal.
#!/bin/bash
# Description: Get the length of a string
# Usage: len <string>
# Example: len "hello world"
# Output: 11
set -euo pipefail
[ "$#" -ne 1 ] && { echo "Usage: len <string>" >&2; exit 1; }
printf '%d\n' "${#1}"
Como verificar seu ipv6
Como verificar seu ipv6
curl -6 https://ifconfig.co
curl -6 https://ipv6.icanhazip.com
Configuração do Bash
Configuração do Bash
Algumas configurações úteis para adicionar no início de scripts Bash:
set -e # Exit on error
set -u # Treat unset variables as an error
set -x # Print commands and their arguments as they are executed
set -o pipefail # Fail on pipe errors
Ou tudo em uma linha:
set -euxo pipefail
Com isso, você garante:
- O script falha imediatamente se um comando falhar.
- Variáveis não definidas causam erro.
- Comandos e argumentos são impressos no terminal.
- Erros em pipes são capturados.
AGENTS.md
AGENTS.md
Uma dica para tornar o uso de agents menos sofrido é criar um arquivo AGENTS.md na raiz do seu projeto. E colocar nele as informações e contextos que você quer que o agente siga, exemplos de comandos, descrições de tarefas, etc.
Alguns sistemas já leem esse arquivo automaticamente, mas você pode garantir isso simplesmente solicitando para o agente ler o arquivo e seguir as instruções.
Exemplos de AGENTS.md em https://agentsmd.net
Redirecionando a saída do terminal.
Redirecionando a saída do terminal.
Você pode redirecionar toda a saída de um script para um arquivo usando um único comando no início do script.
Nesse exemplo, a saída do comando ls será direcionada para o arquivo out.txt.
#!/bin/bash
exec >out.txt 2>&1
ls -al --color
Você também pode redirecionar a saída para o console, usando /dev/console, requer permissão de root.
#!/bin/bash
exec >/dev/console 2>&1
ls -al --color
O parâmetro --color é usado para manter a saída colorida, porque o comando ls detecta se a saída é um terminal ou não, e ajusta a saída de acordo.
Baytimetro
Baytimetro
Esse fim de semana fiz algumas brincadeiras com o terminal, desenhando direto e recriei um recurso lá dos anos 80 que, apesar de extremamente simples, é muito útil: o baytimetro.
echo "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
echo " 1 2 3 4 5 6 7 8"
Ótimo chamar com seu desenho de tela e descobrir se você precisa colocar algum caractere mais para a direita ou esquerda.
É ridiculamente simples, mas fazer esse tipo de coisa tem um apelo nostálgico muito grande para mim.
Função `toclip`
Função toclip
Esta é uma função Bash que uso como parte de meus scripts e ambientes de desenvolvimento. Ela copia o conteúdo do stdin para a área de transferência. Muito útil quando você está acessando um servidor via SSH.
toclip() {
[[ ${SSH_CONNECTION-}${SSH_TTY-} ]] && {
printf $'\033]52;c;%s\a' "$(base64 -w0 2>/dev/null || base64 | tr -d '\n')"
return
}
case $OSTYPE in
darwin*) pbcopy ;;
linux*)
#command -v wl-copy >/dev/null 2>&1 && wl-copy && return
command -v xclip >/dev/null 2>&1 && xclip -selection clipboard && return
# Fallback Linux without xclip or wl-copy returns to OSC52
printf $'\033]52;c;%s\a' "$(base64 -w0 2>/dev/null || base64 | tr -d '\n')"
;;
esac
}
Exemplo de uso
Direto do stdin:
echo "Texto para copiar" | toclip
Copiando o conteúdo de um arquivo:
toclip < arquivo.txt
Listando servidores DNS
Listando servidores DNS
Para listar os servidores DNS usados no macOS:
scutil --dns
Útil para saber quais servidores foram pegos depois de renovar o DHCP.
Não largue o osso
Não largue o osso
Uma vez, meu tio William me contou uma história de um piloto de corrida que estava com ele e ia passar por uma curva com uma leve subida. Enquanto tangenciava a curva perfeitamente, em um único e contínuo movimento, reduziu a marcha e acelerou, ao mesmo tempo, virou a fita no toca-fitas. Sem trancos, com o carro ganhando somente a potência necessária. Fez tudo isso como se não fosse nada, enquanto conversava.
Meu tio usou essa história para me falar sobre preparo e sobre conhecer bem sua profissão. Essa habilidade não vem do nada, não é inata; vem de trabalho duro e determinação.
Para quem está lendo isso hoje, várias décadas depois, é difícil explicar a complexidade dessa manobra, naquele tempo de câmbios manuais e carburadores mecânicos. Principalmente se você não souber operar um toca-fitas.
Sinto falta dessas conversas com ele. Gostaria de ter assistido a mais corridas ao seu lado.
Nas palavras do Sr. William: – Não largue o osso.
n8n com padman
n8n com padman
Tenho uma máquina que só tem uma regra: tudo que for executado nela deve ser feito em um container.
# podman volume create n8n_data 2>/dev/null || true
podman run -it --rm \
--name n8n \
-p 5678:5678 \
-v n8n_data:/home/node/.n8n \
-e N8N_RUNNERS_ENABLED=true \
-e N8N_SECURE_COOKIE=false \
-e N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=true \
docker.n8n.io/n8nio/n8n
Ajustes para rodar o n8n na rede interna
Ajustes para rodar o n8n na rede interna
Essas configurações são para rede interna, maquina não acessível pela internet, sem SSL. Use apenas em ambiente de desenvolvimento ou teste.
Diminui as permissões do arquivo de configuração do n8n.
chmod 600 /home/user/.n8n/config
Rodando na rede interna sem SSL e com task runners habilitados:
export N8N_RUNNERS_ENABLED=true #enable task runners
export N8N_SECURE_COOKIE=false #disable secure cookies
npx n8n
Listar variáveis
Listar variáveis
Tecnica para fazer “debug de pobre” em Lua, listando variáveis globais e locais.
-- List all global variables
for name, value in pairs(_G) do
local repr = tostring(value)
print(string.format("%s = %s", name, repr))
end
-- List all local variables in the current function
-- This will only work if the code is run in a function context
local function list_locals()
local i = 1
while true do
local var_name, var_value = debug.getlocal(2, i)
if not var_name then break end
print(string.format("%s = %s", var_name, tostring(var_value)))
i = i + 1
end
end
-- Example
local function demo()
local a = 10
local b = "hello"
list_locals() -- This will list local variables a and b
end
demo()
Conway's Game of Life
Conway’s Game of Life
Essa noite de brincadeira, criei uma versão para terminal do consagrado Jogo da Vida de Conway (Conway’s Game of Life).
Sobre tentar manter um diário: Se eu não escrever o que tenho na cabeça imediatamente, provavelmente eu nunca vou escrever.
Sobre tentar manter um diário: Se eu não escrever o que tenho na cabeça imediatamente, provavelmente eu nunca vou escrever.
Processamento de Registros em Lote com PostgreSQL e Go
Processamento de Registros em Lote com PostgreSQL e Go
Este é um padrão interessante para processamento de registros em lote no Go com PostgreSQL. Ele utiliza transações e bloqueios para garantir que os registros sejam processados de forma segura e eficiente, evitando conflito entre múltiplas instâncias do processo.
O truque é combinar o uso de FOR UPDATE SKIP LOCKED para evitar que múltiplas instâncias do processo leiam e processem o mesmo registro ao mesmo tempo, e o uso do índice (id) para evitar que algum erro de processamento faça com que o registro seja processado novamente porque não houve uma mudança de status.
Se houver um erro durante o processamento, o registro não é atualizado e permanece com o status ‘pendente’. Sem o WHERE id > $1, o loop poderia entrar em um ciclo infinito tentando processar o mesmo registro repetidamente.
var id int
for {
done := func() bool {
const sqlStatement = `SELECT
id, ...
FROM ...
WHERE id > $1
AND status = 'pendente'
AND ...
ORDER BY id
FOR UPDATE SKIP LOCKED LIMIT 1;`
// aqui inicia uma transação
tx := ...
defer func() {
// mecanismo de rollback
}()
// então executa a consulta
err := tx.QueryRow(sqlStatement, id).Scan(&id, ...)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return true // não há mais registros
}
// trata outros erros
...
return false
}
// aqui faz o processamento do registro e atualiza o status
// pode ser fail, paid, processed, etc.
// ...
// se tudo estiver ok, confirma a transação
err = tx.Commit()
if err != nil {
// trata erro de commit geralmente log.Fatal(...)
}
return false // indica que o loop deve continuar
}()
if done {
break // não há mais registros para processar
}
}
Este é um exemplo bom para processamento de registros em lote e pode ser tranquilamente colocado para rodar de tempos em tempos, como um cron job, para processar registros pendentes em um banco de dados PostgreSQL.
Uma vantagem interessante é que, se o processamento demorar muito, automaticamente o cron vai carregar outras instâncias do processo, que vão pegar os registros que ainda não foram processados e não estão bloqueados (SKIP LOCKED). Isso permite que o sistema escale horizontalmente, processando mais registros em paralelo sem risco de conflitos.