0

I am recently studying golang and realize that everything passed to a go function get a new copy of same type with different address? Is it something what we call pass by value?

https://go.dev/play/p/eNvezQZrn8i

package main

import "fmt"

func fn(m map[int]int, s []int, i int) {
    fmt.Printf("%p \n", &m)
    fmt.Printf("%p \n", &s)
    fmt.Printf("%p \n", &i)

    m = make(map[int]int)
    s = make([]int, 0)
    i = 1

    fmt.Printf("%p \n", &m)
    fmt.Printf("%p \n", &s)
    fmt.Printf("%p \n", &i)
}

func main() {
    var m map[int]int
    var s []int
    var i int

    fmt.Printf("%p \n", &m)
    fmt.Printf("%p \n", m)
    fmt.Printf("%p \n", &s)
    fmt.Printf("%p \n", &i)

    fn(m, s, i)
    fmt.Println(m == nil)
    fmt.Println(s == nil)
    fmt.Println(i == 0)

    fmt.Printf("%p \n", &m)
    fmt.Printf("%p \n", &s)
    fmt.Printf("%p \n", &i)
}

Output:

0xc00011a018 
0x0 
0xc000116018 
0xc000122000 
0xc00011a028 
0xc000116030 
0xc000122008 
0xc00011a028 
0xc000116030 
0xc000122008 
true
true
true
0xc00011a018 
0xc000116018 
0xc000122000 

So basically everything gets a new address unless we directly pass in the address like below:

package main

import "fmt"

func fn(m *map[int]int, s *[]int, i *int) {
    fmt.Printf("%p \n", m)
    fmt.Printf("%p \n", s)
    fmt.Printf("%p \n", i)

    *m = make(map[int]int)
    *s = make([]int, 0)
    *i = 1

    fmt.Printf("%p \n", &m)
    fmt.Printf("%p \n", &s)
    fmt.Printf("%p \n", &i)
}

func main() {
    var m map[int]int
    var s []int
    var i int

    fmt.Printf("%p \n", &m)
    fmt.Printf("%p \n", &s)
    fmt.Printf("%p \n", &i)

    fn(&m, &s, &i)
    fmt.Println(m == nil)
    fmt.Println(s == nil)
    fmt.Println(i == 0)

    fmt.Printf("%p \n", &m)
    fmt.Printf("%p \n", &s)
    fmt.Printf("%p \n", &i)
}

https://go.dev/play/p/QLSBQd4Dbe0 output

0xc000012028 
0xc000010030 
0xc00001c030 
0xc000012028 
0xc000010030 
0xc00001c030 
0xc000012038 
0xc000012040 
0xc000012048 
false
false
false
0xc000012028 
0xc000010030 
0xc00001c030 

Golang still behaves consistently up to now.

But as for java, everything is passed by the exact memory address:

public class TestReferenceVsPointer {
    public static void main(String[] args) {
        Object obj = new Object();
        int i = 1;
        System.out.println("Object Memory address: " + VM.current().addressOf(obj));
        System.out.println("int Memory address: " + VM.current().addressOf(i));

    }

    public static void print(Object obj, int i){
        System.out.println("Object Memory address: " + VM.current().addressOf(obj));
        System.out.println("int Memory address: " + VM.current().addressOf(i));
    }
}

enter image description here

This is really against my common sense. AS I always thought in java object is passed by pointer but this is apparently not pointer because it still has the same address as the argument. As for primitive value will get a new copy and new address. But it is still same address for the primitive type.

Both java and golang have pass by value but why are they different?

Can anyone give me a clear definition as to what reference, value and pointer are and what the above three examples use: reference, value and pointer? It is better that you can use different languages to answer it

