You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

值、引用与指针定义及Go、Java传参机制差异问询

关于Go与Java传参机制的疑问

我近期学习Go语言时发现:传入Go函数的所有参数都会生成同类型的新副本,且地址不同,这是否就是所谓的值传递?


一、Go语言传参观察

示例1:直接传入参数

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)
}

输出:

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

由此可见,所有参数都会获得新地址,除非直接传入地址:

示例2:传入指针

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)
}

输出:

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

Go语言的表现始终一致。


二、Java语言传参观察

但在Java中,所有参数似乎都是按精确内存地址传递的:

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));
    }
}

运行结果截图:
Java传参地址输出

这与我的认知相悖:我一直认为Java中的对象是按指针传递的,但参数与实参的地址相同;原以为基本类型会生成新副本并拥有新地址,但实际地址也相同。


三、核心疑问

  1. 既然Go和Java均采用值传递,为何表现会有差异?
  2. 恳请明确值、引用、指针的定义,并说明上述三个示例分别采用了哪种传参方式(值、引用还是指针),最好结合不同语言进行解答。

内容的提问来源于stack exchange,提问作者Stan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 21:45:38