自学内容网 自学内容网

golang学习笔记12-函数(一):定义与使用

注:本人已有C,C++,Python基础,只写本人认为的重点。

一、基本语法

go的函数和C/C++的也很像,语法如下:
func 函数名(形参列表)返回值类型列表{
//执行语句
return 返回值列表
}
其中形参列表为:变量名1 变量类型1,变量名2 变量类型2,…,变量名n 变量类型n,返回列表为变量类型1,变量类型2,…,变量类型n,实例如下:

func cal(num1 int, num2 int) int {
var sum int = 0
sum += num1
sum += num2
return sum
}

显然,形参列表和C/C++的区别无非是变量类型写在后面,这里return的机制也一样。但形参列表还可以是可变参数列表,语法为:
func 函数名(变量名…变量类型)返回值类型列表{
//执行语句
return 返回值列表
}
可变参数接收任意数量参数,在函数内部会被视为切片,用len函数即可获取其长度,示例如下:

package main

import "fmt"

//定义一个函数,函数的参数为:可变参数 ...  参数的数量可变
//args...int 可以传入任意多个数量的int类型的数据  传入0个,1个,,,,n个
func test(args ...int) {
//函数内部处理可变参数的时候,将可变参数当做切片来处理
//遍历可变参数:
for i := 0; i < len(args); i++ {
fmt.Println(args[i])
}
}
func main() {
test()
fmt.Println("--------------------")
test(3)
fmt.Println("--------------------")
test(37, 58, 39, 59, 47)
}

不难发现,上述例子中无返回值,所以无需return,也就无需写返回列表。但return还有个额外机制:当返回列表存在且声明了函数内的变量名时,有以下两种情况:
1.只写return,那么返回变量的顺序由返回列表的变量名决定
2.return后跟变量名,那么return的优先级会高于返回列表,返回顺序由return后的变量名决定
示例如下:

package main

import "fmt"

func cal(num1 int, num2 int) (sub int, sum int) {
sum = num1 + num2
sub = num1 - num2
return //无返回值,按返回列表的名字顺序返回
}
func cal2(num1 int, num2 int) (sub int, sum int) {
sum = num1 + num2
sub = num1 - num2
return sum, sub //return优先级高于返回列表
}
func main() {
sub, sum := cal2(1, 2) //按返回列表,sub=-1,sum=3
//但结果不是这样
fmt.Println("sum=", sum, "sub=", sub)
}

二、函数的传递

我在第七节(golang学习笔记7)中讲过,函数是值类型的数据类型,但有引用特性,所以当函数赋给一个变量时,传递的是引用而不是函数代码本身,示例如下:

package main

import "fmt"

//定义一个函数:
func test(num int) {
fmt.Println(num)
}

//定义一个函数,把另一个函数作为形参:
func test02(num1 int, num2 float32, testFunc func(int)) {
fmt.Println("-----test02")
}
func main() {
//函数也是一种数据类型,可以赋值给一个变量
a := test //变量就是一个函数类型的变量
fmt.Printf("a的类型是:%T,test函数的类型是:%T \n", a, test)
//a的类型是:func(int),test函数的类型是:func(int)
//通过该变量可以对函数调用
a(10) //等价于  test(10)
//调用test02函数:
test02(10, 3.19, test)
test02(10, 3.19, a)
}

不难发现,test和C/C++中的函数指针很像,但C/C++中的函数不是数据类型,其传递要通过指针来操控,而go把函数单独作为一个数据类型,脱离了指针的控制。
如果你觉得testFunc func(int)可以再简化,go提供了type关键字,类似C/C++的typedef,但也有明显区别:typedef定义的类型可完全替代原类型,而type定义的类型赋值时,go编译器还是认为和原类型不是一个类型。示例如下:

package main

import "fmt"

//定义一个函数:
func test(num int) {
fmt.Println(num)
}

type myFunc func(int)

//定义一个函数,把另一个函数作为形参:
func test02(num1 int, num2 float32, testFunc myFunc) {
fmt.Println("-----test02")
fmt.Printf("num1=%d,num2=%.2f\n", num1, num2)
}
func main() {
a := test
type myInt int
num1 := 1
var num3 myInt
num1 = int(num3) //go编译器仍然认为myInt不是int,所以需要强转
num2 := 1.1
test02(num1, float32(num2), a)
}


原文地址:https://blog.csdn.net/weixin_54259326/article/details/142478565

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!