目录
函数是基本的代码块,用于执行一个任务。
Go程序中最少有个main()函数。
可以通过函数来划分不同功能,逻辑上每个函数执行的是指定的任务。
函数声明告诉了编译器函数的名称,返回类型,和参数。
Go中的标准库提供了多种可动用的内置的函数。例如,len()函数可以接受不同类型参数并返回该类型的长度。如果传入的是字符串则返回字符串的长度,如果传入的是数组,则返回数组中包含的元素个数。
1、基础函数
语法:func 函数名 (参数列表) (返回值列表) |
无参数无返回值 |
func test(){
}
有参数有返回值 |
func result(a int,b int)(int,int){
return a+b,a*b
}
传参有多个返回值 |
func result(a int,b int)(int,int){
return a+b,a*b
}
示例一
package main
import "fmt"
func main() {
var (
test1 = 10
test2 = 20
result int
)
result = max(test1, test2)
fmt.Println("最大值", result)
}
//func main() {
//result := max(10, 20)
//fmt.Println("最大值", result)
//}
func max(num1 int, num2 int) int {
if num1 > num2 {
return num1
} else {
return num2
}
}
##
最大值 20
示例二
package main
import "fmt"
func main() {
he, ji := oyyy(10, 20)
fmt.Println(he, ji)
}
func oyyy(num1 int, num2 int) (int, int) {
result1 := num1 + num2
result2 := num1 * num2
return result1, result2
}
##
30 200
示例三
package main
import "fmt"
func main() {
fmt.Println(test(1, 2))
}
func test(a, b int) int {
return a + b
}
##
3
2、函数参数
函数如果使用参数,该变量可称为函数的形参。形参就像定义在函数体内的局部变量。
调用函数,可以通过两种方式来传递参数
传递类型 | 描述 |
---|---|
值传递 | 值传递是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数 |
引用传递 | 引用传递是指在调用函数时将实际参数的地址传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数 |
默认情况下,Go 语言使用的是值传递,即在调用过程中不会影响到实际参数。
注意1:无论是值传递,还是引用传递,传递给函数的都是变量的副本,不过,值传递是值的拷贝。引用传递是地址的拷贝,一般来说,地址拷贝更为高效。而值拷贝取决于拷贝的对象大小,对象越大,则性能越低。 |
注意2:map、slice、chan、指针、interface默认以引用的方式传递。 |
值传递
值传递不影响结果
package main
import "fmt"
func main() {
var (
num1 = 10
num2 = 20
)
//交换前
fmt.Println(num1, num2)
//交换后
//值不变 因为参数值的变化不影响
swap(num1, num2)
fmt.Println(num1, num2)
}
func swap(a, b int) {
a, b = b, a
}
##
10 20
10 20
引用传递
package main
import "fmt"
func main() {
var (
num1 = 10
num2 = 20
)
//交换前
fmt.Println(num1, num2)
//交换后
//值不变 因为参数值的变化不影响
swap(&num1, &num2)
fmt.Println(num1, num2)
}
func swap(a, b *int) {
*a, *b = *b, *a
}
##
10 20
20 10
函数的可变参数
一个函数里只能有一个可变参数,可变参数的类型必须与其他参数的类型一致
args是一个切片
package main
import "fmt"
func test(a, b int, args ...int) int {
result := a + b
for _, v := range args {
result = result + v
}
return result
}
func main() {
sum := test(1, 2, 3, 4)
fmt.Println(sum)
}
##
10
3、函数作为实参
package main
import (
"fmt"
"math"
)
func main() {
//函数变量
result := func(x float64) float64 {
return math.Sqrt(x)
}
fmt.Println(result(9))
fmt.Println("-10的绝对值:", math.Abs(-10))
fmt.Println("5.2向下取整:", math.Ceil(5.2))
fmt.Println("5.8向下取整:", math.Floor(5.8))
fmt.Println("11除3的余数:", math.Mod(11, 3))
fmt.Println("取整数,取小数")
fmt.Println(math.Modf(5.26))
fmt.Println("3的2次方", math.Pow(3, 2))
fmt.Println("10的4次方", math.Pow10(4))
fmt.Println("8的开平方", math.Sqrt(8))
fmt.Println("8的开立方", math.Cbrt(8))
fmt.Println("圆周率", math.Pi)
}
##
3
-10的绝对值: 10
5.2向下取整: 6
5.8向下取整: 5
11除3的余数: 2
取整数,取小数
5 0.2599999999999998
3的2次方 9
10的4次方 10000
8的开平方 2.8284271247461903
8的开立方 2
圆周率 3.141592653589793
4、回调函数
回调函数:作为一个参数传递 |
package main
import "fmt"
//声明形式函数
type cback func(int) int
func main() {
//对回调函数进行了隐匿,起到安全保护作用之余,提高程序运行效率
test_back(1, call_back)
test_back(2, func(b int) int {
fmt.Println("匿名回调函数:", b)
return b
})
}
//测试函数,用来调用回调函数
func test_back(x int, f cback) {
fmt.Println("test_back函数:语句1")
f(x)
fmt.Println("test_back函数:语句2")
}
//回调函数
func call_back(a int) int {
fmt.Println("回调函数cal_back:", a)
return a
}
##
test_back函数:语句1
回调函数cal_back: 1
test_back函数:语句2
test_back函数:语句1
匿名回调函数: 2
test_back函数:语句2
5、函数闭包
闭包是一个结构。 闭包=函数+外层变量的引用 |
闭包:作为一个值传递 |
匿名函数,可作为闭包。匿名函数是一个"内联"语句或表达式。匿名函数的优越性在于可以直接使用函数内的变量,不必申明。
package main
import "fmt"
func main() {
nextnumber := close_package()
fmt.Println("使用nextnumber做自增")
fmt.Println(nextnumber())
fmt.Println(nextnumber())
fmt.Println(nextnumber())
nextnumber1 := close_package()
fmt.Println("使用nextnumber1做自增")
fmt.Println(nextnumber1())
fmt.Println(nextnumber1())
}
func close_package() func() int {
i := 0
return func() int {
i++
return i
}
}
##
使用nextnumber做自增
1
2
3
使用nextnumber1做自增
1
2
6、函数方法
同时有函数和方法。一个方法就是一个包含了接受者的函数,接受者可以是命名类型或者结构体类型的一个值或者是一个指针。所有给定类型的方法属于该类型的方法集。
示例----求圆面积
法一
package main
import (
"fmt"
"math"
)
//定义结构体
type Circle struct {
R float64
}
func main() {
var c Circle
c.R = 2
fmt.Println("圆的面积=", c.getArea())
}
//该method属于Circle类型对象中的方法
func (c Circle) getArea() float64 {
return math.Pi * c.R * c.R
}
##
圆的面积= 12.566370614359172
法二
package main
import (
"dev_code/day9/example2/circle"
"fmt"
)
func main() {
c := new(circle.Circle)
fmt.Println("请输入圆的半径")
fmt.Scan(&c.R)
c.Mianji()
}
-----------------------------------------------------------------------------------------
package circle
import (
"fmt"
"math"
)
type Circle struct {
R float64 //半径
S float64 //面积
}
func (c Circle) Mianji() {
c.S = math.Pi * c.R * c.R
fmt.Printf("圆的面积为%f", c.S)
}
##
请输入圆的半径
2
圆的面积为12.566371