Go 函数 参数值传递
Go 函数 传递 参数值
2023-09-14 09:15:18 时间
函数
函数为什么是一等公民呢?和其他主流语言不同,在go里面函数的地位是不一样的。
与其他主要编程语⾔的差异
- 可以有多个返回值
- 所有参数都是值传递:slice,map,channel 会有传引⽤的错觉(在传递过去的时候,传入到函数当中,在函数里面修改参数的值,外面也可以感受到,难道这不是传引用吗?😳😳😳😳😳😳😳😳😳其实这是一个错觉,就比如slice,切片背后实际上对应的是数组,切片本身是一个数据结构,数据结构里面包含指向数组到指针,即便是在传值的情况下,结构被复制到函数里面了,通过指向数组到指针去操作具体值到时候,其实操作的是同一块空间,所以就会有一种传引用到错觉,实际上是结构被复制了,包含的指针指向到是同一个后端到数组,所以才有这个错觉。)
- 函数可以作为变量的值
- 函数可以作为参数和返回值
传递参数类型 值类型 引用类型
1) 值传递 值类型--》值拷贝
在 Go 语言中参数传递默认均为值传递(形参为实参变量的副本),
对于引用类型数据因其底
层共享数据结构,所以在函数内可对引用类型数据修改从而影响函数外的原变量信息
2) 引用传递。引用类型的时候--》也是值拷贝,只不过底层有个地址,导致使用的地址空间是一样的,所以在函数内部是可以影响函数外面变量的
所以go语言当中都是值拷贝,也就是值传递,不能说在函数里面是引用传递,其次在值传递的时候
为什么引用类型的参数可以影响函数外表的变量?因为值拷贝的时候底层是有地址和指针的。
可以通过将变量的地址通过指针类型递给函数,此时可通过指针对函数外的原变量进行修改。
先来看看变量的作用域
func main() {
name := "jack"
nums := []int{}
fmt.Println(name,nums)
func(){
fmt.Println(name,nums)
name = "lucas"
nums = []int{1,2,3}
fmt.Println(name,nums)
}()
fmt.Println(name,nums)
}
jack []
jack []
lucas [1 2 3]
lucas [1 2 3]
func main() {
name := "jack"
nums := []int{}
fmt.Println(name,nums)
func(){
fmt.Println(name,nums)
name := "lucas"
nums := []int{1,2,3}
fmt.Println(name,nums)
}()
fmt.Println(name,nums)
}
jack []
jack []
lucas [1 2 3]
jack []
值类型的参数和引用类型的参数
func main() {
name := "jack"
nums := []int{1,2,3}
fmt.Println(name,nums)
func(pname string,pnums []int){
fmt.Println(pname,pnums) //jack [1 2 3]
pname = "lucas"
pnums = append(pnums,4,5,6) //大于cap了,所以产生了新切片,和原来的没关系了
fmt.Println(pname,pnums) //lucas [1 2 3 4 5 6]
}(name,nums)
fmt.Println(name,nums) //jack [1 2 3]
}
可以看到在append之后会产生新的切片! 😏😏😏😏
a := []int{1,2,3}
fmt.Printf("%p,%d,%d\n",&a,len(a),cap(a))
b := append(a,4,5,6)
fmt.Printf("%p,%d,%d",&b,len(b),cap(b))
0xc0000a6018,3,3
0xc0000a6030,6,6
上面是pnums = 重新赋值,指向另外一个地方了,所以对原来的切片没有影响,如果是pnums[0] = 100就是对原来的切片进行修改,因为底层有指针,指向的数组是同一个。
func main() {
name := "jack"
nums := []int{1,2,3}
fmt.Println(name,nums)
func(pname string,pnums []int){
fmt.Println(pname,pnums) //jack [1 2 3]
pname = "lucas"
pnums[0] = 100
fmt.Println(pname,pnums) //lucas [100 2 3]
}(name,nums)
fmt.Println(name,nums) //jack [100 2 3]
}
看下图理解最方便:😂😂😂😂😂
相关文章
- Go语言并发之并发实现、多核CPU设置、多协程间的通信、select、多协程间的同步(二十一)
- 化整为零优化重用,Go lang1.18入门精炼教程,由白丁入鸿儒,go lang函数的定义和使用EP07
- .NET 7 AOT 的使用以及 .NET 与 Go 互相调用
- 【一Go到底】第二天---你好,Go and GOROOT&GOPATH
- Go 语言怎么使用变长参数函数?
- go中的map和锁
- Go-函数作为参数传递
- 国产ETL etl-engine 可视化 轻量级 跨平台 支持动态解析GO语言脚本
- Go常见错误集锦之不正确的初始化slice方式会降低性能
- Go错误集锦 | 函数何时使用带参数名的返回值
- 「Go工具箱」将文件大小转换成Kb、Mb、Gb就用这个库:go-humanize
- 「Go工具箱」推荐一个轻量级、语义化的时间处理库:carbon
- Go-包管理-go mod(一)
- Go语言实现Web服务器
- go基础之–函数和map详解编程语言
- go 排序sort的使用详解编程语言
- Go语言圣经-函数递归习题详解编程语言
- 使用Go语言来操作Oracle数据库(go语言oracle)
- Go字符串函数详解编程语言
- go语言之面向对象详解编程语言
- Go语言函数值传递和引用传递
- Linux上构建Go开发环境(linux安装go环境)
- 一步一步学习Go读取Oracle数据库(go读取oracle)
- 学习Oracle Go了解信息技术世界(oracle go的用法)
- Express作者TJ告别Node.js奔向Go