Manipulando Arquivos em Go

Manipulando Arquivos com Go

Olá leitor, se você está comigo deste o início desta jornada, saiba que a partir deste ponto, acabamos de sair dos conceitos básicos da linguagem Go, e estamos entrando em conceitos mais avançados, como o uso de algumas bibliotecas e conceitos mais avançados 😎

Sendo assim, se você ainda não se sente seguro para continuar, recomendo voltar algumas lições anteriores e revisar alguns conteúdos, ok? 🙂

Dito isso, nesta lição você irá aprender a manipular arquivos com GoLang por meio da biblioteca os.

Com ela seremos capazes de abrir arquivos, lê-los (caso possível), gravar novos arquivos, atualizá-los, e até mesmo removê-los do sistema operacional.

Preparado? 🤩

Criando seu projeto de testes

Dentro da pasta JornadaGoLang, nós iremos criar uma nova pasta chamada de 14-manipulando-arquivos-em-go, onde dentro dela, vamos criar o nosso arquivo main.go:

package main

func main() {

}

Feito isso, vamos conhecer um pouco mais sobre a biblioteca os 😉

Conhecendo a biblioteca os do Go

A biblioteca os no GoLang é parte da biblioteca padrão do Go, e fornece funções essenciais para interação com o sistema operacional.

Com ela, você poderá manipular arquivos, diretórios, variáveis de ambiente, processos, entre outras funcionalidades a mais.

Para importar a biblioteca é bem simples:

import "os"

Se você tiver mais de uma biblioteca implementada dentro do seu arquivo .go, basta implementá-la da seguinte forma:

import (
        //Outras bibliotecas aqui...
	"os"
)

Para mais informações sobre esta biblioteca, não deixe de consultar a documentação do GoLang por meio deste link.

Nesta lição, você vai aprender as seguintes funcionalidades da biblioteca:

  • Manipular arquivos e diretórios.
  • Gerenciar variáveis de ambiente.
  • Controlar processos.
  • E obter informações do sistema operacional em questão.

📄 Manipulando Arquivos em Go

Por vezes, durante o funcionamento da sua aplicação, talvez você queria abrir, criar, editar ou até mesmo deletar arquivos que existem no seu sistema operacional.

Sejam arquivos de logs, arquivos de texto, imagens, mídia, ou qualquer outro tipo de arquivo que você queira trabalhar.

No caso do GoLang, nós podemos usar a biblioteca os para isso 🤓

Essa biblioteca conta com as seguintes funções que são capazes de manipular tais arquivos, vejamos as principais:

os.Create(): Cria ou sobrescreve um arquivo.

os.Open(): Abre um arquivo somente para leitura.

os.OpenFile(): Abre/cria um arquivo com permissões customizadas.

os.ReadFile(): Lê o conteúdo de um arquivo inteiro.

os.WriteFile(): Escreve em um arquivo.

os.Remove(): Remove um arquivo ou diretório vazio.

os.Rename(): Renomeia ou move um arquivo/diretório.

os.Stat(): Retorna informações sobre um arquivo.

Vejamos agora na prática, como utilizar tais funções em seu projeto em Go, por meio de alguns exemplos.

✅ Criando um arquivo de texto

Supondo que você queria criar um arquivo chamado de meu-texto.txt que vai existir no mesmo diretório do seu arquivo main.go, você poderia fazer isso da seguinte forma:

package main

import (
	"fmt"
	"os"
)

func main() {
	file, err := os.Create("meu-texto.txt")
	if err != nil {
		fmt.Println("Erro ao criar o arquivo:", err)
		return
	}
	defer file.Close()

	_, err = file.WriteString("Primeira linha do arquivo.\n")
	if err != nil {
		fmt.Println("Erro ao escrever no arquivo:", err)
		return
	}

	fmt.Println("Arquivo 'meu-texto.txt' criado com sucesso!")
}

Agora supondo que você queria criar este arquivo em um diretório customizado? Como você poderia fazer isso?

Simples, basta especificar o caminho absoluto (ex: C:\meu-diretorio\meu-texto.txt) ou relativo da seguinte forma:

package main

import (
	"fmt"
	"os"
	"path/filepath"
)

