简单将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. 理解ASP.NET Core - 日志(Logging)

    注:本文隶属于<理解ASP.NET Core>系列文章,请查看置顶博客或点击此处查看全文目录 快速上手 添加日志提供程序 在文章主机(Host)中,讲到Host.CreateDefault ...

  2. Linux Kdump 机制详解

    文章目录 1. 简介 1.1 安装 1.2 触发 kdump 1.3 调试 kdump 1.3.1 安装 debuginfo vmlinux 1.3.2 编译 kernel 1.4 kdump-too ...

  3. Spring Boot程序中@JsonIgnoreProperties与@JsonIgnore基本使用

    问题由来: springboot项目中定义了很多类,我们在rest返回中直接返回或者在返回对象中使用这些类,spring已经使用jackson自动帮我们完成这些的to json.但是有时候自动转的js ...

  4. Import “google/api/annotations.proto“ was not found or had errors.问题;proto 中外部引入proto文件问题解决方案

    问题 在proto 中引入了一些其他 proto 文件的情况下会出现was not found or had errors.问题 在使用Kratos框架时proto文件引入import "g ...

  5. 手把手教你基于Netty实现一个基础的RPC框架(通俗易懂)

    阅读这篇文章之前,建议先阅读和这篇文章关联的内容. [1]详细剖析分布式微服务架构下网络通信的底层实现原理(图解) [2][年薪60W的技巧]工作了5年,你真的理解Netty以及为什么要用吗?(深度干 ...

  6. Windows11 如何让开始菜单出现休眠选项(Windows11如何开启休眠功能?)Windows家庭版

    1. Windows11新版的菜单找不到调休眠的选项了,所以我们可以用win+r键调出运行,输入control,回车调出「控制面板」 配图: 2. 我的电脑系统是家庭版的Windows11,其它版本这 ...

  7. win10开机自启

    所有用户的开机自启文件夹 英文路径 # ProgramData目录是隐藏的 C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp 中 ...

  8. Node.js实现前后端交换——用户登陆

    最近学习了一点Node.js的后端知识,于是作为一个学习前端方向的我开始了解后端,话不多说,开始介绍.首先,如果你想要更好的理解这篇博客,你需要具备html,css,javascript和Node.j ...

  9. [hdu4388]Stone Game II

    不管是否使用技能,发现操作前后所有堆二进制中1的个数之和不变.那么对于一个堆其实可以等价转换为一个k个石子的堆(k为该数二进制的个数),然后就是个nim游戏. 1 #include<bits/s ...

  10. [bzoj2241]打地鼠

    先考虑如何判定一个r*c的矩阵是否符合条件,容易发现左上角的点无法被别的矩阵砸到,要求左上角r*c的矩阵中不能超过最左上角的元素,之后同理不断枚举最上&最左的非0点,可以用差分来优化,复杂度为 ...