0基础小白的Golang学习之路--04--函数(上),函数定义和细节

Go中函数定义的方式

        Go中的函数说头可就大了,各种不一样和新的功能,话不多说,直接看一下Go中函数定义的方式        

        上面可以看到,func 表示了函数的关键字,有点类似我们定义类class结构体struct这种,随后是函数名,之后是两个括号。这里我们注意到,Go中的返回值类型是在形参列表后面的,再一个它是用“返回值类型列表” 来描述的。字面意思也就是好像Go可以自定义多个返回值?这我们之后再讨论,先保留疑问。

        我们先简单来个例子写一下函数

package main
import "fmt"
func helloWorld(str string){
	fmt.Println(str)
}
func main(){
	helloWorld("hello wrold!")
}

 这个例子中函数名是helloWorld,单参,无返回值,这就是一个最为简单的函数构成了,当然这还不够,接下来我们通过一些特定的点对函数进行认识和练习。

函数定义的要点

1.命名

遵循标识符命名规范:见名知意 addNum,驼峰命名addNum

①首字母不能是数字

②首字母大写该函数可以被本包文件和其它包文件使用(类似public)

③首字母小写只能被本包文件使用,其它包文件不能使用(类似private)

2.形参/返回值列表

        个数:可以是一个参数,可以是n个参数,可以是0个参数

多参数多返回值举例(其实也很好理解,几个返回值我们就return几个,然后接收几个就行):

package main
import "fmt"
/*
func swap(num1,num2 *int) {}也可以这么写
其他函数形式比如
1.func prac1(a,b int){无返回值}
2.func prac1(a,b int) int{单返回值,括号可写可不写}
3.func prac1(a,b int)(argv1,argv2,argb3......){多返回值}
*/
func moniterPair(val1,val2 int)(int,int){
    first,second := val1,val2
    //对first和second进行encode处理
    return first,second
}
func main(){
    num1:=5
    num2:=10
    first,second := moniterPair(num1,num2)
    fmt.Println(first," ",second)
}

        上面的例子中我们的形参有两个参数,返回值也有两个参数,我们在主函数调用函数接收返回值时也得用两个变量去接收

3.Golang中函数不支持重载

4.Golang中支持可变参数(如果你希望函数带有可变数量的参数)

        我们可以通过 参数名+...  的方式表示参数不定数量 

package main
import "fmt"
func testArgv(args...int){//使用...来表示参数不定
    for idx,val:=range args{
        //遍历参数,打印出参数的下标和值
        fmt.Println(idx,val)
    }
}
func main(){
    testArgv(1,2,3)
    testArgv(4,5)
    testArgv(6)
}

5.基本数据类型和数组默认都是值传递的,即进行值拷贝。在函数内修改,不会影响到原来的值。

        小白在第一次写函数时其实写的就是swap函数,一个是练一下手,一个就是想看看Go中怎么进行的址传递,考虑到Go语言的内存管理应该和C++的差不多,所以尝试了写一个swap函数,果不其然直接传参数的话是没办法交换的。由于目前还没有接触到Go中类似C++引用的方式,所以只能用指针的方式解决。

package main
import "fmt"

func swap(num1 *int,num2 *int){
    temp := *num1
    *num1 = *num2
    *num2 = temp
}
func main(){
    num1:=5
    num2:=10
    swap(&num1,&num2)
    fmt.Println(num1,num2)
}

        以值传递方式的数据类型,如希望在函数内的变量能修改函数外的变量,可以传入变量的地址&,函数内以指针的方式操作变量。从效果来看类似引用传递。

6.在Go中,函数也是一种数据类型,可以赋值给一个变量,则该变量就是一个函数类型的变量了。通过该变量可以对函数调用。

        可能第一次看这句话有点懵,举个例子,4是整数int型,那我们 a := 4此时a也就是int类型,函数类型也是这个意思,

package main
import "fmt"
func test(num int){
    fmt.Println(num)
}
func main(){
    a := test//函数也是一种数据类型,,可以赋值给一个变量
    //则该变量就是一个函数类型的变量了,此时的type:a应该是func(int)
    fmt.Printf("a的类型是:%T,test函数的类型是:%T\n",a,test)//a的类型是:func(int),test函数的类型是:func(int)
    a(111)//输出10,通过该变量可以对函数调用。
}

问题:我们对于其他类型的理解比如int存储具体数据,指针存储地址,那么函数类型存储什么呢?

        在Go语言中函数类型并不存储常规的数据,而是存储“签名”,函数的签名包括函数的参数类型和返回值类型,它描述了函数的参数和返回值的特征。

        当我们定义一个函数类型时,实际上是在创建一个新的类型,该类型与具有相同签名的函数相匹配。函数类型可以用作函数参数、函数返回值或者在变量声明中使用。当我们声明一个函数类型的变量时,该变量可以存储任何具有相同函数签名的函数,但函数的地址并不会存储在函数类型变量中。

7.函数既然是一种数据类型,因此在Go中,函数可以作为形参,并且调用(把函数本身当做一种数据类型)

        其实就是在函数的参数中我们可以传一个函数进去

func testFunc(num int,str string)int{
    fmt.Println(str)
    return num-1
}
func test(num int,testFunc func(int,string)int){//函数类型作为函数形参传入
    fmt.Println(num)
    testFunc(num-1,"func test!!!!")//内部调用函数
}
func main(){
    test(123,testFunc)
}
/*输出结果
123
func test!!!!
*/

在上面的代码中我们定义的test参数有一个 int 和一个 func(int,string)int 函数类型参数,这么一看是不是特别像函数指针?但其实不是,小白刚开始也觉得这个好像就是函数指针么,传一个函数的名字过去。我们在下一条具体的解释一下。

8.为了简化数据类型定义,Go支持自定义数据类型基本语法: type 自定义数据类型名 数据类型可以理解为:相当于起了一个别名

例如:type mylnt int----->这时mylnt就等价int来使用了

例如:type mySum func (int,int) int----->这时mySum就等价一个函数类型func (int,int) int

到这里,函数类型和命名函数类型可能就会让很多小伙伴和函数指针弄混了,但其实他俩有着本质的区别,最简单来看,他俩的数据类型就不一样,一个是函数类型,一个是指针类型。上面小白也有提到函数类型到底是什么,他俩存储的东西都是不同的。

具体来说,以上面的例子:

  1. type mySum func (int, int) int 是一种类型定义,用于声明一个新的函数类型,可以使用 mySum 类型创建函数变量,但不能直接存储函数的内存地址。这种类型定义可用于创建具有相同函数签名的变量、方法或接口。
  2. 函数指针实际上是一个指针变量,可以存储函数的内存地址,并通过该指针来调用相应的函数。

9.支持对函数返回值命名

也就是可以返回时不按序返回了,有点像Python中的字典传参,可以指定哪个参数是什么数据 ,这里也就不过多赘述。

总结

        Go中的函数使用是非常灵活的,不仅引入了函数类型,我们还可以自定义数据类型,我们可以多参数多返回值也可以定义返回值的名字以实现指定返回。但是也正因为着这种灵活多变的形式,我们需要注意的地方就很多,比如我们怎样去理解函数类型,怎样去理解自定义函数类型和函数指针的区别,怎样更加合理的用形参为函数类型以及多返回值的情况。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值