一、go 函数的使用细节
-
1、函数的形参列表可以有多个,返回的值列表也可以有多个
-
2、形参列表和返回值列表的数据类型可以是值类型和引用类型
-
3、函数的命名遵循标识符命名规范,首字母不能不是数字。如果首字母大写,则函数对外可见;如果首字母小写,则函数对外不可见
-
4、函数中的变量是局部的,在函数外部无法访问;函数外部的变量在函数内部可以访问,但如果在函数内部对其进行赋值,则会创建一个新的局部变量,遮蔽掉外部变量
-
5、函数可以作为参数传递给另一个函数,也可以作为另一个函数的返回值返回
-
6、函数可以使用 defer 关键字来延迟执行,直到函数返回之前执行 defer 后的语句
-
7、基本数据类型和数组默认是值传递,在函数内部对其进行修改不会影响到函数外部的变量
-
8、切片、映射、通道、接口和函数默认是引用传递,在函数内部对其进行修改会影响到函数外部的变量
-
10、如果希望函数内部的值类型变量能修改函数外部的变量,可以将其地址传递给函数,使用指针类型来接收参数
-
11、函数不支持函数重载,但可以通过可变参数和接口类型来实现类似的功能
-
12、函数可以使用匿名函数和闭包来实现一些特殊的功能,如回调函数、工厂函数等
-
13、函数也是一种特殊的数据类型,可以赋值给变量,可以通过该变量实现对函数的调用
-
14、函数可作为参数传递、作为返回值返回,也可以有方法和属性
-
16、支持对函数的返回值命名,命名的返回值在函数体内作为变量使用,函数结束时自动返回这些变量的当前值
-
17、函数可以是匿名的,也可以是有名字的,匿名函数通常用于一次性使用或者作为参数传递给其他函数,有名字的函数可以被重复调用
-
18、使用 _ 标识符来忽略函数的某个返回值,表示该返回值不需要使用
-
19、函数的入参支持可变参数,使用 ...语法来表示可变参数,函数内部将其视为一个切片。可变参数只能有一个,并且必须是参数列表的最后一个参数
-
20、为了简化数据类型定义,go支持自定义数据类型和类型别名,可以使用 type 关键字来定义新的类型或给已有类型起别名
-
基本语法:type 自定义数据类型名 数据类型
-
例如:type MyInt int // 定义一个新的数据类型 MyInt,底层类型为 int。注意 int 和MyInt 是两种不同的类型,不能直接赋值或比较,需要进行类型转换。
-
二、代码示例
package main
import "fmt"
type MyInt int
func main() {
// 定义一个 MyInt 类型的变量 a,并赋值为 10
var a MyInt = 10
fmt.Println(a) // 输出:10
// int 和 MyInt 是两种不同的类型,不能直接赋值或比较,需要进行类型转换
var b int = 20
// b = a // 这会编译错误
b = int(a) // 正确的类型转换方式
fmt.Println(b) // 输出:10
// 函数的形参列表可以有多个,返回的值列表也可以有多个
x, y := swap(1, 2)
fmt.Println(x, y) // 输出:2 1
// 函数的变量是局部的,在函数外部无法访问;函数外部的变量在函数内部可以访问,但如果在函数内部对其进行赋值,则会创建一个新的局部变量,遮蔽掉外部变量
var c int = 5
fmt.Println(c) // 输出:5
modify(c)
fmt.Println(c) // 输出:5,c 的值没有被修改
// 如果希望值类型变量能修改函数外部的变量,可以将其地址传递给函数,使用指针类型来接收参数
var d int = 5
fmt.Println(d) // 输出:5
modifyPointer(&d)
fmt.Println(d) // 输出:10,d 的值被修改
// 函数可以作为参数传递给另一个函数,也可以作为另一个函数的返回值返回
result := apply(3, 4, add)
fmt.Println(result) // 输出:7
// 函数可以是匿名的,也可以是有名字的,匿名函数通常用于一次性使用或者作为参数传递给其他函数,有名字的函数可以被重复调用
apply(5, 6, func(x, y int) int {
return x * y // 这是一个匿名函数,作为参数传递给 apply 函数,计算两个数的乘积
})
// 函数也可以使用 defer 关键字来延迟执行,直到函数返回之前执行 defer 后的语句
defer fmt.Println("This will be printed at the end of main function")
// 函数如果有不确定的参数数量,可以使用可变参数来接收,这些参数在函数内部会被视为一个切片
fmt.Println(add(1,2,3))
fmt.Println(add(1,2,3,4))
// 函数不支持函数重载,但可以通过可变参数和接口类型来实现类似的功能
fmt.Println(sum(1, 2)) // 输出:3
fmt.Println(sum(1, 2, 3, 4)) // 输出:10
}
// 函数的形参列表可以有多个,返回的值列表也可以有多个
func swap(x, y int) (int, int) {
return y, x
}
// 函数的变量是局部的,在函数外部无法访问;函数外部的变量在函数内部可以访问,但如果在函数内部对其进行赋值,则会创建一个新的局部变量,遮蔽掉外部变量
func modify(c int) {
c = 10 // 这里修改了 c 的值,但这是一个新的局部变量,不会影响 main 函数中的 c
}
// 如果希望值类型变量能修改函数外部的变量,可以将其地址传递给函数,使用指针类型来接收参数
func modifyPointer(d *int) {
*d = 10 // 这里通过指针修改了 d 的值,这会影响 main 函数中的 d,因为传递的是 d 的地址
}
// 函数可以作为参数传递给另一个函数,也可以作为另一个函数的返回值返回
func apply(x, y int, op func(int, int) int) int {
return op(x, y) // 这里调用了作为参数传入的函数 op,并返回其结果
}
func add(x, y int) int {
return x + y // 这是一个简单的加法函数,符合 func(int, int) int 的类型签名,可以作为参数传递给 apply 函数
}
// 函数如果有不确定的参数数量,可以使用可变参数来接收,这些参数在函数内部会被视为一个切片
func add(a int, args ...int) int {
res := a
for index, value:= range ...args {
fmt.Println("index:", index, "value:", value, "value", args[index])
res+= value
}
return res
}
// 函数不支持函数重载,但可以通过可变参数和接口类型来实现类似的功能
func sum(nums ...int) int {
total := 0
for _, n := range nums {
total += n
}
return total // 这是一个求和函数,接受可变数量的整数参数,并返回它们的和
}