Go入门(三)之自定义函数、匿名函数、闭包、defer、作用域

上一篇文章> Go入门(二)之基础类型、fmt格式化、运算符、流程控制

一、自定义函数


在这里插入图片描述

1、无参无返回值

package main

import "fmt"

// 无参无返回值的函数定义
func MyFunc() {
	a := 123
	fmt.Println("a = ", a)
}

func main() {
	//函数调用
	MyFunc()
}

结果:

a =  123

2、普通参数列表

(1)有参无返回值
package main

import "fmt"

// 有参无返回值的函数定义
func MyFunc(a int) {
	fmt.Println("a = ", a)
}

func main() {
	//函数调用
	MyFunc(123)
}

结果:

a =  123
(2)不定参数列表

<1> 不定参数类型

package main

import "fmt"

func MyFunc(a int, args ...int) {
	fmt.Println("a = ", a)
	fmt.Println("长度等于", len(args))
	fmt.Println("------------------------")
	for i := 0; i < len(args); i++ {
		fmt.Printf("args[%d] = %d\n", i, args[i])
	}
	fmt.Println("------------------------")
	for i, data := range args {
		fmt.Printf("args[%d] = %d\n", i, data)
	}
}

func main() {
	//函数调用
	MyFunc(1, 2, 3)
}

结果:

a =  1
长度等于 2
------------------------
args[0] = 2
args[1] = 3
------------------------
args[0] = 2
args[1] = 3

<2> 不定参数传递

package main

import "fmt"

func MyFunc(tmp ...int) {
	for _, data := range tmp {
		fmt.Println("data = ", data)
	}
}

func test(args ...int) {
	// 全部元素传递给MyFunc
	// MyFunc(args...)

	//只想把后2个参数传递给另外一个函数使用
	MyFunc(args[2:]...)
}
func main() {
	test(1, 2, 3, 4)
}

结果:

data =  3
data =  4

3、无参有返回值

(1)一个返回值
package main

import "fmt"

// 无参数有一个返回值
func myfunc01() int {
	return 123
}

// 给返回值起一个变量名,go推荐写法
func myfunc02() (result int) {
	return 1234
}

// 常用写法
func myfunc03() (result int) {
	result = 666
	return
}

func main() {
	fmt.Println("myfunc01 = ", myfunc01())
	fmt.Println("myfunc02 = ", myfunc02())
	fmt.Println("myfunc03 = ", myfunc03())
}

结果:

myfunc01 =  123
myfunc02 =  1234
myfunc03 =  666
(2)多个返回值
package main

import "fmt"

func myfunc01() (int, int, int) {
	return 1, 2, 3
}

// go官网推荐写法
func myfunc02() (a int, b int, c int) {
	a, b, c = 1, 2, 3
	return
}

// 常用写法
func myfunc03() (a, b, c int) {
	a, b, c = 1, 2, 3
	return
}

func main() {
	a, b, c := myfunc03()
	fmt.Printf("a = %d, b = %d, c = %d\n", a, b, c)
	// myfunc01()
}

结果:

a = 1, b = 2, c = 3

4、有参有返回值

package main

import "fmt"

func MyFunc01(a, b int) (max, min int) {
	if a > b {
		max = a
		min = b
	} else {
		max = b
		min = a
	}
	return
}

func main() {
	max, min := MyFunc01(10, 20)
	fmt.Printf("max = %d, min = %d\n", max, min)
}

结果:

max = 20, min = 10

二、递归函数


package main

import "fmt"

// 实现1+2+3+100
// 方式一
func test01() (sum int) {
	for i := 0; i <= 100; i++ {
		sum += i
	}
	return
}

// 方式二
func test02(i int) int {
	if i == 1 {
		return 1
	}
	return i + test02(i-1)
}

// 方式三
func test03(i int) int {
	if i == 100 {
		return 100
	}
	return i + test02(i+1)
}

func main() {
	// sum := test01()
	// sum := test02(100)
	sum := test03(100)
	fmt.Println("sum = ", sum)
}

结果:

sum =  100

三、函数类型


1、类型

package main

import "fmt"

func Add(a, b int) int {
	return a + b
}

func minus(a, b int) int {
	return a - b
}

// 函数也是一种类型, 通过type给一个函数类型起名
// FuncType它是一个函数类型
type FuncType func(int, int) int // 没有函数名字,没有{}

func main() {
	res := Add(1, 2)
	fmt.Println("res = ", res)

	// 声明一个函数类型的变量,变量名为fTest
	var fTest FuncType
	fTest = Add //是变量就可以赋值
	res = fTest(10, 20)
	fmt.Println("res1 = ", res)

	fTest = minus
	res = fTest(10, 2)
	fmt.Println("res2 = ", res)
}

结果:

res =  3
res1 =  30
res2 =  8

2、回调函数

package main

import "fmt"

type FuncType func(int, int) int

// 实现加法
func Add(a, b int) int {
	return a + b
}

func minus(a, b int) int {
	return a - b
}