func main() {
	// Caminho do diretório onde o arquivo será criado
	dir := "C:\\MeusArquivos"

	// Verificar se o diretório existe, caso contrário, criar
	if _, err := os.Stat(dir); os.IsNotExist(err) {
		err := os.MkdirAll(dir, 0755) // Cria o diretório (e subdiretórios, se necessário)
		if err != nil {
			fmt.Println("Erro ao criar diretório:", err)
			return
		}
		fmt.Println("Diretório criado:", dir)
	}

	// Caminho completo do arquivo
	filePath := filepath.Join(dir, "meu-texto.txt")

	// Criar o arquivo no diretório especificado
	file, err := os.Create(filePath)
	if err != nil {
		fmt.Println("Erro ao criar o arquivo:", err)
		return
	}
	defer file.Close()

	// Escrever no arquivo
	_, err = file.WriteString("Conteúdo do arquivo criado em diretório customizado.\n")
	if err != nil {
		fmt.Println("Erro ao escrever no arquivo:", err)
		return
	}

	fmt.Println("Arquivo criado com sucesso em:", filePath)
}

Note que neste caso, nós precisamos fazer o uso da biblioteca path/filepath, que é responsável por controlar o caminho dos arquivos no sistema operacional em questão.

✅ Abrindo um arquivo de texto, e mostrando seu resultado no terminal

Supondo que você queria abrir um arquivo de texto (pode ser aquele que criamos no tópico anterior), ler o seu conteúdo e mostrar no terminal.

Tal resultado pode ser obtido usando o seguinte comando:

package main

import (
	"fmt"
	"io"
	"os"
)

func main() {
	file, err := os.Open("meu-texto.txt")
	if err != nil {
		fmt.Println("Erro ao abrir o arquivo:", err)
		return
	}
	defer file.Close()

	fmt.Println("Conteúdo do arquivo:")
	content, err := io.ReadAll(file)
	if err != nil {
		fmt.Println("Erro ao ler o conteúdo:", err)
		return
	}
	fmt.Println(string(content))
}

E mais uma vez, nos deparamos com uma outra biblioteca chamada de io, que é responsável por fazer a leitura dos arquivos abertos pelo os.

✅ Criando um arquivo de texto com permissões customizadas

Nem sempre, o arquivo de texto que você quer criar precisa ser acessado por todo mundo, por vezes, você quer que só um grupo de usuários possam fazer leitura e escrita, já outros, somente leitura e por aí vai...

Para obter este resultado, você pode usar os seguintes comandos:

package main

import (
	"fmt"
	"os"
)

func main() {
	// Permissões: 0664 -> Usuário e grupo com leitura/escrita, outros apenas leitura
	file, err := os.OpenFile("arquivo-custom.txt", os.O_CREATE|os.O_WRONLY, 0664)
	if err != nil {
		fmt.Println("Erro ao abrir o arquivo:", err)
		return
	}
	defer file.Close()

	_, err = file.WriteString("Escrevendo com permissões customizadas!\n")
	if err != nil {
		fmt.Println("Erro ao escrever no arquivo:", err)
		return
	}

	fmt.Println("Arquivo 'arquivo-custom.txt' criado com sucesso!")
}

O comando acima, cria um arquivo chamado de arquivo-custom.txt que contem as permissões 0664.

✅ Atualizando um arquivo de texto

Agora que você já sabe criar e ler o conteúdo de um determinado arquivo de texto, que tal aprender a atualizar o conteúdo ali existente, e salvar de volta?

O processo continua o mesmo que vimos em tópicos anteriores, mas com pequenas diferenças, observe:

package main

import (
	"fmt"
	"os"
)

func main() {
	// Abrir em modo de apêndice (append) para adicionar sem sobrescrever
	file, err := os.OpenFile("meu-texto.txt", os.O_APPEND|os.O_WRONLY, 0644)
	if err != nil {
		fmt.Println("Erro ao abrir o arquivo para adicionar conteúdo:", err)
		return
	}
	defer file.Close()

	_, err = file.WriteString("Essa é uma nova linha adicionada.\n")
	if err != nil {
		fmt.Println("Erro ao adicionar conteúdo:", err)
		return
	}

	fmt.Println("Conteúdo adicionado ao 'meu-texto.txt' com sucesso!")
}

