Desafio Go
Módulo com múltiplos pacotes e internal
Enunciado
Crie um módulo exemplo.com/empresa com a seguinte estrutura:
- Pacote
funcionarios(emfuncionarios/) que exporte a structFuncionariocom camposNome(string) eSalario(float64), e uma funçãoNovoFuncionario(nome string, salario float64) Funcionario. - Pacote
internal/folha(eminternal/folha/) que exporte a funçãoCalcularTotal(funcs []funcionarios.Funcionario) float64. main.goque cria dois funcionários, calcula o total da folha e imprime no formatoTotal da folha: R$ 7500.00.
Use valores: Ana com 5000.00 e Bruno com 2500.00.
Requisitos
- O módulo deve se chamar
exemplo.com/empresa. - O pacote
funcionariosdeve estar emfuncionarios/e exportarFuncionarioeNovoFuncionario. - O pacote
folhadeve estar eminternal/folha/e importarfuncionarios. - A saída deve ser exatamente
Total da folha: R$ 7500.00.
Código inicial
// main.go
package main
import (
"fmt"
// importe os pacotes necessários
)
func main() {
// crie os funcionários e calcule o total
fmt.Println("Total da folha: R$ 0.00") // substitua
}
Saída esperada
Total da folha: R$ 7500.00
Ver dica
No pacote folha, você precisará importar exemplo.com/empresa/funcionarios. A função CalcularTotal percorre a slice e soma os salários. Use fmt.Printf com R$ %.2f.
Mostrar solução
// go.mod
module exemplo.com/empresa
go 1.22
// funcionarios/funcionarios.go
package funcionarios
// Funcionario representa um empregado.
type Funcionario struct {
Nome string
Salario float64
}
// NovoFuncionario cria um Funcionario com os dados fornecidos.
func NovoFuncionario(nome string, salario float64) Funcionario {
return Funcionario{Nome: nome, Salario: salario}
}
// internal/folha/folha.go
package folha
import "exemplo.com/empresa/funcionarios"
// CalcularTotal soma os salários de uma lista de funcionários.
func CalcularTotal(funcs []funcionarios.Funcionario) float64 {
total := 0.0
for _, f := range funcs {
total += f.Salario
}
return total
}
// main.go
package main
import (
"fmt"
"exemplo.com/empresa/funcionarios"
"exemplo.com/empresa/internal/folha"
)
func main() {
ana := funcionarios.NovoFuncionario("Ana", 5000.00)
bruno := funcionarios.NovoFuncionario("Bruno", 2500.00)
total := folha.CalcularTotal([]funcionarios.Funcionario{ana, bruno})
fmt.Printf("Total da folha: R$ %.2f\n", total)
}
Passo a passo
- Criamos o módulo com
go mod init exemplo.com/empresa. - No pacote
funcionarios, definimos a structFuncionariocom campos exportadosNomeeSalario. - A função
NovoFuncionarioé um construtor que retorna uma instância deFuncionario. - No pacote
internal/folha, importamosexemplo.com/empresa/funcionarios(permitido porque estamos dentro do módulo). CalcularTotalpercorre a slice de funcionários e soma os salários.- No
main.go, criamos dois funcionários comNovoFuncionarioe os colocamos em uma slice. - Chamamos
folha.CalcularTotalpassando a slice e armazenamos o resultado. - Imprimimos com
fmt.PrintfusandoR$ %.2fpara formatar o valor.
Por que funciona
A estrutura de pastas define pacotes separados: funcionarios e internal/folha. O pacote folha está em internal, então só pode ser importado por código dentro do módulo exemplo.com/empresa. Como main.go está na raiz, pode importá-lo. A comunicação entre pacotes usa tipos exportados: folha importa funcionarios e usa funcionarios.Funcionario como tipo de parâmetro. O compilador verifica se todos os identificadores usados são exportados e se os imports são válidos.
Erros comuns
- Esquecer de exportar campos da struct: se
Funcionariotivesse camposnomeesalario(minúsculos), o pacotefolhanão conseguiria acessá-los. Erro:f.Salario undefined (cannot refer to unexported field or method salario). - Import cycle: se
funcionariosimportassefolhae vice-versa, o compilador acusaria ciclo de importação. A solução é manter dependências em uma direção só. - Caminho de import errado: usar
import "empresa/funcionarios"em vez deexemplo.com/empresa/funcionarios. O Go não encontra o pacote. - Não usar
internalcorretamente: sefolhaestivesse fora deinternal, ainda funcionaria, mas perderia a restrição de acesso.
Outra forma de resolver
Se não precisasse restringir o acesso, folha poderia ficar em folha/ diretamente. O uso de internal é uma escolha de design para esconder detalhes de implementação. Também é possível usar um método Total() na struct, mas a função separada demonstra melhor a interação entre pacotes.
Saída esperada
Total da folha: R$ 7500.00