【4.0】Go语言基础之函数
【一】函数基础
【1】语法
func关键字 函数名(形参1 形参1的类型,形参2 形参2的类型) (返回值类型) {
函数体(函数体的内容和缩进无关,只要是在大括号内,都是函数体内容)
}
- 在Python中需要先定义函数再使用
- 在Go中不需要先定义再使用
func main() {
}
【2】无参数无返回值
package main
import "fmt"
func main() {
// (2)在main函数中调用 index 函数
index() // 这是index函数
}
// (1)简单的函数定义 :无参数 , 无返回值
// 定义函数后在main函数中调用
func index() {
fmt.Println("这是index函数")
}
【3】有参数无返回值
- 有参数无返回值,且参数类型不同
package main
import "fmt"
func main() {
// (2)在main函数中调用 index 函数 需要传递两个参数,并且 参数要符合规定
// 只有位置传参,没有所谓的关键字传参
index("Dream", 18) // Dream 18
}
// (1)有参数无返回值的函数
// 定义函数后在main函数中调用
func index(name string, age int) {
fmt.Println(name, age)
}
- 有参数无返回值,且参数类型相同
package main
import "fmt"
func main() {
// (2)在main函数中调用 index 函数 需要传递两个参数,并且 参数要符合规定
// 只有位置传参,没有所谓的关键字传参
index(19, 18) //
}
// (1)有参数无返回值的函数
// 定义函数后在main函数中调用
// name 和 age 都是相同类型 可简写
func index(name, age int) {
fmt.Println(name, age)
}
- 有参数无返回值,且参数类型不同
package main
import "fmt"
func main() {
// (2)在main函数中调用 index 函数 需要传递两个参数,并且 参数要符合规定
// 只有位置传参,没有所谓的关键字传参
index(19, 18, "dream","hope")
}
// (1)有参数无返回值的函数
// 定义函数后在main函数中调用 name 和 age 都是数字类型 , gender 和 class 都是字符串类型
func index(name, age int,gender,class string) {
fmt.Println(name, age,gender,class)
}
【4】2个参数和1个返回值
package main
import "fmt"
func main() {
// (2)在main函数中调用 index 函数 需要传递两个参数,并且 参数要符合规定
// 只有位置传参,没有所谓的关键字传参
// 调用返回值需要先定义接收返回值的变量名
res := index("Dream", 18)
fmt.Println(res)
// Dream 18
// 18
}
// (1)两个参数和一个返回值
// 定义函数后在main函数中调用
func index(name string, age int) int {
fmt.Println(name, age)
// 返回值需要定义返回值类型,否则会报错
// return age // Too many arguments to return
return age // Too many arguments to return
}
【5】2个参数和2个返回值
package main
import "fmt"
func main() {
// (2)在main函数中调用 index 函数 需要传递两个参数,并且 参数要符合规定
// 只有位置传参,没有所谓的关键字传参
// 调用返回值需要先定义接收返回值的变量名
res, result := index("Dream", 18)
fmt.Println(res, result)
// Dream 18
// Dream 18
}
// (1)两个参数和两个返回值 --- 多个返回值需要加 ()
// 定义函数后在main函数中调用
func index(name string, age int) (string, int) {
fmt.Println(name, age)
// 返回值需要定义返回值类型,否则会报错
// return age // Too many arguments to return
return name, age // Too many arguments to return
}
【6】_
代替不需要接收的返回值
package main
import "fmt"
func main() {
// (3)在main函数中调用 index 函数 需要传递两个参数,并且 参数要符合规定
// 只有位置传参,没有所谓的关键字传参
// 调用返回值需要先定义接收返回值的变量名 , 可以用 _ 代替不要的返回值
//a, b, c := index(6, 18)
//fmt.Println(a, b, c) // 6 18 108
_, _, c := index(6, 18)
fmt.Println(c) // 108
}
// (1)两个参数和两个返回值 --- 多个返回值需要加 ()
// 定义函数后在main函数中调用
func index(a, b int) (int, int, int) {
// 返回值需要定义返回值类型,否则会报错
return a, b, a * b
}
【7】命名返回值
package main
import "fmt"
func main() {
// (4)在main函数中调用 index 函数 需要传递两个参数,并且 参数要符合规定
// 只有位置传参,没有所谓的关键字传参
// 调用返回值需要先定义接收返回值的变量名 , 可以用 _ 代替不要的返回值
// 命名返回值的使用
add, mul := index(6, 18)
fmt.Println(add, mul) // 24 108
}
// (1)两个参数和两个返回值 --- 多个返回值需要加 ()
// 定义函数后在main函数中调用
func index(a, b int) (add int, mul int) {
// [1] add / mul : 相当于定义了两个返回值的变量名,在函数内部不用定义就可以直接使用
// 命名返回值
// 返回值需要定义返回值类型,否则会报错
//return a + b, a * b
add = a + b
mul = a * b
// [2] return 可以直接省略掉 return add , mul
return
}
【二】函数高级
【1】不定长参数
package main
import "fmt"
// 补充 : 同一个包下,不能出现同名的变量和变量名 (py以py文件为最小单位,go以包为最小单位)
func main() {
// 调用函数 : [1 2 3 4] 容器类型
// Python 有可变长位置参数 和 可变长关键字参数 , 但是 go 只有 可变长位置参数
foo(1, 2, 3, 4) // [1 2 3 4]
}
// 不定长参数
// 可以接收任意长度的数字类型的参数 : ...interface
func foo(a ...int) {
fmt.Println(a)
}
【2】匿名函数
(1)基本的匿名函数
package main
import (
"fmt"
)
// 补充 : 同一个包下,不能出现同名的变量和变量名 (py以py文件为最小单位,go以包为最小单位)
func main() {
// 调用函数 : [1 2 3 4] 容器类型
// Python 有可变长位置参数 和 可变长关键字参数 , 但是 go 只有 可变长位置参数
foo()
// 这是 foo 函数内部
//这是 foo 函数内部的匿名函数
}
// 匿名函数 --- 没有名字的函数 (需要定义在函数内部)
func foo(a ...int) {
fmt.Println("这是 foo 函数内部")
// 匿名函数 : 定义在函数内部的函数 , 必须是匿名函数
func() {
fmt.Println("这是 foo 函数内部的匿名函数")
}() // 匿名函数要加 () 调用执行
}
(2)有参数的匿名函数
package main
import (
"fmt"
)
// 补充 : 同一个包下,不能出现同名的变量和变量名 (py以py文件为最小单位,go以包为最小单位)
func main() {
// 调用函数 : [1 2 3 4] 容器类型
// Python 有可变长位置参数 和 可变长关键字参数 , 但是 go 只有 可变长位置参数
foo()
// 这是 foo 函数内部
//这是 foo 函数内部的匿名函数
}
// 匿名函数 --- 没有名字的函数 (需要定义在函数内部)
func foo(a ...int) {
fmt.Println("这是 foo 函数内部")
// 匿名函数 : 定义在函数内部的函数 , 必须是匿名函数
// 有参数的匿名函数
// 位置参数 a,b 均为 int 类型
func(a, b int) {
fmt.Println("这是 foo 函数内部的匿名函数")
}(4, 5) // 匿名函数要加 () 调用执行,未知参数必须传入参数才不会报错
}
(3)有参数并且有返回值的匿名函数
package main
import (
"fmt"
)
// 补充 : 同一个包下,不能出现同名的变量和变量名 (py以py文件为最小单位,go以包为最小单位)
func main() {
// 调用函数 : [1 2 3 4] 容器类型
// Python 有可变长位置参数 和 可变长关键字参数 , 但是 go 只有 可变长位置参数
foo()
// 这是 foo 函数内部
//这是 foo 函数内部的匿名函数
}
// 匿名函数 --- 没有名字的函数 (需要定义在函数内部)
func foo(a ...int) {
fmt.Println("这是 foo 函数内部")
// 匿名函数 : 定义在函数内部的函数 , 必须是匿名函数
// 有参数的匿名函数
// 位置参数 a,b 均为 int 类型
// 有参数,有返回值的匿名函数
res := func(a, b int) int {
fmt.Println("这是 foo 函数内部的匿名函数")
return a * b
}(4, 5) // 匿名函数要加 () 调用执行,未知参数必须传入参数才不会报错
fmt.Println("这是 匿名函数的返回值 :>>>> ", res)
}
【3】函数是一等公民
package main
import "fmt"
// 补充 : 同一个包下,不能出现同名的变量和变量名 (py以py文件为最小单位,go以包为最小单位)
func main() {
// 调用函数
foo()
}
// 匿名函数也是一种类型 ---> 函数是一等公民 ---> 头等函数
func foo() {
// 一门语言,只要函数是一等公民的意思是可以把函数当成变量来使用,传递
// 函数是一等公民 ---> 可以把函数赋值给一个变量
var f = func() {
fmt.Println("我是 foo 函数内部的匿名函数")
}
// 调用函数
f() // 我是 foo 函数内部的匿名函数
// 查看函数的类型
fmt.Printf("匿名函数的类型是 :>>>> %T", f) // 匿名函数的类型是 :>>>> func()
// 既然函数是变量,就可以当参数传递,也可以当返回值返回
}
package main
import "fmt"
// 补充 : 同一个包下,不能出现同名的变量和变量名 (py以py文件为最小单位,go以包为最小单位)
func main() {
// 调用函数
foo()
}
// 匿名函数也是一种类型 ---> 函数是一等公民 ---> 头等函数
func foo() {
// 一门语言,只要函数是一等公民的意思是可以把函数当成变量来使用,传递
// 函数是一等公民 ---> 可以把函数赋值给一个变量 -- 完整定义
var f func() = func() {
fmt.Println("我是 foo 函数内部的匿名函数")
}
// 调用函数
f() // 我是 foo 函数内部的匿名函数
// 查看函数的类型
fmt.Printf("匿名函数的类型是 :>>>> %T", f) // 匿名函数的类型是 :>>>> func()
// 既然函数是变量,就可以当参数传递,也可以当返回值返回
}
【4】闭包函数
(1)引入
package main
import "fmt"
// 补充 : 同一个包下,不能出现同名的变量和变量名 (py以py文件为最小单位,go以包为最小单位)
func main() {
// 调用函数
foo()
}
// 闭包函数 : 必须符合两个 条件
// 1 :定义在函数内部
// 2 :对外部作用域有引用
func foo() func() {
f := func() { // 这样写只满足了第一个条件 :定义在函数内部 , 所以不是闭包函数
fmt.Println("我是 foo 函数内部的匿名函数")
}
return f
}
(2)闭包函数
- Go 有闭包函数,但是没有装饰器的语法糖
package main
import "fmt"
// 补充 : 同一个包下,不能出现同名的变量和变量名 (py以py文件为最小单位,go以包为最小单位)
func main() {
// 调用函数
f := foo()
f()
// 这是foo函数的结果调用 Dream
// 我是 foo 函数内部的匿名函数
// 这是foo函数 内部的匿名函数的结果调用 Dream
}
// 闭包函数 : 必须符合两个 条件
// 1 :定义在函数内部
// 2 :对外部作用域有引用
func foo() func() {
name := "Dream"
f := func() { // 【1】定义在函数内部,
fmt.Println("我是 foo 函数内部的匿名函数")
// 【2】并对外部作用域有引用
fmt.Println("这是foo函数 内部的匿名函数的结果调用 ", name)
}
fmt.Println("这是foo函数的结果调用 ", name)
return f
}
【5】函数的参数和返回值都是类型的一部分
(1)函数的参数是类型的一部分
package main
import "fmt"
// 补充 : 同一个包下,不能出现同名的变量和变量名 (py以py文件为最小单位,go以包为最小单位)
func main() {
// 调用函数
f := foo()
f(4, 5) // 我是 foo 函数内部的匿名函数 20
}
// 函数是一种类型,函数的参数和返回值都是类型的一部分
func foo() func(a, b int) {
return func(a, b int) {
fmt.Println("我是 foo 函数内部的匿名函数 ", a*b)
}
}
(2)函数的返回值是类型的一部分
package main
import "fmt"
// 补充 : 同一个包下,不能出现同名的变量和变量名 (py以py文件为最小单位,go以包为最小单位)
func main() {
// 调用函数
f := foo()
f()
}
// 函数是一种类型,函数的参数和返回值都是类型的一部分
// func(a, b int) int 外层定义函数的参数类型及返回值类型
func foo() func(a, b int) int {
// func(a, b int) int 内层定义 函数的参数类型及 内部函数的返回值类型
return func(a, b int) int {
fmt.Println("我是 foo 函数内部的匿名函数 ", a*b)
return a * b
}
}
(3)函数也可以作为参数
package main
import "fmt"
// 补充 : 同一个包下,不能出现同名的变量和变量名 (py以py文件为最小单位,go以包为最小单位)
func main() {
// 调用函数
f := foo()
f()
}
// 函数是一种类型,函数的参数和返回值都是类型的一部分
// func(a int, b func()) int 外层定义函数的参数类型(a 为int,b 为一个函数)及返回值类型(返回了一个数字所以是 int)
func foo() func(a int, b func()) int {
// func(a, b int) int 内层定义 函数的参数类型 (a 为int,b 为一个函数)及 内部函数的返回值类型(返回了一个数字所以是 int)
return func(a int, b func()) int {
fmt.Println("我是 foo 函数内部的匿名函数 ")
return a
}
}
【6】给类型重命名
package main
import "fmt"
// 补充 : 同一个包下,不能出现同名的变量和变量名 (py以py文件为最小单位,go以包为最小单位)
func main() {
// 调用函数
f := foo()
f(4, 5) // 我是 foo 函数内部的匿名函数 20
}
// 给类型重命名
type Myfunc func(a int, b func()) int
// 函数是一种类型,函数的参数和返回值都是类型的一部分
// func(a int, b func()) int 外层定义函数的参数类型(a 为int,b 为一个函数)及返回值类型(返回了一个数字所以是 int)
func foo() Myfunc {
// func(a, b int) int 内层定义 函数的参数类型 (a 为int,b 为一个函数)及 内部函数的返回值类型(返回了一个数字所以是 int)
return func(a int, b func()) int {
fmt.Println("我是 foo 函数内部的匿名函数 ")
return a
}
}
本文来自博客园,作者:Chimengmeng,转载请注明原文链接:https://www.cnblogs.com/dream-ze/p/17825655.html