目录函数定义参数返回值匿名函数函数可变数量参数传参闭包递归延迟调用defer异常处理单元测试压力测试函数定义golang函数特点:无需声明原型。支持不定变参。支持多返回值。支持命名返回参数。支持匿名函数和闭包。函数也是一种类型,一
golang函数特点:
无需声明原型。
支持不定 变参。
支持多返回值。
支持命名返回参数。
支持匿名函数和闭包。
函数也是一种类型,一个函数可以赋值给变量。
不支持 嵌套 (nested) 一个包不能有两个名字一样的函数。
不支持 重载 (overload)
不支持 默认参数 (default parameter)。
package main
import "fmt"
func test(fn func() int) int {
return fn()
}
// 定义函数类型。
type FormatFunc func(s string, x, y int) string
func format(fn FormatFunc, s string, x, y int) string {
return fn(s, x, y)
}
func main() {
s1 := test(func() int { return 100 }) // 直接将匿名函数当参数。
s2 := format(func(s string, x, y int) string {
return fmt.Sprintf(s, x, y)
}, "%d, %d", 10, 20)
println(s1, s2)
}
函数定义时指出,函数定义时有参数,该变量可称为函数的形参。形参就像定义在函数体内的局部变量。
但当调用函数,传递过来的变量就是函数的实参,函数可以通过两种方式来传递参数:
引用传递:是指在调用函数时将实际参数的地址传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。
package main
import (
"fmt"
)
/* 定义相互交换值的函数 */
func swap(x, y *int) {
var temp int
temp = *x /* 保存 x 的值 */
*x = *y /* 将 y 值赋给 x */
*y = temp /* 将 temp 值赋给 y*/
} func main() { var a, b int = 1, 2 / 调用 swap() 函数 &a 指向 a 指针,a 变量的地址 &b 指向 b 指针,b 变量的地址 / swap(&a, &b) fmt.Println(a, b) }
### 任意类型的不定参数:
```go
package main
import (
"fmt"
)
func test(s string, n ...int) string {
var x int
for _, i := range n {
x += i
}
return fmt.Sprintf(s, x)
}
func main() {
s := []int{1, 2, 3}
res := test("sum: %d", s...) // slice... 展开slice
println(res)
}
没有参数的 return 语句返回各个返回变量的当前值。这种用法被称作“裸”返回。
package main
import (
"fmt"
)
func add(a, b int) (c int) {
c = a + b
return
}
func calc(a, b int) (sum int, avg int) {
sum = a + b
avg = (a + b) / 2
return
}
func test() (int, int) {
return 1, 2
}
func sum(n ...int) int {
var x int
for _, i := range n {
x += i
}
return x
}
func addp(x, y int) (z int) {
defer func() {
println(z) // 输出: 203 defer 延迟调用通过闭包读取和修改
}()
z = x + y
return z + 200 // 执行顺序: (z = z + 200) -> (call defer) -> (return)
}
func main() {
var a, b int = 1, 2
c := add(a, b)
sum, avg := calc(a, b)
fmt.Println(a, b, c, sum, avg)
x, _ := test()
println(x)
println(add(1, 2)) // 命名返回参数可看做与形参类似的局部变量,最后由 return 隐式返回。
println(sum(test())) // 多返回值可直接作为其他函数调用实参。
println(add(1, 2)) // 显式 return 返回前,会先修改命名返回参数。
}
匿名函数由一个不带函数名的函数声明和函数体组成。匿名函数的优越性在于可以直接使用函数内的变量,不必申明。
package main
func main() {
// 匿名函数申明
getSqrt := func(a float64) float64 {
return math.Sqrt(a)
}
fmt.Println(getSqrt(4))
// --- function variable ---
fn := func() { println("Hello, World!") }
fn()
// --- function collection ---
fns := [](func(x int) int){
func(x int) int { return x + 1 },
func(x int) int { return x + 2 },
}
println(fns[0](100))
// --- function as field ---
d := struct {
fn func() string
}{
fn: func() string { return "Hello, World!" },
}
println(d.fn())
// --- channel of function ---
fc := make(chan func() string, 2)
fc <- func() string { return "Hello, World!" }
println((<-fc)())
}
package main
import "fmt"
// 外部引用函数参数局部变量
func add(base int) func(int) int {
return func(i int) int {
base += i
return base
}
}
// 返回2个函数类型的返回值
func test01(base int) (func(int) int, func(int) int) {
// 定义2个函数,并返回
// 相加
add := func(i int) int {
base += i
return base
}
// 相减
sub := func(i int) int {
base -= i
return base
}
// 返回
return add, sub
}
func main() {
tmp1 := add(10)
fmt.Println(tmp1(1), tmp1(2))
// 此时tmp1和tmp2不是一个实体了
tmp2 := add(100)
fmt.Println(tmp2(1), tmp2(2))
f1, f2 := test01(10)
// base一直是没有消
fmt.Println(f1(1), f2(2))
// 此时base是9
fmt.Println(f1(3), f2(4))
}
// 数字阶乘
package main
import "fmt"
func factorial(i int) int {
if i <= 1 {
return 1
}
return i * factorial(i-1)
}
func main() {
var i int = 7
fmt.Printf("Factorial of %d is %d\n", i, factorial(i))
}
// 斐波那契数列(Fibonacci)
package main
import "fmt"
func fibonaci(i int) int {
if i == 0 {
return 0
}
if i == 1 {
return 1
}
return fibonaci(i-1) + fibonaci(i-2)
}
func main() {
var i int
for i = 0; i < 10; i++ {
fmt.Printf("%d\n", fibonaci(i))
}
}
go语言 def...
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!