Как в Go передаются аргументы в функции?

Ответ

В Go все аргументы в функции передаются исключительно по значению (pass by value). Это означает, что функция всегда получает копию передаваемой переменной, а не саму переменную.

Однако поведение зависит от типа данных:


  1. Простые типы (int, string, bool, struct):

    Создается полная копия значения. Изменения этой копии внутри функции не влияют на исходную переменную.


  2. Ссылочные типы (слайсы, мапы, каналы, указатели):

    Копируется не сам базовый массив данных или структура, а значение-дескриптор (для слайсов, мап) или адрес в памяти (для указателей). Этот дескриптор или указатель по-прежнему ссылается на ту же самую область памяти, что и оригинал.

    • Слайсы и мапы: Изменение элементов слайса или мапы внутри функции будет видно снаружи, так как копия дескриптора указывает на тот же базовый массив данных.
    • Указатели: Изменение значения, на которое указывает указатель, также будет видно снаружи.

Пример для наглядности:

package main

import "fmt"

// Принимает копию int. Изменения не видны снаружи.
func modifyValue(val int) {
    val = 100
}

// Принимает копию указателя. Изменения по указателю видны снаружи.
func modifyPointer(ptr *int) {
    *ptr = 100
}

// Принимает копию дескриптора слайса. Изменения элементов видны снаружи.
func modifySlice(slice []int) {
    slice[0] = 100
}

func main() {
    // Простой тип
    num := 10
    modifyValue(num)
    fmt.Println("num после modifyValue:", num) // Вывод: 10

    // Указатель
    modifyPointer(&num)
    fmt.Println("num после modifyPointer:", num) // Вывод: 100

    // Слайс
    s := []int{1, 2, 3}
    modifySlice(s)
    fmt.Println("slice после modifySlice:", s) // Вывод: [100 2 3]
}

Вывод: Хотя технически передача всегда идет по значению, для ссылочных типов эффект похож на передачу по ссылке, так как копируется не сама структура данных, а указатель на нее.