Stan
  • 602
  • 6
  • 23
  • Note that [Java passes references by value](https://stackoverflow.com/questions/40480/is-java-pass-by-reference-or-pass-by-value). – dan1st Jan 20 '23 at 21:51
  • 1
    likely dupe of [Passing by reference and value in Go to functions](https://stackoverflow.com/questions/47296325/passing-by-reference-and-value-in-go-to-functions) – underscore_d Jan 20 '23 at 21:57
  • @underscore_d I need a more systematic answer: What is reference, pointer and value? it needs to be answered by using different language as examples Go is passing new value for pointer or prmitive type, which makes sense. But for java, it should also pass the reference by value,but why does it never get a new address allocated? see here: https://stackoverflow.com/questions/40480/is-java-pass-by-reference-or-pass-by-value – Stan Jan 20 '23 at 22:06
  • 1
    might just be linguistics?... but it boils down to the same thing...you're passing a reference to an object (which boils down to pointers at some level) when you're passing by reference... you can also pass a new copy of that object... which is usually called by value. I don't think Java is strictly one or the other... maybe the real concern is whether the original object is/can be modified by other scopes? – pcalkins Jan 20 '23 at 22:37
  • Both Go and Java have garbage collectors which manage memory, so dealing directly with memory addresses is handled by their run-times. So pointers are not used in code, but set by the run-time (and compilers?). Pointers have a pretty precise definition... it's a handle (reference) to a specific piece of memory(which can hold a value). The terms "pass-by-value" and "pass-by-reference" are a bit more fuzzy. In Java I think there's differences when it comes to primitives and other types... objects can have many types... (even answering what type is this object gets funny) – pcalkins Jan 20 '23 at 23:01
  • @pcalkins maybe you are right. But as a programmer, I really dislike the things which are fuzzy. I like things that can be proved and verified by code. I need to understand what they are internally and at lower level. otherwise it is very easy to make mistakes during coding. value, reference and pointer are used by a lot of languages. If we can have a detailed explanation about these general concept shared by all languages, it is like a universal tool – Stan Jan 21 '23 at 06:08
  • @pcalkins There is nothing fuzzy about pass-by-value and pass-by-reference. Those terms are precise definitions that are valid across languages. Besides them there are other kinds of passing arguments, but those two are the most commonly used. What is usually confusing to people is that those terms use _value_ and _reference_ but in that context it is not related to _reference or value types_. but to how is part of the parameter that is passed on to the method through stack. – Dalija Prasnikar Jan 21 '23 at 07:25
  • In that light reference types consist of two parts: the reference itself and the data that reference points to. When passing parameters pass-by-value and pass-by-reference refer only to the first part - how is reference itself passed. They don't care about other data allocated in some other place. When we say Java is pass-by-value that means the reference part of the parameter is copied (passed as value) to the method. – Dalija Prasnikar Jan 21 '23 at 07:27
  • @Stan You Java example is bad. It is showing the address of the allocated object not the address of the variable or parameter itself. You can verify this by retrieving address of `Object obj2 = obj;` which will be the same as the address of `obj`. Integer object instances are not held in duplicates and what you get here is not address of primitive integer, but its boxed Integer object which is the same object in the both occasions because you are boxing same integer value. – Dalija Prasnikar Jan 21 '23 at 07:36
  • @DalijaPrasnikar Hi you are right. This java example is bad. it is hard to verify the address of var in Java – Stan Jan 22 '23 at 05:10
  • That is because Java does not use raw pointers and memory address is not something developers should be concerned about there. There are easier ways to confirm whether something is pass-by-reference or pass-by-value (besides reading documentation). Pass an object to method and then try to assign null to that parameter or new object. And then check what you have in the variable you passed to the method. If you get null or ne object it is pass-by-reference. – Dalija Prasnikar Jan 22 '23 at 08:17
  • 1
    Note: There are some languages, Swift for instance, that does not have pass-by-reference, but in-out parameter which behaves like pass-by-reference, but has different mechanism behind and some slightly different behavior is some circumstances. So the above test is not fool proof. – Dalija Prasnikar Jan 22 '23 at 08:22
  • @DalijaPrasnikar Thanks for your note. I really appreciate it – Stan Jan 22 '23 at 09:32

0 Answers0