Se você abrir o arquivo meu-texto.txt, verá que uma nova linha foi adicionada ao arquivo:

Primeira linha do arquivo.
Essa é uma nova linha adicionada.

✅ Renomeando um arquivo de texto

Supondo que você queria renomear um arquivo de texto, você pode fazer isso da seguinte forma:

package main

import (
	"fmt"
	"os"
)

func main() {
	err := os.Rename("meu-texto.txt", "meu-texto-renomeado.txt")
	if err != nil {
		fmt.Println("Erro ao renomear o arquivo:", err)
		return
	}

	fmt.Println("Arquivo renomeado para 'meu-texto-renomeado.txt'.")
}

No caso do exemplo acima, eu renomeei o arquivo meu-texto.txt para meu-texto-renomeado.txt.

✅ Obtendo informações sobre um arquivo de texto

Por vezes, é necessário obter algumas informações relevantes de um determinado arquivo, e para isso, você pode usar a função stat() da seguinte forma:

package main

import (
	"fmt"
	"os"
)

func main() {
	info, err := os.Stat("meu-texto-renomeado.txt")
	if err != nil {
		fmt.Println("Erro ao obter informações do arquivo:", err)
		return
	}

	fmt.Println("Informações do arquivo:")
	fmt.Println("Nome:", info.Name())
	fmt.Println("Tamanho (bytes):", info.Size())
	fmt.Println("Permissões:", info.Mode())
	fmt.Println("Última modificação:", info.ModTime())
}

Lembrando que a função stat() possuí inúmeros objetos que podem ser retornados, por isso, não deixe de consultar a documentação.

✅ Removendo um arquivo de texto

Por fim, e não menos importante, você também vai querer saber como remover um arquivo existente em um determinado diretório. Para isso, você pode usar a função delete() da seguinte forma:

package main

import (
	"fmt"
	"os"
)

func main() {
	err := os.Remove("meu-texto-renomeado.txt")
	if err != nil {
		fmt.Println("Erro ao remover o arquivo:", err)
		return
	}

	fmt.Println("Arquivo 'meu-texto-renomeado.txt' removido com sucesso!")
}

E pronto, o seu arquivo que sofreu inúmeras alterações em tópicos anteriores, finalmente pode descansar em paz 👻

A biblioteca os só serve para manipular arquivos de textos?

Apesar de nossos exemplos anteriores trabalharem com arquivos .txt, a biblioteca os vai muito além disso 🚀

Nos exemplos acima, usei arquivos de texto, pois eles são simples de serem manipulados, entretanto, você pode manipular quaisquer tipos de arquivo que você desejar.

Porém, cada arquivo terá uma especificidade diferente dependendo do seu formato e do que você deseja fazer. Por exemplo:

Arquivos binários: No caso deles, utilize métodos como os.Read() e os.Write() para manipular bytes diretamente.

Imagens e PDFs: Embora a biblioteca os permita abrir e salvar esses arquivos, você precisará de bibliotecas específicas (como image ou pdfcpu) para interpretá-los ou modificá-los.

Arquivos CSV ou JSON: A leitura e escrita podem ser feitas com os para acesso básico, mas as bibliotecas encoding/csv e encoding/json simplificam o processamento dessas estruturas. (Veremos mais sobre elas nas próximas lições).

A principal função da biblioteca os é fornecer acesso de baixo nível para lidar com o sistema operacional. Seja criando, movendo ou excluindo arquivos, manipulando permissões ou até gerenciando processos, ela é fundamental para qualquer programa feito em Go que interaja com o ambiente externo.

Mas não se esqueça que você vai precisar fazer o uso de outras bibliotecas para lidar com arquivos customizados.

📂 Manipulando diretórios em Go

A biblioteca os também nos fornece a possibilidade de manipulação de diretórios, vejamos seus principais métodos:

os.Mkdir(): Cria um diretório com permissões definidas.

os.MkdirAll(): Cria diretórios recursivamente (subpastas).

os.Remove(): Remove um arquivo ou diretório vazio.

os.RemoveAll(): Remove um diretório e seu conteúdo.

os.Getwd(): Retorna o diretório de trabalho atual.

os.Chdir(): Altera o diretório de trabalho.

Vejamos agora alguns exemplos práticos:

