En Go, el nombre de una entidad (como una función, una variable o una estructura) no es solo una etiqueta estética, es una instrucción para el compilador. La visibilidad de tus componentes se decide mediante una regla muy simple: si el nombre comienza con mayúscula, es exportado (público); si comienza con minúscula, es no exportado (privado para el paquete).
Esta es una de las decisiones de diseño más elegantes del lenguaje porque elimina la necesidad de palabras clave como public, private o protected. En su lugar, el propio nombre de la función o variable le dice al compilador qué debe ser visible fuera del paquete donde fue definida. Esta mecánica funciona porque mantiene la semántica del código limpia y directa, permitiendo que el lector sepa de inmediato el alcance de cualquier elemento con solo mirar su primera letra.
Para usar esto correctamente, debes seguir la convención CamelCase (la primera letra de cada palabra en mayúscula, sin guiones ni guiones bajos como snake_case). Si escribes código para otros, esto es obligatorio para que puedan usar tu librería. Si fallas en esta distinción, el compilador simplemente no te permitirá acceder a lo que intentas usar, resultando en errores de compilación. Por último, la longitud de los nombres debe ser proporcional al ámbito (scope) de la variable: si una variable solo vive en un pequeño bucle, un nombre corto como i es perfecto; si es una variable global o un campo de una estructura importante, usa un nombre descriptivo.
package main
import (
"fmt"
)
// Perfil representa la información de un usuario.
// Perfil es "exportado" porque empieza con mayúscula.
type Perfil struct {
ID int // Exportado: accesible desde otros paquetes.
Nombre string // Exportado: accesible desde otros paquetes.
email string // No exportado: solo accesible dentro de este paquete.
}
// NewPerfil es un constructor idiomático.
// En Go, cuando devuelves un tipo para su inicialización, se suele usar el prefijo New.
func NewPerfil(id int, nombre, email string) Perfil {
return Perfil{
ID: id,
Nombre: nombre,
email: email,
}
}
// Email es un método para obtener el email.
// Nota que NO llamamos al método GetEmail(); en Go, se omite el prefijo "Get".
func (p Perfil) Email() string {
return p.email
}
// ValidarURL es un ejemplo de cómo tratar los acrónimos.
// Los acrónimos como URL o HTTP deben mantener su mayúscula original.
func ValidarURL(url string) bool {
return len(url) > 0
}
func main() {
// Creamos una nueva instancia usando la función exportada.
user := NewPerfil(1, "Alex", "alex@ejemplo.com")
// Accedemos a campos y métodos exportados.
fmt.Printf("Usuario: %s (ID: %d)\n", user.Nombre, user.ID)
fmt.Println("Email:", user.Email())
// Validamos una URL usando el acrónimo correctamente escrito.
if ValidarURL("https://google.com") {
fmt.Println("La URL es válida.")
}
}
Desglose del código
En el ejemplo, observa la estructura Perfil. Al definir ID y Nombre con mayúscula inicial, estamos permitiendo que cualquier otro paquete que importe este código pueda leer y modificar esos campos. Sin embargo, email comienza con minúscula, lo que lo convierte en una propiedad privada. Aunque podemos acceder a él dentro de main porque estamos en el mismo paquete, si este código estuviera en un paquete llamado user, no podrías hacer user.email desde fuera.
El método Email() ilustra una convención crucial: el rechazo al prefijo Get. Mientras que en otros lenguajes es común ver user.GetEmail(), en Go lo idiomático es llamar al método simplemente Email(). Esto hace que el código sea mucho más fluido y menos ruidoso.
Fíjate también en la función ValidarURL. En Go, si usas un acrónimo, este debe mantener su capitalización en todo su nombre. No escribas ValidarUrl ni ValidarUrlString; lo correcto es ValidarURL. Lo mismo aplica para HTTP, ID, o JSON.
El error frecuente
Un error muy común para quienes vienen de Java o JavaScript es intentar acceder a un campo “privado” desde un archivo externo, esperando que el compilador les dé un error de lógica, cuando en realidad el error es de visibilidad.
// Supongamos que este código está en el paquete "main"
// y que el tipo Perfil está definido en el paquete "models".
package main
import "proyecto/models"
func main() {
p := models.Perfil{ID: 1}
// ERROR DE COMPILACIÓN:
// p.email es un campo no exportado (unexported)
// y no es accesible desde fuera del paquete "models".
fmt.Println(p.email)
}
Si intentas hacer esto, el compilador de Go te detendrá inmediatamente con un error de tipo cannot refer to unexported field email. No es un error de ejecución que aparecerá cuando el programa corra; es una regla de seguridad que el compilador aplica antes de que el binario siquiera se cree.
N° 15