Go Academy · Урок

Указатели и функции

Передача по значению и передача указателя

Урок 2 из 413 шагов

«Указатели и функции» — бесплатный урок Go Academy на CoddyKit. Это урок 2 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Go Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Go Academy содержит 4 уроков всего.

Передача по значению

Go передаёт все аргументы функций по значению — создаётся копия. Изменения внутри функции не влияют на оригинал:

package main
import "fmt"

func increment(n int) { n++ }

func main() {
    x := 5
    increment(x)
    fmt.Println(x) // 5 — unchanged
}

Передача указателя по значению

Передайте указатель, чтобы функция могла изменить исходное значение:

package main
import "fmt"

func increment(n *int) { *n++ }

func main() {
    x := 5
    increment(&x)
    fmt.Println(x) // 6
}

Возврат указателей

Функции могут возвращать указатели на значения, выделенные в куче. Анализ выхода переменных за пределы области видимости в Go обеспечивает безопасность:

package main
import "fmt"

func newInt(v int) *int { return &v }

func main() {
    p := newInt(42)
    fmt.Println(*p) // 42
}

Эффективная работа с большими структурами

Передача большой структуры через указатель позволяет избежать затратного копирования:

package main
import "fmt"

type BigData struct{ Data [1024]int }

func process(d *BigData) { d.Data[0] = 99 }

func main() {
    bd := BigData{}
    process(&bd)
    fmt.Println(bd.Data[0]) // 99
}

Указатель на интерфейс

Требуется редко — интерфейсы уже содержат внутренний указатель. Передача *interface{} почти всегда является ошибкой:

package main
import "fmt"

type Stringer interface{ String() string }

func print(s Stringer) { fmt.Println(s.String()) }

// Pass interface directly, NOT *Stringer
type Name string
func (n Name) String() string { return string(n) }

func main() {
    print(Name("Alice"))
}

Необязательные параметры с указателями

Используйте параметры-указатели, чтобы отличать отсутствие аргумента от нулевого значения:

package main
import "fmt"

func greet(name *string) {
    if name == nil {
        fmt.Println("Hello, stranger")
        return
    }
    fmt.Println("Hello,", *name)
}

func main() {
    s := "Alice"
    greet(&s)
    greet(nil)
}

Изменение через срезы

Срезы уже содержат внутренний указатель, поэтому *[]T часто не требуется. Однако при перераспределении памяти функцией append нужен указатель на сам срез:

package main
import "fmt"

func addItem(s *[]int, v int) { *s = append(*s, v) }

func main() {
    nums := []int{1, 2, 3}
    addItem(&nums, 4)
    fmt.Println(nums) // [1 2 3 4]
}

Псевдонимы указателей

Несколько указателей на одну переменную создают псевдонимы — изменение через один указатель видно через все остальные:

package main
import "fmt"

func main() {
    x := 10
    a, b := &x, &x
    *a = 99
    fmt.Println(*b) // 99 — same memory
}

Как не злоупотреблять указателями

Используйте указатели только при необходимости:

  • Изменение данных внутри функции
  • Большие структуры (>= ~64 байт)
  • Нулевое значение в качестве признака отсутствия

Чрезмерное использование указателей увеличивает нагрузку на сборщик мусора и снижает ясность кода.

Шаблон указателей на функции

Храните указатели на функции в отображении для таблиц диспетчеризации:

package main
import "fmt"

func add(a, b int) int { return a + b }
func sub(a, b int) int { return a - b }

func main() {
    ops := map[string]func(int,int)int{
        "+": add, "-": sub,
    }
    fmt.Println(ops["+"](10, 3)) // 13
    fmt.Println(ops["-"](10, 3)) // 7
}

Быстрая проверка

Как позволить функции изменить целочисленную переменную, определённую в вызывающем коде?

Итоги

Главные выводы:

  • Go передаёт аргументы по значению — для изменения данных используйте указатели
  • Возвращайте из конструкторов указатели для выделения памяти в куче
  • Срезы содержат внутренний указатель, но append может потребовать *[]T
  • Не злоупотребляйте указателями — для небольших типов предпочитайте значения

Практическое задание

Напишите функцию normalize, которая принимает *[]string и преобразует все строки к нижнему регистру на месте с помощью strings.ToLower.

Можно начать бесплатно

Изучай Go с ИИ-репетитором — бесплатно

Пиши и запускай код прямо в браузере, получай мгновенную помощь от ИИ-репетитора 24/7 и продолжи учиться на сайте или в приложении.

Курсы
51
Уроки
203

Часто задаваемые вопросы

Урок «Указатели и функции» бесплатный?

Да — полный текст урока «Указатели и функции» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Go Academy, подпишись на CoddyKit PRO. Курс Go Academy содержит 4 уроков всего.

Чему я научусь в уроке «Указатели и функции»?

Передача по значению и передача указателя Ты практикуешь Go Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Go Academy?

Предыдущий опыт не требуется. Go Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 2 из 4.

Сколько времени занимает урок «Указатели и функции»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Go Academy?

Да. Каждый урок Go Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Что такое указатели
  2. Указатели и функции
  3. Получатели-указатели в методах
  4. new() и когда использовать указатели
← Назад к Go Academy