值、引用与指针定义及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中的对象是按指针传递的,但参数与实参的地址相同;原以为基本类型会生成新副本并拥有新地址,但实际地址也相同。
三、核心疑问
- 既然Go和Java均采用值传递,为何表现会有差异?
- 恳请明确值、引用、指针的定义,并说明上述三个示例分别采用了哪种传参方式(值、引用还是指针),最好结合不同语言进行解答。
内容的提问来源于stack exchange,提问作者Stan
相关产品推荐
相关产品推荐

