简单将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 参数传递的更多相关文章

  1. js学习之函数的参数传递

    我们都知道在 ECMAScript 中,数据类型分为原始类型(又称值类型/基本类型)和引用类型(又称对象类型):这里我将按照这两种类型分别对函数进行传参,看一下到底发生了什么. 参数的理解 首先,我们 ...

  2. kettle中含有参数传递的定时任务

    (1)新建一个作业(新建->作业),并在控制面板右键: (2)设置一个命令参数: (3)把作业的参数传递给转换: (4)在转换中右键设置转换属性: (5)接收作业中设置的传递参数: (6)参数的 ...

  3. Java基础知识笔记(七:接口、变量作用域和参数传递)

    一.接口 Java语言不允许一个子类拥有多个直接父类,即任何子类只能有一个直接父类.但允许一个类实现多个接口,即在定义类的接口名称列表中可以包含1个或多个接口名称,从而实现多重继承的特性.接口的定义格 ...

  4. shell 脚本之获取命令输出字符串以及函数参数传递

    在ubuntu 14.04之后,所有的U盘挂载也分用户之分,最近很多操作也和U盘有关,所以就研究了一上午shell脚本函数以及字符串操作的方法. 字符串操作: 获取他的命令输出比较简单,打个简单的比方 ...

  5. 【GoLang】golang 闭包 closure 参数传递的蹊跷!

    结论: 闭包函数可以直接引用外层代码定义的变量, 但是,注意,闭包函数里面引用的是变量的地址, 当goroutine被调度时,改地址的值才会被传递给goroutine 函数. 介绍 go的闭包是一个很 ...

  6. JQuery Mobile 页面参数传递

    在单页模版中使用基于HTTP的方式通过POST和GET请求传递参数,而在多页模版中不需要与服务器进行通信,通常在多页模版中有以下三种方法来实现页面间的参数传递. 1.GET方式:在前一个页面生成参数并 ...

  7. Java 中的值传递和参数传递

    Java中没有指针,所以也没有引用传递了,仅仅有值传递不过可以通过对象的方式来实现引用传递 类似java没有多继承 但可以用多次implements 接口实现多继承的功能 值传递:方法调用时,实际参数 ...

  8. 【Python学习】函数参数传递方法四种(位置,关键字,默认值,包裹位置,包裹关键字传递)

    1. 位置传递: #--coding:utf-8-- def send(name,address): return 'package is sent to %s, located in %s' %(n ...

  9. JAVA反射参数传递

    引用:http://fish2700.blog.163.com/blog/static/130713192009103035723281/ 使用Method反射调用函数时,我们通常会遇到以下几种情况: ...

  10. [蟒蛇菜谱]Python函数参数传递最佳实践

    将函数作为参数传递,同时将该函数需要的参数一起传递.可参考threading.Timer的处理方式: class threading.Timer(interval, function, args=[] ...

随机推荐

  1. 力扣 - 剑指 Offer 30. 包含min函数的栈

    题目 剑指 Offer 30. 包含min函数的栈 思路1 使用一个辅助栈min_stack,用来维护栈的最小的元素 每次添加元素入栈时候,data_stack和min_stack都要同时维护 dat ...

  2. Java JDBC 理论笔记

    一.JDBC常用接口.类介绍 JDBC提供对独立于数据库统一的API,用以执行SQL命令.API常用的类.接口如下: DriverManager 管理JDBC驱动的服务类,主要通过它获取Connect ...

  3. [atARC125F]Tree Degree Subset Sum

    令$a_{i}$为$i$的度数-1,那么$(x,s)$合法即等价于存在$S\subseteq [1,n],|S|=x$且$\sum_{k\in S}a_{k}=s$ 引理:$(x,s)$合法的必要条件 ...

  4. [uoj173]鏖战表达式

    2018年论文题,上接loj2506,主要是论文中的第4章,也可快速跳至原题解 5.平衡树的嵌套问题 平衡树嵌套 所谓平衡树嵌套,就是若干棵平衡树,其中若干棵平衡树的根会指向另一颗平衡树上的一个节点 ...

  5. [atAGC050A]AtCoder Jumper

    考虑二叉树的结构,但并不容易构造从叶子返回的边 (以下为了方便,将所有点编号为$[0,n)$) 对于$i$,选择$2i\ mod\ n$和$(2i+1)\ mod\ n$这两条出边 从二叉树的角度并不 ...

  6. [luogu5665]划分

    暴力dp,用f[i][j]表示前i个数,最后一个区间是(j,i]的最小答案,转移方程用可以用前缀和来优化,复杂度为$o(n^3)$(然后可以各种优化到$o(n^2)$,但这不需要)输出f[i][j], ...

  7. CF1368E Ski Accidents

    读懂题是第一要素. 考虑把点集分割为:\(A,B,C\) 首先把所有入度为\(0\)的点加入\(A\) 然后对所有入边只来自\(A\)的点加入\(B\) 然后对所有入边只来自\(B\)的点加入\(C\ ...

  8. [ARC 122]

    最近状态差到爆炸. \(AT\)连掉两把分,啥时候能上黄啊. \(A\) 考虑直接动归. 把\(O(n^2)\)的动归后缀和优化成\(O(n)\) A #include<iostream> ...

  9. MYSQL5.8-----5

  10. Linux服务器I/O性能分析-2

    一.如何正确分析IO性能 1.1 BLKTRACE分析IO性能 之前的文章已经说明,要是系统发生I/O性能问题,我们常用的命令是无法精确定位问题(内核I/O调度器消耗的时间和硬件消耗的时间,这个不能作 ...