Go语言的函数,很像JavaScript语言的函数
复制 func 函数名称 ( 形参1 , 形参2 ) ( 返回值类型列表 ) {
函数体
retrun 返回值列表
}
函数的声明
函数的命名
重载:不支持
复制 // 以下代码会报错
// 编译器会认为下面的两个方法定义是重复的
func test () {}
func test (a string ) {}
无参函数
有参函数:参数类型一致
复制 func test (x, y float32 ) {}
有参函数:类型不一致
复制 func test (x string , y int ) {}
有参函数:可变参数
复制 func test ( names ...int ) {
// 可变参数在方法内会被转换为切片,可以对切片进行遍历取值
}
无返回值函数
如果是无返回函数,返回值类型不填
复制 func test () {
}
// 调用函数
test()
单返回值函数
如果只有一个返回值,可以省略括号
复制 func test () string {
return "hello"
}
// 调用函数
var s = test()
多返回值函数
函数可以有多个返回值,多个返回值返回使用逗号隔开
复制 func test () ( string , int ) {
return "hello" , 20
}
// 调用函数
var s, i = test()
带有变量名的返回值
复制 func namedRetValues () (a, b int ) {
a = 1
b = 2
return
}
// 直接返回a 和 b
函数的调用
调用多返回值函数
忽略多返回值函数返回值
复制 // 调用函数,忽略部分返回值
var s, _ = test()
函数参数的值传递与引用传递
基本类型形参是值传递
复制 // 交换两个数字
func exchangeNum (num1 int , num2 int ) {
var t int
t = num1
num1 = num2
num2 = t
}
func main () {
var i = 10
var j = 20
exchangeNum(i, j)
fmt.Printf( "i = %d , j = %d " , i, j) // 结果为 i = 10, j = 20
}
使用指针可以做到引用传递:
复制 // 交换两个数字
// 参数类型为指针
func exchangeNum (num1Ptr *int , num2Ptr *int ) {
var t int
t = * num1Ptr
* num1Ptr = * num2Ptr
* num2Ptr = t
}
func main () {
var i = 10
var j = 20
exchangeNum( & i, & j)
fmt.Printf( "i = %d , j = %d " , i, j) // 结果为 i = 20, j = 10
}
引用类型形参是引用传递
等数据类型。
匿名函数
定义并直接调用匿名函数
复制 func (data int ) {
fmt.Println( "hello" , data)
}( 100 )
变量函数
复制 // 将匿名函数体保存到f()中
f := func (data int ) {
fmt.Println( "hello" , data)
}
// 使用f()调用
f( 100 )
变量函数传递
复制 package main
import (
"fmt"
)
// 遍历切片的每个元素, 通过给定函数进行元素访问
func visit (list [] int , f func ( int )) {
for _, v := range list {
f(v)
}
}
func main () {
// 使用匿名函数打印切片内容
visit([] int { 1 , 2 , 3 , 4 }, func (v int ) {
fmt.Println(v)
})
}
匿名函数应用技巧
复制 func main () {
var skill = map [ string ] func (){
"fire" : func () {
fmt.Println( "chicken fire" )
},
"run" : func () {
fmt.Println( "soldier run" )
},
"fly" : func () {
fmt.Println( "angel fly" )
},
}
skill[ "fire" ]()
}
闭包(Closure)
闭包就是能够读取其他函数内部变量的函数,在其他语言中,也称为Lambda表达式。在Golang中,闭包组成如下:
下面是一个闭包累加器:
复制 package main
import "fmt"
// 定义一个名为getSum的函数,无参,返回值是一个func (int) int 的函数
func getSum () func ( int ) int {
var sum = 0
return func (num int ) int { // 这个拥有sum变量的匿名函数就是闭包
sum = sum + num // sum变量的作用域被扩大,将会被一直保存在内存中,所以要适当使用闭包
fmt.Println(sum)
return sum
}
}
func main () {
sumF := getSum()
sumF( 1 ) // 1. 入门
sumF( 2 ) // 3
sumF( 3 ) // 6
}
结果:
defer 延迟执行语句
类似于Java的Finally语句,通常用于标记关闭资源的语句,让其使用完毕后自动关闭:
复制 package main
import (
"fmt"
)
func main () {
testDefer()
}
func printReturn () int {
fmt.Println( "defer return" )
return 0
}
func testDefer () int {
fmt.Println( "defer begin" )
var num1 int = 30
var num2 int = 60
// 将defer放入延迟调用栈,这是一个新的栈空间
// 涉及的变量如果是基本类型,则会进行值传递,如果是引用类型则是传递引用
// 因为num1和num2是基本类型,所以打印30和60
defer fmt.Println(num1) // 先放入的是栈底,最后调用
defer fmt.Println(num2) // 后放入的是栈顶,最先调用
num1 += 10
num2 += 10
fmt.Println( "num1 和 num2:" , num1, num2)
return printReturn() // defer 在return语句之后运行
}
执行结果如下:
复制 $ go run main.go
defer begin
num1 和 num2: 40 70
defer return
60
30