查看: 50|回复: 0

Go语言地址引用的问题解决

[复制链接]

0

主题

0

回帖

0

积分

积极分子

金币
0
阅读权限
220
精华
0
威望
0
贡献
0
在线时间
0 小时
注册时间
2009-10-8
发表于 2025-11-21 09:25:57 | 显示全部楼层 |阅读模式

1、channel

先看以下代码:

package main

import "fmt"

func main() {
	ch1 := make(chan int, 3)
	ch2 := ch1
	ch1 <- 123
	ch2 <- 456
	fmt.Println(ch1, ch2)     //输出地址是否一样?  TODO:打印结果是?
	fmt.Println(<-ch2, <-ch1) // ch2中的数据是:456; ch1中的数据是123;TODO:打印结果是?
}

输出结果:

代码分析:

在以上代码中,新定义的变量ch2:=ch1 ;ch2是地址引用,ch1,ch2地址指向的是同一块数据,ch1、ch2都可以改变数据。

2、slice

看看以下代码:

package main

import "fmt"

func main() {
	s := make([]int, 3)
	s1 := s
	s2 := s
	s[0] = 123
	s1[1] = 456
	s2[2] = 789
	fmt.Println("原始切片:", s)
	fmt.Println("赋值切片:", s1)
	fmt.Println("赋值切片:", s2)
	fmt.Println("切片的长度、容量为:", len(s), cap(s))
	fmt.Printf("追加之前的地址:s:%p ;s1:%p; s2:%p\n",s,s1,s2)
	fmt.Println("====执行append操作====")
	s2 = append(s2, 123)
	fmt.Printf("追加之后的地址:s:%p ;s1:%p; s2:%p\n",s,s1,s2)
	fmt.Println("原始切片s:", s)
	fmt.Println("赋值切片s1:", s1)
	fmt.Println("赋值切片s2:", s2)
}

输出结果:

代码分析:起初,s,s1,s2都指向同一块数据。所以任意一个变量修改了该块数据,其他变量查到的都是修改之后的数据。

指向:

s2 = append(s2, 123),会在末尾追加一个元素,由于现有s2的
cap(s)=3, len(s)=3;

在追加数据时,容量已经不够,会开辟新的内存,将现有数据s2拷贝,形成新的s2。当然在容量足够的情况下,不会开辟新的内存空间。

再来看以下代码:(容量大于append的数据数量)

package main

import "fmt"

func main() {
	s := make([]int, 3,6)
	s1 := s
	s2 := s
	s[0] = 123
	s1[1] = 456
	s2[2] = 789
	fmt.Println("原始切片:", s)
	fmt.Println("赋值切片:", s1)
	fmt.Println("赋值切片:", s2)
	fmt.Println("切片的长度、容量为:", len(s), cap(s))
	fmt.Printf("追加之前的地址:s:%p ;s1:%p; s2:%p\n",s,s1,s2)
	fmt.Println("====执行append操作====")
	s2 = append(s2, 123)
	fmt.Printf("追加之后的地址:s:%p ;s1:%p; s2:%p\n",s,s1,s2)
	s[0]=888 // TODO:会修改s1、s2吗
	fmt.Println("原始切片s:", s)
	fmt.Println("赋值切片s1:", s1)
	fmt.Println("赋值切片s2:", s2)
}

输出效果:

在以上代码中添加内容:

package main

import "fmt"

func main() {
	s := make([]int, 3,6)
	s1 := s
	s2 := s
	s[0] = 123
	s1[1] = 456
	s2[2] = 789
	fmt.Println("原始切片:", s)
	fmt.Println("赋值切片:", s1)
	fmt.Println("赋值切片:", s2)
	fmt.Println("切片的长度、容量为:", len(s), cap(s))
	fmt.Printf("追加之前的地址:s:%p ;s1:%p; s2:%p\n",s,s1,s2)
	fmt.Println("====执行append操作====")
	s2 = append(s2, 123)
	fmt.Printf("追加之后的地址:s:%p ;s1:%p; s2:%p\n",s,s1,s2)
	s[0]=888 // TODO:会修改s1、s2吗
	fmt.Println("原始切片s:", s)
	fmt.Println("赋值切片s1:", s1)
	fmt.Println("赋值切片s2:", s2)
	fmt.Println("执行以下操作,输出结果又是什么呢?")
	s = append(s, 666)
	fmt.Println("原始切片s:", s)
	fmt.Println("赋值切片s1:", s1)
	fmt.Println("赋值切片s2:", s2)
}

特别说明:Go语言为了节省内存空间,对于切片、map、channel、指针等地址引用的变量,会操作同一块地址对应的数据,在操作时也特别留意。

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

相关侵权、举报、投诉及建议等,请发 E-mail:qiongdian@foxmail.com

Powered by Discuz! X5.0 © 2001-2026 Discuz! Team.

在本版发帖返回顶部