← Назад к вопросам

Что делает оператор asterisk в Go?

2.3 Middle🔥 71 комментариев
#Основы Go

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI7 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Оператор asterisk (*) в Go: основные применения

В языке Go оператор asterisk (*) играет ключевую роль в двух контекстах: как оператор указателя (pointer) и как оператор разыменования (dereferencing). Его использование фундаментально для работы с памятью и структурами данных.

1. Объявление и использование указателей

Указатель — это переменная, хранящая адрес памяти другой переменной, а не её значение. Оператор * используется для объявления типа указателя.

package main

import "fmt"

func main() {
    var value int = 42
    var pointer *int = &value // *int — тип "указатель на int"
    
    fmt.Println("Значение:", value)       // Вывод: 42
    fmt.Println("Адрес:", pointer)        // Вывод: 0xc0000180a8 (адрес)
    fmt.Println("Значение через указатель:", *pointer) // Вывод: 42
}

В этом примере:

  • *int объявляет тип указатель на целое число
  • &value возвращает адрес переменной value (оператор взятия адреса)
  • *pointer разыменовывает указатель, получая значение из памяти

2. Разыменование указателей

Разыменование — процесс получения значения, хранящегося в памяти по адресу, который содержит указатель.

func modifyViaPointer(ptr *int) {
    *ptr = 100 // Разыменовываем ptr и изменяем значение в памяти
}

func main() {
    x := 50
    modifyViaPointer(&x)
    fmt.Println(x) // Вывод: 100 (значение изменено через указатель)
}

Ключевой момент: без разыменования через * мы работаем только с адресом, не с самим значением.

3. Указатели в структурах и функциях

Указатели особенно важны для эффективной работы с структурами (structs) и избежания копирования больших данных.

type Person struct {
    Name string
    Age  int
}

func (p *Person) UpdateAge(newAge int) {
    p.Age = newAge // Метод с указателем изменяет оригинал
}

func main() {
    person := Person{Name: "Alice", Age: 30}
    person.UpdateAge(35)
    fmt.Println(person.Age) // Вывод: 35
}

Различие между методами с указателем (*Person) и с значением (Person):

  • Метод с указателем работает с оригинальной структурой, изменяя её
  • Метод со значением получает копию структуры, изменения не сохраняются

4. Оператор * в типах (псевдонимы указателей)

* также используется при объявлении псевдонимов типов (type aliases) для указателей.

type IntPtr *int       // Псевдоним для типа *int
type PersonPtr *Person // Псевдоним для указателя на Person

5. Особенности и лучшие практики

  • Nil указатели: указатель может быть nil (нулевым). Попытка разыменовать nil указатель вызывает панику (panic)
var ptr *int = nil
// *ptr // PANIC: runtime error: invalid memory address or nil pointer dereference
  • Нет pointer arithmetic: в отличие от C/C++, Go не поддерживает арифметику указателей (ptr++, ptr--). Это повышает безопасность.

  • **Оператор & vs ***: & берет адрес переменной, * разыменовывает указатель или объявляет тип указателя.

Итог: оператор * в Go — это мощный инструмент для управления памятью и создания эффективных программ. Он позволяет:

  1. Работать с данными через адреса, избегая копирования
  2. Изменять значения в функциях (аналог "pass by reference")
  3. Создавать методы, которые модифицируют структуры
  4. Контролировать выделение памяти и производительность

Правильное использование указателей требует понимания их природы: они дают прямый доступ к памяти, что одновременно и мощно, и требует осторожности (особенно с nil указателями). В Go указатели — компромисс между безопасностью (нет pointer arithmetic) и эффективностью работы с данными.

Что делает оператор asterisk в Go? | PrepBro