✅ Criando diretórios

Para criar um diretório, você pode fazer o uso da função Mkdir() da seguinte forma:

package main

import (
	"fmt"
	"os"
)

func main() {
	// Cria o diretório "minha-pasta"
	err := os.Mkdir("minha-pasta", 0755)
	if err != nil {
		fmt.Println("Erro ao criar o diretório:", err)
		return
	}
	fmt.Println("Diretório 'minha-pasta' criado com sucesso!")
}

O código acima, criou uma nova pasta chamada minha-pasta no mesmo local onde o main.go está localizado.

Note que criamos o diretório usando a permissão 0755.

Agora, supondo que você queria criar um diretório em um local customizado, você pode fazer isso da seguinte forma:

package main

import (
	"fmt"
	"os"
)

func main() {
	// Caminho do diretório no Windows (modifique conforme necessário)
	dirPath := "C:\\Users\\SeuUsuario\\Documentos\\minha-pasta-dois"

	// Criar o diretório
	err := os.Mkdir(dirPath, 0755)
	if err != nil {
		fmt.Println("Erro ao criar diretório personalizado:", err)
		return
	}
	fmt.Println("Diretório criado em:", dirPath)
}

No caso do exemplo acima, se estiver usando Windows, você deve mudar o caminho da pasta existente dentro da variável dirPath para um local onde você queira criar sua pasta.

Observação: o código acima também funciona em outros sistemas operacionais, como Linux e Mac, bastando apenas informar o caminho da pasta.

✅ Criando diretórios recursivos (subpastas)

Também é possível criar um diretório em conjunto com diversas subpastas, vejamos como isso pode ser feito:

package main

import (
	"fmt"
	"os"
)

func main() {
	// Cria a estrutura de diretórios recursivamente
	err := os.MkdirAll("minha-pasta/subpasta", 0755)
	if err != nil {
		fmt.Println("Erro ao criar subpasta:", err)
		return
	}
	fmt.Println("Subpasta criada em 'minha-pasta/subpasta'!")
}

No caso do exemplo acima, foi criado uma pasta chamada minha-pasta e dentro dela uma outra chamada de subpasta.

✅ Obtendo o diretório atual de execução

Será por meio do método Getwd() que você será capaz de obter o diretório atual de onde o seu main.go está sendo executado, vejamos:

package main

import (
	"fmt"
	"os"
)

func main() {
	// Obter o diretório atual
	currentDir, err := os.Getwd()
	if err != nil {
		fmt.Println("Erro ao obter diretório atual:", err)
		return
	}
	fmt.Println("Diretório atual:", currentDir)
}

No meu caso, o retornado foi:

Diretório atual: C:\Users\William Lima\Desktop\JornadaGoLang\14-manipulando-arquivos

✅ Alterando diretório de trabalho

O diretório de trabalho (ou diretório atual) é a pasta onde seu programa está operando no momento.

Se você abrir o terminal (ou CMD no Windows) e rodar seu programa Go, ele irá considerar o diretório onde foi executado como o diretório de trabalho.

Entretanto, é possível mudar isso por meio do método Chdir(), com ele você consegue mudar o diretório de trabalho do programa enquanto ele ainda está em execução.

📌 E por que isso é útil? Se você mudar o diretório com os.Chdir(), todas as operações como abrir, criar ou deletar arquivos vão usar esse novo diretório como ponto de referência.

package main

import (
	"fmt"
	"os"
)

func main() {
	// Alterar para o diretório "minha-pasta"
	err := os.Chdir("minha-pasta")
	if err != nil {
		fmt.Println("Erro ao mudar de diretório:", err)
		return
	}

	// Confirmação do diretório alterado
	newDir, _ := os.Getwd()
	fmt.Println("Diretório atual após mudança:", newDir)
}

✅ Removendo diretórios

Por fim, você pode querer remover o diretório que você acabou de criar. E atualmente existem duas formas de se fazer isso.

Removendo um diretório vazio com os.Remove():

package main

import (
	"fmt"
	"os"
)

func main() {
	// Remove um diretório vazio
	err := os.Remove("minha-pasta/subpasta")
	if err != nil {
		fmt.Println("Erro ao remover diretório:", err)
		return
	}
	fmt.Println("Diretório 'subpasta' removido com sucesso!")
}

