Ao redirecionar para a saída de erro padrão em Go
Olá, sou um incompetente.
Não consegui encontrar muitos artigos que explicassem esta parte para Go, então estou a anotá-la.
Verificar o valor de retorno
Quando havia este código inicialmente.
func main() {
if len(os.Args) < 2 {
fmt.Println("Usage: go run main.go https://soulminingrig.com/")
return
}
url := os.Args[1]
title, err := fetchTitle(url)
if err != nil {
fmt.Printf( "Error: %v\n", err)
return
}
fmt.Printf("Title: %s\n", title)
}
Claro que o código acima ainda produzirá erros que ocorrem em Go, mas o que acontece se quisermos obter o valor de retorno de um erro de um binário executável após a construção?
alleycat:[haturatu]:~/git/go-title$ ./go-title
Usage: go run main.go https://soulminingrig.com/
alleycat:[haturatu]:~/git/go-title$ echo $?
0
alleycat:[haturatu]:~/git/go-title$ ./go-title http://https://soulminingrig.nodomain/
Error: failed to fetch URL: Get "http://https//soulminingrig.nodomain/": dial tcp: lookup https: no such host
alleycat:[haturatu]:~/git/go-title$ echo $?
0
Tudo é tratado como saída padrão.
Especificar o valor de retorno com os.Exit
Portanto, é necessário especificar com os.Exit para que seja tratado corretamente como um erro, então corrigimos da seguinte forma.
func main() {
if len(os.Args) < 2 {
fmt.Println("Usage: go run main.go https://soulminingrig.com/")
os.Exit(1)
}
url := os.Args[1]
title, err := fetchTitle(url)
if err != nil {
fmt.Printf( "Error: %v\n", err)
os.Exit(2)
}
fmt.Printf("Title: %s\n", title)
}
Agora, construa e execute novamente.
alleycat:[haturatu]:~/git/go-title$ ./go-title
Usage: go run main.go https://soulminingrig.com/
alleycat:[haturatu]:~/git/go-title$ echo $?
1
alleycat:[haturatu]:~/git/go-title$ ./go-title http://https://soulminingrig.nodomain/
Error: failed to fetch URL: Get "http://https//soulminingrig.nodomain/": dial tcp: lookup https: no such host
alleycat:[haturatu]:~/git/go-title$ echo $?
2
O valor de retorno foi recebido corretamente.
Tentar descartar o padrão de sucesso com valor de retorno 0 para /dev/null
Podemos descartar apenas o valor de retorno 0 da saída padrão com > /dev/null, então vamos tentar isso.
alleycat:[haturatu]:~/git/go-title$ ./go-title > /dev/null
alleycat:[haturatu]:~/git/go-title$ ./go-title http://https://soulminingrig.nodomain/ > /dev/null
Neste caso, fmt.Println corresponde à saída padrão, então as mensagens de erro não podem ser verificadas.
Para a maioria das GNU Tools e outros binários executáveis, não é comum que as mensagens de erro sejam enviadas para a saída padrão, então as mensagens de erro também devem ser enviadas para a saída de erro.
Mesmo na documentação oficial, a maioria das saídas é feita com fmt.Print, mas
Retornar e lidar com um erro
https://pkg.go.dev/errors
No mundo Go, ao criar módulos, não há muita necessidade de forçar a saída de erro padrão, mas isso não atende à necessidade de ver apenas a saída de erro ao depurar usando apenas > /dev/null.
No final das contas, é necessário lidar com isso usando fprint, assim como na linguagem C.
Em seguida, vamos tentar fornecer os.Stderr como o primeiro argumento de fprint para a saída de erro padrão.
Diferenças entre fmt.Print e fmt.Fprint
Vamos tentar fazer as seguintes alterações.
Este artigo é muito fácil de entender.
Quero usar as funções da família fmt.Print do Go de forma inteligente
Se mesmo com este artigo você ainda se perguntar 'o que é isso!', talvez encontre uma explicação satisfatória pesquisando as diferenças nas funções de saída da família print da linguagem C.
Se você não entender printf, pode tentar com awk.
$ ls -la | awk '{print $9}'
$ ls -la | awk '{printf $9}'
fprint com awk é... não sei por falta de conhecimento...
Se alguém souber, por favor, me diga.
func main() {
if len(os.Args) < 2 {
fmt.Fprintln(os.Stderr, "Usage: go run main.go https://soulminingrig.com/")
os.Exit(1)
}
url := os.Args[1]
title, err := fetchTitle(url)
if err != nil {
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
os.Exit(2)
}
fmt.Printf("Title: %s\n", title)
}
Vamos ver os resultados agora.
alleycat:[haturatu]:~/git/go-title$ ./go-title > /dev/null
Usage: go run main.go https://soulminingrig.com/
alleycat:[haturatu]:~/git/go-title$ echo $?
1
alleycat:[haturatu]:~/git/go-title$ ./go-title http://https://soulminingrig.nodomain/ > /dev/null
Error: failed to fetch URL: Get "http://https//soulminingrig.nodomain/": dial tcp: lookup https: no such host
alleycat:[haturatu]:~/git/go-title$ echo $?
2
A saída de erro foi realizada corretamente.
Realmente, esse tipo de manipulação é fácil de esquecer, então sinto que preciso ter muito cuidado ao lidar com a saída de erro correta.