2.8 GO 参数传递
简单将GO中参数传递分为三类
数字、字符、字符串等类型
结构体
方法
GO的方法本身就是地址的入口,打印一个方法输出的是这个方法的地址
func test_func(){
//0x488a30
fmt.Printf("func address: %v \n",test_func)
//下面这行报错: cannot take the address of test_func
fmt.Printf("func address: %v \n",&test_func)
}
并且在GO语言中没法再对一个方法取地址&,之所以强调GO的方法,是因为在C语言中可以对方法取地址,但取出来的地址还是方法的入口地址,与方法本身的地址一致,这是语言设计的不同
除了方法,剩下的变量,包括结构体、数据、字符、字符串等变量,注意是变量,都可以取地址,可以作为参数传递给方法,其方式有两种
值传递与地址传递
结构体
结构体与其他基本类型又有所不同,结构体的参数,不管是地址传递还是值传递,在使用上没有区别
type Event struct{
ID int
Title string
Cmd string
Res string
}
func InitEvent(e Event){
e.ID = 1
e.Title = "mysql实例崩溃后,第一次尝试重启"
e.Cmd = "/etc/init.d/mysql restart"
e.Res = "success"
}
func InitEvent2(e *Event){
e.ID = 1
e.Title = "mysql实例崩溃后,第一次尝试重启"
e.Cmd = "/etc/init.d/mysql restart"
e.Res = "success"
}
比如InitEvent方法的参数类型一个是值传递,一个是地址传递,但在使用时,都是对象.属性,用法是一致,这一点与其他的一些语言不同;
GO中对结构体取地址的用法,非常非常地普遍,并且GO建议这么做(因为性能高),若无特殊场景需要,结构的传递基本全是以地址的方式进行的,比如你在看一些GO程序的源码时,凡是看到带*的变量,可以全部认为,这就是一个结构体。
GO语言说自己的值传递是一大特色,这个……这个比如在Java中,复合类型默认就是地址传递,方法中对一个对象属性的修改后,方法外对象属性值永久性变化;
在GO中如果使用值传递的方式,在方法修改结构体这种复合类型,方法外结构体属性不会变化;从这一点讲,GO并不一个完全面向对象的语言,它是面向过程与面向对象的结合。
基本类型
基本类型值传递和地址传递在使用上要有所区别
func test_var(j *int){
var i int = 1
//0xc000012068
fmt.Printf("i address: %v \n",unsafe.Pointer(&i))
//0xc000074010
fmt.Printf("j address: %v \n",j)
//9
fmt.Printf("j address: %v \n",*j)
}
基本类型,地址传递输出的就是16进制的地址,而不是变量值本身,取其值要使用*符号,*j = 1,表示将1写入j变量所在的地址;
这一点,几乎所有的语言处理方法是一致的,需要注意的是GO的字符串
在GO中字符串可以归到甚至类型这一类型中,GO中对字符中处理都是将字符串本身作为参数传递到一个方法中进行的,比如,
fmt.Println(strings.Contains("seafood", "foo")) //true
strInt64 := strconv.FormatInt(id64, 10)
这一点与C语言是一致的,而在面向对象的语言(比如Java),字符串本身就可以包含常用的字符处理方法,比如"123".equals("123")
package main import (
"fmt"
"unsafe"
) //unsafe.Pointer() 函数来查看一个变量的内存地址 func test_var(j *int){
var i int = 1
//0xc000012068
fmt.Printf("i address: %v \n",unsafe.Pointer(&i))
//0xc000074010
fmt.Printf("j address: %v \n",j)
//9
fmt.Printf("j address: %v \n",*j)
} func test_string(s *string){
fmt.Printf("s address: %v \n",*s) //abc
fmt.Printf("s address: %v \n",s) //
fmt.Printf("s address: %v \n",unsafe.Pointer(&s))
} type Event struct{
ID int
Title string
Cmd string
Res string
} func InitEvent(e Event){
e.ID = 1
e.Title = "mysql实例崩溃后,第一次尝试重启"
e.Cmd = "/etc/init.d/mysql restart"
e.Res = "success"
} func InitEvent2(e *Event){
e.ID = 1
e.Title = "mysql实例崩溃后,第一次尝试重启"
e.Cmd = "/etc/init.d/mysql restart"
e.Res = "success"
} func test_struct(){
e1 := Event{ID:0}
InitEvent(e1)
fmt.Printf("e1 address: %v \n",e1) InitEvent2(&e1)
fmt.Printf("e1 address: %v \n",e1)
} func test_func(){
//0x488a30
fmt.Printf("func address: %v \n",test_func)
//下面这行报错: cannot take the address of test_func
//fmt.Printf("func address: %v \n",&test_func)
} func main(){
//var j = 9
//test_var(&j)
ss := "abc"
test_string(&ss)
//test_struct() //test_func()
}
函数作为参数传递
GO方法也可以作为参数传递,但就没有值传递与地址传递这一说法了
package main import (
"fmt"
) //声明了一个函数类型
type testInt func(int) bool func isOdd(integer int) bool {
if integer%2 == 0 {
return false
}
return true
} func isEven(integer int) bool {
if integer%2 == 0 {
return true
}
return false
} //声明的函数在这个地方当做了一个参数
func filter(slice []int, f testInt) []int {
var result []int
for _, value := range slice {
if f(value) {
result = append(result, value)
}
}
return result
}
func main() {
slice := []int{1, 2, 3, 4, 5, 7}
fmt.Println("slice = ", slice)
//将函数当做值来传递
odd := filter(slice, isOdd)
fmt.Println("奇数是:", odd)
//将函数当做值来传递
even := filter(slice, isEven)
fmt.Println("偶数是:", even)
}
数组与切片
数组与切片参数传递相当于地址传递
package main import (
"fmt"
) func t1(){
var aa [3]int
for i:=0;i<3;i++ {
aa[i] = i+10
}
fmt.Println(aa)
ar := t2(aa) //[10 9 12]
t2(ar)
} func t2(ar [3]int) [3]int{
fmt.Println(ar)
ar[1]=9
return ar
} func s1(){
var ss []int
for i:=0;i<3;i++ {
ss = append(ss,i)
}
fmt.Println(ss) var s2 []int = make([]int,3,5)
copy(s2,ss) //len=3 cap=5 slice=[0 1 2]
x := printSlice(s2) //len=3 cap=5 slice=[0 10 2]
printSlice(x)
} func printSlice(x []int) []int{
fmt.Printf("len=%d cap=%d slice=%v\n",len(x),cap(x),x)
x[1] = 10
return x
} func main(){
t1()
//s1()
}
2.8 GO 参数传递的更多相关文章
- js学习之函数的参数传递
我们都知道在 ECMAScript 中,数据类型分为原始类型(又称值类型/基本类型)和引用类型(又称对象类型):这里我将按照这两种类型分别对函数进行传参,看一下到底发生了什么. 参数的理解 首先,我们 ...
- kettle中含有参数传递的定时任务
(1)新建一个作业(新建->作业),并在控制面板右键: (2)设置一个命令参数: (3)把作业的参数传递给转换: (4)在转换中右键设置转换属性: (5)接收作业中设置的传递参数: (6)参数的 ...
- Java基础知识笔记(七:接口、变量作用域和参数传递)
一.接口 Java语言不允许一个子类拥有多个直接父类,即任何子类只能有一个直接父类.但允许一个类实现多个接口,即在定义类的接口名称列表中可以包含1个或多个接口名称,从而实现多重继承的特性.接口的定义格 ...
- shell 脚本之获取命令输出字符串以及函数参数传递
在ubuntu 14.04之后,所有的U盘挂载也分用户之分,最近很多操作也和U盘有关,所以就研究了一上午shell脚本函数以及字符串操作的方法. 字符串操作: 获取他的命令输出比较简单,打个简单的比方 ...
- 【GoLang】golang 闭包 closure 参数传递的蹊跷!
结论: 闭包函数可以直接引用外层代码定义的变量, 但是,注意,闭包函数里面引用的是变量的地址, 当goroutine被调度时,改地址的值才会被传递给goroutine 函数. 介绍 go的闭包是一个很 ...
- JQuery Mobile 页面参数传递
在单页模版中使用基于HTTP的方式通过POST和GET请求传递参数,而在多页模版中不需要与服务器进行通信,通常在多页模版中有以下三种方法来实现页面间的参数传递. 1.GET方式:在前一个页面生成参数并 ...
- Java 中的值传递和参数传递
Java中没有指针,所以也没有引用传递了,仅仅有值传递不过可以通过对象的方式来实现引用传递 类似java没有多继承 但可以用多次implements 接口实现多继承的功能 值传递:方法调用时,实际参数 ...
- 【Python学习】函数参数传递方法四种(位置,关键字,默认值,包裹位置,包裹关键字传递)
1. 位置传递: #--coding:utf-8-- def send(name,address): return 'package is sent to %s, located in %s' %(n ...
- JAVA反射参数传递
引用:http://fish2700.blog.163.com/blog/static/130713192009103035723281/ 使用Method反射调用函数时,我们通常会遇到以下几种情况: ...
- [蟒蛇菜谱]Python函数参数传递最佳实践
将函数作为参数传递,同时将该函数需要的参数一起传递.可参考threading.Timer的处理方式: class threading.Timer(interval, function, args=[] ...
随机推荐
- List<String>转List<Integer>
List<Integer> intList = strList.stream().map(Integer::parseInt).collect(Collectors.toList()); ...
- 亚马逊开发者用户授权 AWS
在开发之前最好的方法是先拿到官网的API文档简单的预览一遍 这里有个中文文档:AWS 开发中文文档 需要准备: 注册成为开发者 创建 AWS 账户 创建 IAM 用户 创建 IAM 策略 创建 IAM ...
- [linux]centos7.4上安装MySQL-8.0.11【完美安装】
版本声明 centos7.4 MySQL-8.0.11 1.我用的阿里云的虚拟主机,刚从windows换到linux,需要装下常用工具 #安装下sz rz常用到上传下载的命令 yum install ...
- FZU ICPC 2020 寒假训练 2
A - 排序 输入一行数字,如果我们把这行数字中的'5'都看成空格,那么就得到一行用空格分割的若 干非负整数(可能有些整数以'0'开头,这些头部的'0'应该被忽略掉,除非这个整数就是由 若干个'0'组 ...
- 菜鸡的Java笔记 数据表与简单java类映射
利用实际的数据表实现表与类的操作转换 简单java类是整个项目开发中的灵魂所在,它有自己严格的开发标准,而最为重要的是它需要于数据表是完全对应的 不过考虑到现在没有接触到过 ...
- [atARC128F]Game against Robot
为了方便,下文中的$n$是原来的$\frac{n}{2}$ 当确定排列$\{p_{i}\}$后,将$a_{i}$按照$p_{i}$从大到小排序,那么机器人即会不断选第一个元素 考虑玩家最后选择的$n$ ...
- javascript-初级-day07
day01-运算符 <!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type&quo ...
- 如何查看dpdk版本
服务器上曾经装过很多版本的dpdk,此时如果编译某个程序出现奇怪错误的时候不由得会怀疑是不是dpdk版本的问题= = 令人吃惊的是,网上搜了一圈居然没有一个简单直接的方法能够直接使用,于是自己实验了一 ...
- ICCV2021 | 渐进采样式Vision Transformer
前言 ViT通过简单地将图像分割成固定长度的tokens,并使用transformer来学习这些tokens之间的关系.tokens化可能会破坏对象结构,将网格分配给背景等不感兴趣的区域,并引 ...
- 洛谷 P6071 『MdOI R1』Treequery(LCA+线段树+主席树)
题目链接 题意:给出一棵树,有边权,\(m\) 次询问,每次给出三个数 \(p,l,r\),求边集 \(\bigcap\limits_{i=l}^rE(p,i)\) 中所有边的权值和. 其中 \(E( ...