Removendo um diretório com todo o conteúdo com os.RemoveAll():

package main

import (
	"fmt"
	"os"
)

func main() {
	// Remove o diretório e todo seu conteúdo
	err := os.RemoveAll("minha-pasta")
	if err != nil {
		fmt.Println("Erro ao remover diretório e conteúdo:", err)
		return
	}
	fmt.Println("Diretório 'minha-pasta' e seu conteúdo foram removidos!")
}

Lembrando que a primeira opção só remove um diretório caso ele estiver vazio, ou seja, se não existir arquivos lá dentro, e a segunda opção, ignora esse fato removendo todos os arquivos e subpastas ali existentes.

🌐 Manipulando variáveis de ambiente em Go

A manipulação de variáveis de ambiente em suas aplicações feitas com GoLang, pode ser de extrema importância, ainda mais se você tiver outras aplicações que são capazes de ler tais variáveis.

Os principais métodos são esses:

os.Getenv(): Retorna o valor de uma variável de ambiente.

os.Setenv(): Define uma variável de ambiente.

os.Unsetenv(): Remove uma variável de ambiente.

os.Environ(): Retorna todas as variáveis de ambiente.

os.LookupEnv(): Verifica se uma variável de ambiente existe.

Vejamos agora, alguns exemplos práticos 🤓

✅ Lendo uma variável de ambiente

Para ler o valor de uma variável de ambiente, podemos fazer isso da seguinte forma:

package main

import (
	"fmt"
	"os"
)

func getEnvVar(key string) {
	value := os.Getenv(key)
	if value == "" {
		fmt.Printf("A variável de ambiente '%s' não está definida.\n", key)
	} else {
		fmt.Printf("Valor de '%s': %s\n", key, value)
	}
}

func main() {
	getEnvVar("USERNAME") // No Windows, geralmente retorna o nome do usuário
	getEnvVar("PATH")     // Exibe o PATH do sistema
}

No código acima, nos separamos em uma função, o comando responsável por selecionar uma variável de ambiente em Go.

✅ Criando (sobrescrevendo) uma variável de ambiente

Também é possível criar uma nova, ou quem sabe atualizar uma variável de ambiente:

package main

import (
	"fmt"
	"os"
)

func setEnvVar(key, value string) {
	err := os.Setenv(key, value)
	if err != nil {
		fmt.Println("Erro ao definir a variável de ambiente:", err)
		return
	}
	fmt.Printf("Variável '%s' definida com sucesso!\n", key)
}

func main() {
	setEnvVar("MINHA_VARIAVEL", "12345")
	fmt.Println("MINHA_VARIAVEL:", os.Getenv("MINHA_VARIAVEL"))
}

Observação: se você tentar criar uma nova variável de ambiente usando o mesmo nome, o GoLang realiza uma atualização (sobrescrita).

✅ Removendo uma variável de ambiente

Para remover uma variável de ambiente é super simples, porém, tenha cuidado ao remover variáveis de ambiente, pois a remoção das mesmas podem afetar o funcionamento do GoLang.

package main

import (
	"fmt"
	"os"
)

func removeEnvVar(key string) {
	err := os.Unsetenv(key)
	if err != nil {
		fmt.Println("Erro ao remover a variável:", err)
		return
	}
	fmt.Printf("Variável '%s' removida com sucesso!\n", key)
}

func main() {
	os.Setenv("TEMP_VAR", "Valor temporário")
	fmt.Println("Antes de remover:", os.Getenv("TEMP_VAR"))

	removeEnvVar("TEMP_VAR")

	fmt.Println("Após remover:", os.Getenv("TEMP_VAR"))
}

✅ Listando variáveis de ambiente

Caso desejar, você também pode listar as variáveis de ambiente que estão setadas no sistema operacional, observe:

package main

import (
	"fmt"
	"os"
)

func listarVariaveisDeAmbiente() {
	vars := os.Environ()
	for _, v := range vars {
		fmt.Println(v)
	}
}

func main() {
	listarVariaveisDeAmbiente()
}

✅ Checando variáveis de ambiente

Também é possível validar se uma determinada variável de ambiente existe ou não no sistema operacional, observe:

package main

import (
	"fmt"
	"os"
)

