Go (или Golang) — это современный статически типизированный компилируемый язык программирования, предназначенный для создания масштабируемого, параллельного и эффективного программного обеспечения. Он поставляется с различными встроенными функциями и возможностями, которые помогают разработчикам писать краткий и производительный код. Среди этих функций есть new()
и make()
, которые на первый взгляд могут показаться похожими, но служат разным целям и имеют решающее значение для распределения памяти и инициализации данных в Go.
В этом сообщении блога мы рассмотрим различия между функциями new()
и make()
и поймем, когда и как их эффективно использовать.
new()
и make()
Функции
И new()
, и make()
— встроенные функции Go, используемые для распределения памяти. Однако они используются для разных типов данных и сценариев:
new()
функция:
new()
используется для выделения памяти для типов значений (например, целых чисел, чисел с плавающей запятой, структур) и возвращает указатель на вновь выделенное обнуленное значение.- Он принимает один аргумент, который является типом, и возвращает указатель на этот тип.
функция make():
make()
используется для создания и инициализации срезов, карт и каналов, которые в Go являются ссылочными типами.- Он принимает два или три аргумента, в зависимости от типа, и возвращает инициализированное (не обнуленное) значение, готовое к использованию.
Понимание функции new()
Синтаксис функции new()
прост, как показано ниже.
func new(Type) *Type
Здесь Type
представляет тип значения, для которого мы хотим выделить память. Давайте посмотрим пример использования new()
.
В этом примере мы создаем новый экземпляр структуры Person
, используя new()
, а затем присваиваем значения его полям, используя указатель.
package main import "fmt" type Person struct { Name string Age int } func main() { // Using new() to allocate memory for a Person struct p := new(Person) fmt.Printf("%T\n", p) // Accessing struct fields using the pointer p.Name = "Alice" p.Age = 30 // Displaying the values fmt.Println("Name:", p.Name) fmt.Println("Age:", p.Age) }
Эта программа выдаст результат, как показано ниже.
> go run main.go *main.Person Name: Alice Age: 30
Понимание make()
функции
Синтаксис функции make()
варьируется в зависимости от типа, с которым она используется.
Для фрагментов
func make([]Type, len, cap) []Type
Type
: Тип элементов, которые будет содержать срез.len
: Начальная длина среза.cap
: емкость среза, которая не является обязательной и используется для указания емкости базового массива. Если оно не указано, по умолчанию оно принимает то же значение, что и длина.
Пример создания среза с помощью make()
:
package main import "fmt" func main() { // Using make() to create a slice of integers numbers := make([]int, 5, 10) // Displaying the slice's length, capacity, and values fmt.Println("Length:", len(numbers)) fmt.Println("Capacity:", cap(numbers)) fmt.Println("Values:", numbers) // Using make() to create a slice of integers numbersWithoutOptional := make([]int, 5) // Displaying the slice's length, capacity, and values fmt.Println("Length:", len(numbersWithoutOptional)) fmt.Println("Capacity:", cap(numbersWithoutOptional)) fmt.Println("Values:", numbersWithoutOptional) }
Эта программа выдаст результат, как показано ниже.
> go run main.go Length: 5 Capacity: 10 Values: [0 0 0 0 0] Length: 5 Capacity: 5 Values: [0 0 0 0 0]
Для карт
func make(map[KeyType]ValueType, initialCapacity int) map[KeyType]ValueType
KeyType
: Тип ключей на карте.ValueType
: Тип значений, связанных с ключами.initialCapacity
: Начальная вместимость карты. Это необязательно, но его можно использовать для оптимизации производительности, если количество элементов известно заранее.
Пример создания карты с помощью make()
package main import "fmt" func main() { // Using make() to create a map of string keys and int values scores := make(map[string]int) // Adding values to the map scores["Alice"] = 95 scores["Bob"] = 87 // Displaying the map fmt.Println("Scores:", scores) } > go run main.go Scores: map[Alice:95 Bob:87]
Для каналов
func make(chan Type, capacity int) chan Type
Type
: Тип значений, которые можно отправлять и получать через канал.capacity
: Размер буфера канала. Если установлено значение 0, канал не буферизуется.
Пример создания канала с помощью make()
package main import ( "fmt" "time" ) func main() { // Using make() to create an unbuffered channel of integers ch := make(chan int) // Sending data into the channel using a goroutine go func() { for i := 1; i <= 5; i++ { ch <- i time.Sleep(time.Second) // Simulating some work before sending the next value } close(ch) }() // Receiving data from the channel for num := range ch { fmt.Println("Received:", num) } } > go run main.go Received: 1 Received: 2 Received: 3 Received: 4 Received: 5
Заключение
В этом сообщении блога мы раскрыли тайну функций new()
и make()
в Go и объяснили их различия и варианты использования. Обобщить:
- Используйте
new()
, чтобы выделить память для типов значений и получить указатель на обнуленное значение. - Используйте
make()
для создания и инициализации фрагментов, карт и каналов (ссылочных типов) с соответствующими типами и исходными возможностями.
Понимание различий между new()
и make()
имеет решающее значение для эффективного распределения памяти и инициализации данных в Go. Правильное применение этих функций приведет к более чистому и оптимизированному коду в ваших проектах Golang. Приятного кодирования!
Первоначально опубликовано для https://thebugshots.dev