La función new()
Parte de la sección Programación Orientada a Objetos del Journey de GO de Coddy — lección 22 de 107.
Go proporciona una función incorporada llamada new() que asigna memoria para un tipo y devuelve un puntero a él. La memoria asignada se inicializa con el valor cero del tipo.
p := new(int) // asigna memoria para un int
fmt.Println(*p) // 0 (valor cero)
fmt.Println(p) // 0xc000018030 (dirección de memoria)La función new() toma un tipo como argumento y devuelve un puntero a un valor cero recién asignado de ese tipo. Esto es particularmente útil cuando necesitas un puntero pero no tienes una variable existente a la cual hacer referencia.
Con las estructuras, new() crea un puntero a una estructura con todos los campos establecidos en sus valores cero.
type Person struct {
Name string
Age int
}
p := new(Person)
fmt.Println(p.Name) // "" (cadena vacía)
fmt.Println(p.Age) // 0Tal vez te preguntes cuándo usar new() en comparación con el operador de dirección &. Ambos enfoques a continuación son equivalentes:
// Usando new()
p1 := new(Person)
// Usando el operador de dirección con un literal
p2 := &Person{}La sintaxis &Person{} es más común en la práctica porque permite inicializar campos al mismo tiempo. Utiliza new() cuando desees específicamente una instancia con valores cero y prefieras una semántica de asignación de memoria explícita.
Desafío
FácilVamos a construir un gestor de configuración que demuestre cómo new() asigna memoria e inicializa structs a sus valores cero. Verás cómo este enfoque difiere del uso del operador de dirección con un literal de struct.
Organizarás tu código en dos archivos:
config.go: Define un structServerConfigcon los camposHost(string),Port(int),MaxConnections(int) yDebugMode(bool). Crea dos funciones:NewServerConfigque utilizanew()para asignar unServerConfigy devuelve el puntero directamente (con todos los valores cero)ConfigureServerque recibe un puntero*ServerConfigjunto con un string para el host y un entero para el puerto, y luego establece esos campos en la configuración a través del puntero
Displayen*ServerConfigque devuelva un string formateado mostrando todos los valores de configuración.main.go: Lee un host y un puerto de la entrada. Primero, crea una configuración usandoNewServerConfig()y muéstrala para ver los valores cero. Luego usaConfigureServerpara establecer el host y el puerto, y muestra la configuración de nuevo para ver los valores actualizados.
Se proporcionarán las siguientes entradas:
- Línea 1: Nombre del host (string)
- Línea 2: Número de puerto (entero)
Tu método Display debe devolver un string en este formato exacto:
Host: [Host]
Port: [Port]
MaxConnections: [MaxConnections]
DebugMode: [DebugMode]Imprime la salida de display dos veces: una antes de configurar (mostrando los valores cero) y otra después de configurar (mostrando el host y el puerto actualizados).
Por ejemplo, dados localhost y 8080, tu salida debería ser:
Host:
Port: 0
MaxConnections: 0
DebugMode: false
Host: localhost
Port: 8080
MaxConnections: 0
DebugMode: falseObserva cómo la primera visualización muestra todos los valores cero (string vacío, 0, 0, false) porque new() inicializa todo a sus valores cero. Después de llamar a ConfigureServer, solo cambian el host y el puerto, mientras que los otros campos permanecen en sus valores cero.
Hoja de referencia
La función new() asigna memoria para un tipo y devuelve un puntero a él, inicializado al valor cero del tipo:
p := new(int) // asigna memoria para un int
fmt.Println(*p) // 0 (valor cero)
fmt.Println(p) // 0xc000018030 (dirección de memoria)Con structs, new() crea un puntero a un struct con todos los campos establecidos en sus valores cero:
type Person struct {
Name string
Age int
}
p := new(Person)
fmt.Println(p.Name) // "" (cadena vacía)
fmt.Println(p.Age) // 0El uso de new() frente al operador de dirección & - ambos son equivalentes:
// Usando new()
p1 := new(Person)
// Usando el operador de dirección con un literal
p2 := &Person{}La sintaxis &Person{} es más común porque permite la inicialización de campos en el momento de la creación. Use new() cuando desee una instancia con valor cero con una semántica de asignación de memoria explícita.
Pruébalo tú mismo
package main
import (
"fmt"
)
func main() {
// Leer la entrada
var host string
var port int
fmt.Scanln(&host)
fmt.Scanln(&port)
// TODO: Crear una configuración usando NewServerConfig() y mostrarla
// Esto mostrará los valores cero
// TODO: Usar ConfigureServer para establecer el host y el port
// TODO: Mostrar la configuración de nuevo para ver los valores actualizados
}
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Programación Orientada a Objetos
1Fundamentos de POO en Go
Archivos externosEspacio de trabajo y módulos de GoPaquetes e importacionesNombres exportados vs. no exportadosIntroducción a la POO en GoStructs como clasesDefinición de métodos en structsReceptores de puntero vs. de valorInicialización de structsFunciones constructorasResumen - Calculadora simple4Interfaces
Introducción a las interfacesImplementación implícitaLa interfaz como contratoInterfaz vacía (any)Type AssertionType SwitchComposición de interfacesInterfaces Stringer y ErrorResumen: Calculadora de figuras7Encapsulamiento
Campos exportados vs. no exportadosEncapsulamiento a nivel de paqueteMétodos Getter y SetterOcultamiento de información en GoResumen - Registros de estudiantes10Genéricos (Go 1.18+)
Introducción a los GenéricosParámetros de tipoRestricciones de tipoStructs genéricosSolución alternativa para métodos genéricosResumen - Colección genérica13Patrones de diseño - Parte 1
Introducción a los patrones de diseñoPatrón SingletonPatrón FactoryPatrón Abstract FactoryPatrón ObserverPatrón Strategy2Inmersión profunda en Tipos y Structs
Tipos básicos y compuestosDefiniciones de tipos personalizadosEtiquetas de StructsStructs anónimosStructs anidadosValores cero y por defectoRepaso - Libreta de contactos5Composición sobre herencia
Por qué Go no tiene herenciaConceptos básicos de incrustación de structsPromoción de métodosIncrustación de múltiples structsIncrustación vs AgregaciónShadowing de métodos incrustadosResumen - Jerarquía de empleados8Manejo de Errores y OOP
La interfaz errorTipos de errores personalizadosEnvoltura de errores (fmt.Errorf)Errores centinelaerrors.Is() y errors.As()Panic, Defer y RecoverResumen - Analizador de archivos3Punteros y Memoria
Fundamentos de punteros en GoPunteros a StructsPaso por valor vs referenciaLa función new()Garbage Collection en GoResumen - Constructor de Linked List6Polimorfismo en Go
Polimorfismo mediante interfacesDuck Typing en GoReglas de satisfacción de interfacesColecciones polimórficasInyección de dependenciasResumen - Procesador de pagos9Concurrencia y POO
Fundamentos de GoroutinesChannels y comunicaciónChannels con buffer vs. sin bufferSentencia Selectsync.Mutex y sync.RWMutexsync.WaitGroupDiseño de estructuras Thread-SafeResumen - Worker Pool