golang 函数一 (定义、参数、返回值)
对于GoLang函数的定义或者说理解: 函数是结构化编程中最小的模块单元,日常开发过程中,将复杂的算法过程分解为若干个小任务(代码块),使程序的结构性更清晰,程序可读性提升,易于后期维护和让别人读懂你的代码。 另外为了更好的重用你的代码,可以把重复性的任务抽象成一个函数。 Go语言中使用关键词func来定义一个函数,并且左花括号不能另起一行,比如: funchello(){//左花括号不能另起一行 println("hello") } Go语言中定义和应用函数时,有如下需要注意的点:
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语言中给函数传参时需要注意以下几点:
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,%vn",&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]) } } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |