Please explain if golang types pass by value
Asked Answered
F

2

5

I'm trying to make a very simple program that modifies arrays, but ran across some interesting behavior if I converted them to types. https://play.golang.org/p/KC7mqmHuLw It appears that if I have an array go passes by reference, but if I have a type then go passes by value. Is this correct?

I have two variables b and c, both are arrays of 3 integers, but c is of type cT, in every other respect they should be identical. I can assign values as b[0]=-1 and c[0]=-1, but if I pass those arrays as parameters to a function they act very differently.

The output of the program is:

before b: [1 2 3]

before c: [1 2 3]

*after b: [-1 2 0]

*after c: [-1 2 3]

*what? c: [-1 2 0]

My initial assumption is that the lines "after b" and "after c" should have been the same. Am I doing something incorrectly or am I correct about types passing to functions by value (ie. creating copy of the variable before passing to the function)?

package main

import "fmt"

type cT [3]int

func main() {
    b := []int{1, 2, 3}
    c := cT{1, 2, 3}

    fmt.Println("before b:", b)
    fmt.Println("before c:", c)

    b[0] = -1
    c[0] = -1
    mangleB(b) // ignore return value
    mangleC(c) // ignore return value

    fmt.Println("*after b:", b)
    fmt.Println("*after c:", c)

    c = mangleC(c)    
    fmt.Println("*what? c:", c)    
}

func mangleB(row []int) []int {
    row[2] = 0
    return row
}

func mangleC(row cT) cT{
    row[2] = 0
    return row
}
Fulks answered 25/11, 2017 at 13:40 Comment(1)
OK, thanks for the help! With the information provided, I am getting the effect I want by passing a reference to the type manglePC(&c) and changing the function to: func manglePC(row *cT) { (*row)[2] = 0 }Fulks
F
6

The Go Programming Language Specification

Array types

An array is a numbered sequence of elements of a single type, called the element type.

Slice types

A slice is a descriptor for a contiguous segment of an underlying array and provides access to a numbered sequence of elements from that array.

Calls

In a function call, the function value and arguments are evaluated in the usual order. After they are evaluated, the parameters of the call are passed by value to the function and the called function begins execution. The return parameters of the function are passed by value back to the calling function when the function returns.


type cT [3]int

b := []int{1, 2, 3}
c := cT{1, 2, 3}

I have two variables, b and c, both are arrays of 3 integers


No, you don't!

b is a slice of int with length (len(b)) 3 and capacity (cap(b)) 3, c is an array of (len(c)) 3 int.

In Go, all parameters are passed by value. b is passed as a slice descriptor, c is passed as an array. A slice descriptor is a struct with a slice length and capacity, and a pointer to the underlying array.

Fides answered 25/11, 2017 at 13:52 Comment(1)
Isn't a slice descriptor a reference, meaning passing a slice descriptor is passing a reference?Judaea
T
0

See comments:

func main() {
    b := []int{1, 2, 3} // slice
    c := cT{1, 2, 3} // array

    fmt.Println("before b:", b) 
    fmt.Println("before c:", c) 

    b[0] = -1
    c[0] = -1

    // passing in a slice which you can think of as ref to array
    // pass by value, and it is copy of ref to array 
    mangleB(b) // ignore return value

    // passing in copy of array (pass by value)
    // yes full shallow copy of array 
    mangleC(c) // ignore return value
    // if you ignore return modifications are lost

    fmt.Println("*after b:", b)
    fmt.Println("*after c:", c)

    // return value is modified array
    c = mangleC(c)
    // c now copy of array from line 24

    fmt.Println("*what? c:", c)
}

https://play.golang.org/p/OAaCMhc-Ug

Triad answered 25/11, 2017 at 14:27 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.