Указатели и функции
Передача по значению и передача указателя
«Указатели и функции» — бесплатный урок 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 — локальная установка не требуется.
Все уроки этого курса
- Что такое указатели
- Указатели и функции
- Получатели-указатели в методах
- new() и когда использовать указатели