Menu
Coddy logo textTech

Функция new()

Часть раздела Объектно-ориентированное программирование путешествия по GO на Coddy — урок 22 из 107.

Go предоставляет встроенную функцию под названием new(), которая выделяет память для типа и возвращает указатель на неё. Выделенная память инициализируется нулевым значением этого типа.

p := new(int)      // выделяет память для int
fmt.Println(*p)    // 0 (нулевое значение)
fmt.Println(p)     // 0xc000018030 (адрес памяти)

Функция new() принимает тип в качестве аргумента и возвращает указатель на вновь выделенное нулевое значение этого типа. Это особенно полезно, когда вам нужен указатель, но у вас нет существующей переменной для ссылки.

При работе со структурами new() создает указатель на структуру, в которой всем полям присвоены их нулевые значения.

type Person struct {
    Name string
    Age  int
}

p := new(Person)
fmt.Println(p.Name)  // "" (пустая строка)
fmt.Println(p.Age)   // 0

Вы можете задаться вопросом, когда использовать new() в сравнении с оператором взятия адреса &. Оба подхода ниже эквивалентны:

// Использование new()
p1 := new(Person)

// Использование оператора взятия адреса с литералом
p2 := &Person{}

Синтаксис &Person{} более распространен на практике, поскольку он позволяет инициализировать поля одновременно. Используйте new(), когда вам специально нужен экземпляр с нулевыми значениями и вы предпочитаете семантику явного выделения памяти.

challenge icon

Задание

Легко

Давайте создадим менеджер конфигурации, который демонстрирует, как new() выделяет память и инициализирует структуры их нулевыми значениями. Вы увидите, чем этот подход отличается от использования оператора взятия адреса со структурным литералом.

Вы организуете свой код в двух файлах:

  • config.go: Определите структуру ServerConfig с полями Host (string), Port (int), MaxConnections (int) и DebugMode (bool). Создайте две функции:
    • NewServerConfig, которая использует new() для выделения памяти под ServerConfig и возвращает указатель напрямую (со всеми нулевыми значениями)
    • ConfigureServer, которая принимает указатель *ServerConfig вместе со строкой хоста и целым числом порта, а затем устанавливает эти поля в конфигурации через указатель
    Также добавьте метод Display для *ServerConfig, который возвращает отформатированную строку, показывающую все значения конфигурации.
  • main.go: Считайте хост и порт из входных данных. Сначала создайте конфигурацию с помощью NewServerConfig() и отобразите ее, чтобы показать нулевые значения. Затем используйте ConfigureServer для установки хоста и порта и снова отобразите конфигурацию, чтобы показать обновленные значения.

Будут предоставлены следующие входные данные:

  • Строка 1: Имя хоста (string)
  • Строка 2: Номер порта (integer)

Ваш метод Display должен возвращать строку именно в таком формате:

Host: [Host]
Port: [Port]
MaxConnections: [MaxConnections]
DebugMode: [DebugMode]

Выведите результат отображения дважды — один раз перед настройкой (показывая нулевые значения) и один раз после настройки (показывая обновленные хост и порт).

Например, для localhost и 8080 ваш вывод должен быть следующим:

Host: 
Port: 0
MaxConnections: 0
DebugMode: false
Host: localhost
Port: 8080
MaxConnections: 0
DebugMode: false

Обратите внимание, что при первом отображении выводятся все нулевые значения (пустая строка, 0, 0, false), потому что new() инициализирует все нулевыми значениями. После вызова ConfigureServer изменяются только хост и порт, в то время как остальные поля остаются со своими нулевыми значениями.

Шпаргалка

Функция new() выделяет память для типа и возвращает указатель на нее, инициализированный нулевым значением этого типа:

p := new(int)      // выделяет память для int
fmt.Println(*p)    // 0 (нулевое значение)
fmt.Println(p)     // 0xc000018030 (адрес памяти)

В случае со структурами new() создает указатель на структуру, все поля которой установлены в их нулевые значения:

type Person struct {
    Name string
    Age  int
}

p := new(Person)
fmt.Println(p.Name)  // "" (пустая строка)
fmt.Println(p.Age)   // 0

Использование new() в сравнении с оператором взятия адреса & — оба варианта эквивалентны:

// Использование new()
p1 := new(Person)

// Использование оператора адреса с литералом
p2 := &Person{}

Синтаксис &Person{} встречается чаще, так как он позволяет инициализировать поля во время создания. Используйте new(), когда вам нужен экземпляр с нулевыми значениями и явной семантикой выделения памяти.

Попробуйте сами

package main

import (
	"fmt"
)

func main() {
	// Чтение входных данных
	var host string
	var port int
	fmt.Scanln(&host)
	fmt.Scanln(&port)

	// TODO: Создайте конфигурацию с помощью NewServerConfig() и выведите её
	// Это покажет нулевые значения

	// TODO: Используйте ConfigureServer для установки host и port

	// TODO: Снова выведите конфигурацию, чтобы показать обновленные значения
}
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Объектно-ориентированное программирование