// 回调函数,函数有一个参数是函数类型
// 多态,多种形态
func Calc(a, b int, fTest FuncType) (result int) {
	fmt.Println("Calc")
	result = fTest(a, b)
	return
}

func main() {
	a := Calc(1, 1, Add)
	fmt.Println("a = ", a)

	b := Calc(2, 1, minus)
	fmt.Println("b = ", b)
}

结果:

Calc
a =  2
Calc
b =  1

四、匿名函数与闭包


1、匿名函数

package main

import "fmt"

func main() {
	a := 10
	// 匿名函数
	f1 := func() {
		fmt.Println("a = ", a)
	}
	f1()

	// 给函数起别名
	type FuncType func()
	// 声明变量
	var f2 FuncType
	f2 = f1
	f2()

	// 定义匿名函数,同时调用
	func() {
		fmt.Printf("a = %d\n", a)
	}() //调用此匿名函数

	// 带参数的匿名函数
	f3 := func(i, j int) {
		fmt.Printf("i = %d, j = %d\n", i, j)
	}
	f3(1, 2)

	// 定义匿名函数,同时调用
	func(i, j int) {
		fmt.Printf("i = %d, j = %d\n", i, j)
	}(10, 20)

	// 匿名函数,有参有返回值
	x, y := func(i, j int) (max, min int) {
		if i > j {
			max = i
			min = j
		} else {
			max = j
			min = i
		}
		return
	}(10, 20)
	fmt.Printf("max = %d, min = %d\n", x, y)
}

结果:

a =  10
a =  10
a = 10
i = 1, j = 2
i = 10, j = 20
max = 20, min = 10

2、闭包

它不关心这些捕获了得变量和常量是否已经超出了作用域
所以只有闭包还在使用它,这些变量就会一直存在

package main

import "fmt"

func test01() int {
	var x int
	x++
	return x * x //函数调用完毕就释放
}

// 闭包:函数返回值为一个匿名函数
func test02() func() int {
	var x int

	return func() int {
		x++
		return x * x
	}
}

func main() {
	fmt.Println(test01())
	fmt.Println(test01())
	fmt.Println(test01())
	fmt.Println("-----------------")
	f := test02()
	fmt.Println(f())
	fmt.Println(f())
	fmt.Println(f())
}

结果:

1
1
1
-----------------
1
4
9

五、延迟调用defer


1、defer使用

package main

import "fmt"

func main() {
	// defer延迟调用,main函数结束前调用
	defer fmt.Println("2222")
	fmt.Println("1111")
}

结果:

1111
2222

2、多个defer的执行顺序

后进先出的顺序执行

package main

import "fmt"

func test(x int) {
	fmt.Println(100 / x)
}

func main() {
	defer fmt.Println("aaaa")
	defer fmt.Println("bbbb")
	defer test(0)
	defer fmt.Println("ccc")
}

结果:

ccc
bbbb
aaaa
panic: runtime error: integer divide by zero

goroutine 1 [running]:
main.test(0x0)
        E:/MyWork/Go Projects/src/wielun666@163.com/02/17_多个defer的执行顺序.go:6 +0xbb
main.main()
        E:/MyWork/Go Projects/src/wielun666@163.com/02/17_多个defer的执行顺序.go:14 +0x193
exit status 2

3、defer和匿名函数结合使用

提前把参数传递进去了,只是没有进行调用

package main

import "fmt"

// func main() {
// 	a := 10

// 	defer func() {
// 		fmt.Println("a = ", a)
// 	}()

// 	a = 20
// 	fmt.Println("a = ", a)
// }

func main() {
	a := 10
	defer func(a int) {
		fmt.Println("aaa = ", a)
	}(a)
	a = 20
	fmt.Println("a = ", a)
}

结果:

a =  20
aaa =  10

六、获取命令行参数


package main

import (
	"fmt"
	"os"
)

func main() {
	list := os.Args
	n := len(list)
	fmt.Println("n = ", n)

	for i := 0; i < n; i++ {
		fmt.Printf("list[%d] = %s\n", i, list[i])
	}
	fmt.Printf("-------------\n")
	for i, data := range list {
		fmt.Printf("range list[%d] = %s\n", i, data)
	}
}

结果:

> go build .\19_获取命令行参数.go
> .\19_获取命令行参数.exe helo wielun
n =  3
list[0] = E:\MyWork\Go Projects\src\wielun666@163.com\02\19_获取命令行参数.exe
list[1] = hello
list[2] = wielun
-------------
range list[0] = E:\MyWork\Go Projects\src\wielun666@163.com\02\19_获取命令行参数.exe
range list[1] = hello
range list[2] = wielun

七、不用作用域同名变量


package main

import "fmt"

var a byte //全局变量

func main() {
	var a int //局部变量

	fmt.Printf("1: %T\n", a) //int
	{
		var a float32
		fmt.Printf("2: %T\n", a) //float32
	}
	test()
}

func test() {
	fmt.Printf("3: %T\n", a) //uint8,就是byte
}

结果:

1: int
2: float32
3: uint8

下一篇文章> Go入门(四)之工程管理、复合类型

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wielun

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值