func checkEnvVar(key string) {
	value, exists := os.LookupEnv(key)
	if exists {
		fmt.Printf("A variável '%s' existe e tem o valor: %s\n", key, value)
	} else {
		fmt.Printf("A variável '%s' não está definida.\n", key)
	}
}

func main() {
	os.Setenv("TOKEN_API", "abc123")

	checkEnvVar("TOKEN_API")
	checkEnvVar("NAO_EXISTE")
}

🧑‍💻 Processos e Sinais

Antes de continuarmos, você sabe o que é um processo?

Um processo é uma instância em execução de um determinado programa, e com a biblioteca os, você é capaz de:

  • Iniciar novos processos.
  • Controlar processos em segundo plano.
  • Obter informações sobre o processo atual.

A biblioteca os conta com os seguintes métodos para isso:

os.Getpid(): Retorna o ID do processo atual (PID).

os.Getppid(): Retorna o ID do processo pai (PPID).

os.StartProcess(): Inicia um novo processo.

os.FindProcess(): Encontra um processo pelo PID.

os.Kill(): Envia um sinal para um processo (matar).

os.Exit(): Finaliza o programa com um código de saída.

os.Signal: Tipo usado para manipular sinais.

Já os sinais, nada mais são do que notificações enviadas para um processo pelo sistema operacional. Tais como:

  • SIGINT: Interrompe o programa (ex.: CTRL+C).
  • SIGTERM: Solicita o encerramento gracioso do programa.
  • SIGHUP: Indica que a sessão foi encerrada.

Dito isso, vamos ver na prática a utilização de cada um desses métodos 😉

✅ Obtendo o ID do processo atual e do processo pai

Para obter informações dos processos atuais, use os seguintes comandos:

package main

import (
	"fmt"
	"os"
)

func mostrarPID() {
	fmt.Printf("PID (Processo Atual): %d\n", os.Getpid())
	fmt.Printf("PPID (Processo Pai): %d\n", os.Getppid())
}

func main() {
	mostrarPID()
}

✅ Executando um programa externo

Supondo que você queria executar um programa externo, como por exemplo, o notepad.exe (do windows), faça isso da seguinte forma:

package main

import (
	"fmt"
	"os"
)

func abrirBlocoDeNotas() {
	programa := "notepad.exe"
	attr := &os.ProcAttr{
		Files: []*os.File{os.Stdin, os.Stdout, os.Stderr},
	}

	processo, err := os.StartProcess(programa, []string{programa}, attr)
	if err != nil {
		fmt.Println("Erro ao iniciar processo:", err)
		return
	}

	fmt.Printf("Bloco de Notas iniciado com PID: %d\n", processo.Pid)
}

func main() {
	abrirBlocoDeNotas()
}

✅ Encontrando e finalizando um determinado processo

Por vezes, você vai querer encontrar e fechar um processo que está sendo executado no seu sistema operacional, para isso, use o comando abaixo:

package main

import (
	"fmt"
	"os"
)

func matarProcesso(pid int) {
	processo, err := os.FindProcess(pid)
	if err != nil {
		fmt.Println("Processo não encontrado:", err)
		return
	}

	err = processo.Kill()
	if err != nil {
		fmt.Println("Erro ao encerrar processo:", err)
		return
	}

	fmt.Printf("Processo %d encerrado com sucesso!\n", pid)
}

func main() {
	// Altere para o PID do processo que deseja matar.
	matarProcesso(12345)
}

✅ Capturando sinais do sistema

Em alguns momentos, eu acredito que a sua aplicação vai querer saber se algumas teclas de atalho, ou do seu próprio teclado foram pressionadas, para isso, use os seguintes métodos:

package main

import (
	"fmt"
	"os"
	"os/signal"
	"syscall"
)

func aguardarSinal() {
	canal := make(chan os.Signal, 1)
	signal.Notify(canal, os.Interrupt, syscall.SIGTERM)

	fmt.Println("Aguardando CTRL+C ou SIGTERM...")
	sinalRecebido := <-canal
	fmt.Println("Sinal recebido:", sinalRecebido)
}

func main() {
	aguardarSinal()
}

Observe que neste exemplo, precisamos importar as bibliotecas os/signal e syscall para capturar tais sinais.

