golang 函数一 (定义、参数、返回值)

前端之家收集整理的这篇文章主要介绍了golang 函数一 (定义、参数、返回值)前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

对于GoLang函数的定义或者说理解:

函数是结构化编程中最小的模块单元,日常开发过程中,将复杂的算法过程分解为若干个小任务(代码块),使程序的结构性更清晰,程序可读性提升,易于后期维护和让别人读懂你的代码

另外为了更好的重用你的代码,可以把重复性的任务抽象成一个函数

Go语言中使用关键词func来定义一个函数,并且左花括号不能另起一行,比如:

funchello(){//左花括号不能另起一行
println("hello")
}

Go语言中定义和应用函数时,有如下需要注意的点:

函数无须前置声明

不支持命名嵌套定义,支持匿名嵌套

函数只能判断是否为nil,不支持其它比较操作

支持多返回值

支持命名返回值

支持返回局部变量指针

支持匿名函数和闭包

funchello()
{//左括号不能另起一行
}

funcadd(x,yint)(sumint){//命名返回值
sum=x+y
return
}

funcvals()(int,int){//支持多返回值
return2,3
}

funca(){}
funcb(){}

funcadd(x,yint)(*int){//支持返回局部变量指针
sum:=x+y
return&sum
}
funcmain(){
println(a==b)//只能判断是否为nil,不支持其它比较操作
funchello(){//不支持命名嵌套定义
println("hello")
}
}

具备相同签名(参数和返回值)的函数才视为同一类型函数,比如:

funchello(){
fmt.Println("hello")
}

funcsay(ffunc()){
f()
}

funcmain(){
f:=hello
say(f)
}

参数:

Go语言中给函数传参时需要注意以下几点:

不支持默认参数

不支持命名实参

参数视作为函数的局部变量

必须按签名顺序传递指定类型和数量的实参

相邻的同类型参数可以合并

支持不定长变参,实质上是slice

functest(x,yint,sstring,_bool){//相邻的同类型参数可以合并
return
}

funcadd(x,yint)int{//参数视作为函数的局部变量
x:=100//nonewvariablesonleftsideof:=
varyint=200//yredeclaredinthisblock
returnx+y
}

funcsum(nums...int){//变参函数
total:=0
for_,num:=rangenums{
total+=num
}
fmt.Println(total)
}

funcmain(){
//test(1,2,"s")//notenoughargumentsincalltotest
test(1,"s",false)
nums:=[]int{1,3}
sum(nums...)
}

不管传递的是指针、引用还是其它类型参数,都是值拷贝传递的,区别在于拷贝的目标是目标对象还是拷贝指针而已。

函数调用之前,编译器会为形参和返回值分配内存空间,并将实参拷贝到形参内存。比如:

functest1(x*int){
fmt.Printf("%p,%v\n",&x,x)
}

funcmain(){
a:=0x100
p:=&a
fmt.Printf("%p,&p,p)
test1(p)
}
输出:
0xc42002c020,0xc42000a320
0xc42002c030,0xc42000a320
从结构中看出,实参和形参指向同一目标,但是传递的指针是被赋值了的

如果函数参数和返回值过多,可以将其封装成一个结构体类型,比如:

typeserverOptionstruct{
addrstring
portint
pathstring
timeouttime.Duration
}

funcnewOption()*serverOption{
return&serverOption{
addr:"127.0.0.1",port:8080,path:"/var/www",timeout:time.Second*5,}
}
func(s*serverOption)server(){
println("runserver")
}

funcmain(){
s:=newOption()
s.port=80
s.server()
for{}
}

变参:

变参本质上是一个切片(slice),只能接收一到多个同类型参数,且必须放在参数列表尾部,比如:

funcadd(args...int)int{
total:=0
for_,v:=rangeargs{
total+=v
}
returntotal
}
funcmain(){
fmt.Println(add(1,3))
}

变参既然是切片,那是否可以直接传个切片或数组呢?

functest1(sstring,a...int){
fmt.Printf("%T,a,a)//[]int,[1234]
}
{
a:=[4]int{1,3,4}
test1("s",a)//cannotusea(type[4]int)astypeintinargumenttotest1
test1("s",a[:]//cannotusea[:](type[]int)astypeintinargumenttotest1
test1("s",a[:]...)//切片展开
}

变参既然是切片,那么参数复制的是切片的本身,并不包括底层的数组,因此可以修改原数据,但是可以copy底层数据,防止原数据被修改,比如:

functest1(a...int){
fori:=rangea{
a[i]+=100
}
}
funcmain(){
a:=[4]int{1,4}
//b:=make([]int,0)
//copy(b,a[:])
//test1(b[:]...)
test1(a[:]...)
fori:=rangea{
fmt.Println(a[i])
}
}

猜你在找的Go相关文章