-
Go通关14:参数传递中,值、引用及指针之间的区别
值类型、引用类型
1、在Go语言中,值类型和引用类型有以下特点:
a、值类型:基本数据类型,int,float,bool,string,以及数组和struct
特点:变量直接存储值,内存通常在栈上分配
,栈在函数调用完会被释放
b、引用类型:指针,slice,map,chan,interface等都是引用类型
特点:变量存储的是一个地址,这个地址存储最终的值。内存通常在堆上分配
,通过GC回收。
- 严格来说,Go 语言没有引用类型。
- 但是我们可以把 map、chan、函数、接口、slice 切片, 称为引用类型,这样便于理解。
- 指针类型也可以理解为是一种引用类型。
上面我们提到了堆、栈,这里简单介绍下
内存分配中的堆和栈:
栈
(操作系统):由操作系统自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。堆
(操作系统): 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收,分配方式倒是类似于链表。
值类型和指针类型参数示例:
package main
import "fmt"
func main() {
name := "无尘"
modify1(name)
fmt.Println("name的值为:", name)
modify2(&name)
fmt.Println("name的值为:", name)
}
func modify1(name string) { //值类型
name = "wucs"
}
func modify2(name *string) { //指针类型
*name = "wucs"
}
//运行结果:
//name的值为: 无尘
//name的值为: wucs
引用类型
map
以map类型为参数示例:
package main
import "fmt"
func main() {
m:=make(map[string]int)
m["无尘"] = 18
fmt.Println("无尘的年龄为",m["无尘"])
modify(m)
fmt.Println("无尘的年龄为",m["无尘"])
}
func modify(p map[string]int) {
p["无尘"] =20
}
//运行结果:
//无尘的年龄为 18
//无尘的年龄为 20
- 我们看到,函数 modify 的参数类型为 map ,数据仍然修改成功了。
- 其实,在创建 map 的时候,最终调用的是 runtime.makemap 函数,makemap 函数返回的是一个 *hmap 类型,也就是说返回的是一个指针,所以我们创建的 map 其实就是一个 *hmap。
- 因为 map 本质上就是个指针,所以通过 map 类型的参数可以修改原始数据。
// makemap implements Go map creation for make(map[k]v, hint).
func makemap(t *maptype, hint int, h *hmap) *hmap{
//省略无关代码
}
chan
channel 本质上也是个指针,来看源码:
func makechan(t *chantype, size int64) *hchan {
//省略无关代码
}
可以看到创建的 chan 其实是个 *hchan,所以它在参数传递中也和 map 一样。
类型的零值
-
在 Go 语言中,定义变量可以通过
声明
或者通过make
、new函数
,区别是 make 和 new 函数属于显示声明并初始化。 - 如果我们声明的变量没有显示的声明初始化,那么该变量的默认值就是对于类型的零值。
类型 | 零值 |
---|---|
数值类型(int、float等) | 0 |
bool | false |
string | ""(空字符串) |
struct | 内部字段的零值 |
slice | nil |
map | nil |
指针 | nil |
函数 | nil |
chan | nil |
interface | nil |
在 Go 语言中,函数的参数传递只有值传递,而且传递的实参都是原始数据的一份拷贝。如果拷贝的内容是值类型的,那么在函数中就无法修改原始数据;如果拷贝的内容是指针(或者可以理解为引用类型 map、chan 等),那么就可以在函数中修改原始数据。
出处:https://www.cnblogs.com/isungge/p/15146600.html
栏目列表
最新更新
nodejs爬虫
Python正则表达式完全指南
爬取豆瓣Top250图书数据
shp 地图文件批量添加字段
爬虫小试牛刀(爬取学校通知公告)
【python基础】函数-初识函数
【python基础】函数-返回值
HTTP请求:requests模块基础使用必知必会
Python初学者友好丨详解参数传递类型
如何有效管理爬虫流量?
SQL SERVER中递归
2个场景实例讲解GaussDB(DWS)基表统计信息估
常用的 SQL Server 关键字及其含义
动手分析SQL Server中的事务中使用的锁
openGauss内核分析:SQL by pass & 经典执行
一招教你如何高效批量导入与更新数据
天天写SQL,这些神奇的特性你知道吗?
openGauss内核分析:执行计划生成
[IM002]Navicat ODBC驱动器管理器 未发现数据
初入Sql Server 之 存储过程的简单使用
这是目前我见过最好的跨域解决方案!
减少回流与重绘
减少回流与重绘
如何使用KrpanoToolJS在浏览器切图
performance.now() 与 Date.now() 对比
一款纯 JS 实现的轻量化图片编辑器
关于开发 VS Code 插件遇到的 workbench.scm.
前端设计模式——观察者模式
前端设计模式——中介者模式
创建型-原型模式