✅ Finalizando um programa com código de saída

Além disso, você pode finalizar a execução de um programa da seguinte forma:

package main

import (
	"fmt"
	"os"
)

func validarEntrada(valor int) {
	if valor < 0 {
		fmt.Println("Erro: Valor negativo não permitido.")
		os.Exit(1) // Sai com código de erro 1
	}
	fmt.Println("Valor válido:", valor)
}

func main() {
	validarEntrada(-10)
	fmt.Println("Esse código não será executado.")
}

✅ Executando um comando do sistema e capturando uma saída

Por fim, você pode exibir os arquivos do diretório atual de um determinado programa da seguinte forma:

package main

import (
	"fmt"
	"os"
	"os/exec"
)

func listarArquivos() {
	cmd := exec.Command("cmd", "/C", "dir") // Windows
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr

	err := cmd.Run()
	if err != nil {
		fmt.Println("Erro ao listar diretórios:", err)
	}
}

func main() {
	listarArquivos()
}

📊 Informações do Sistema Operacional

A biblioteca os do Go também oferece funções para obter informações sobre o sistema operacional, tais como:

os.Hostname(): Retorna o nome da máquina (hostname).

os.Getenv(): Recupera o valor de uma variável de ambiente.

os.Environ(): Lista todas as variáveis de ambiente disponíveis.

os.TempDir(): Retorna o diretório padrão de arquivos temporários.

os.UserHomeDir(): Retorna o diretório "Home" do usuário.

os.UserCacheDir(): Retorna o diretório de cache do usuário (desde Go 1.11).

os.UserConfigDir(): Retorna o diretório de configuração do usuário (Go 1.13).

os.Executable(): Retorna o caminho absoluto do executável atual.

Vejamos agora, o uso desses métodos:

✅ Obtendo o nome da máquina

Para obter o nome da máquina atual, use o método abaixo:

package main

import (
	"fmt"
	"os"
)

func main() {
	hostname, err := os.Hostname()
	if err != nil {
		fmt.Println("Erro ao obter o nome da máquina:", err)
		return
	}

	fmt.Println("Nome da máquina:", hostname)
}

✅ Obtendo o diretório do executável atual

Caso desejar, você pode obter o diretório de onde a sua aplicação está sendo executada:

package main

import (
	"fmt"
	"os"
	"path/filepath"
)

func main() {
	exePath, err := os.Executable()
	if err != nil {
		fmt.Println("Erro ao obter o caminho do executável:", err)
		return
	}

	fmt.Println("Caminho do executável:", exePath)
	fmt.Println("Diretório do executável:", filepath.Dir(exePath))
}

✅ Obter o diretório do usuário

Para obter a pasta do usuário atual do seu sistema, use o método:

package main

import (
	"fmt"
	"os"
)

func main() {
	homeDir, err := os.UserHomeDir()
	if err != nil {
		fmt.Println("Erro ao obter o diretório home:", err)
		return
	}

	fmt.Println("Diretório Home do usuário:", homeDir)
}

✅ Obtendo o diretório temporário do usuário

Para obter o diretório temporário do usuário atual, use o método:

package main

import (
	"fmt"
	"os"
)

func main() {
	tempDir := os.TempDir()
	fmt.Println("Diretório temporário do sistema:", tempDir)
}

✅ Listando todas as variáveis de ambiente

Uma forma mais rápida de listar todas as variáveis de ambiente do sistema, é usando o seguinte método:

package main

import (
	"fmt"
	"os"
)

func main() {
	fmt.Println("Variáveis de ambiente:")

	for _, env := range os.Environ() {
		fmt.Println(env)
	}
}

Repositório da lição

Todos os arquivos relacionados com esta lição, podem ser encontrados nos seguintes repositórios abaixo:

Conclusão

Nesta lição, você aprendeu não só a manipular arquivos, como também manipular diretórios, variáveis de ambiente e também recuperar informações do sistema operacional e da aplicação em questão.

Até a próxima lição 😀

Criadores de Conteúdo

Foto do William Lima
William Lima
Fundador da Micilini

Inventor nato, escreve conteudos de programação para o portal da micilini.

Torne-se um MIC 🤖

Mais de 100 mic's já estão conectados na plataforma.