1、函数
1.1、不支持重载,暂无泛型
普通函数
package main
import "fmt"
func main() {
println("----------------")
prt("你好")
println("!!!!!!!!!!!!!!!!")
}
func prt(s string) {
fmt.Printf("hello:%s",s)
}
func prt(s string,n int16) {
fmt.Printf("hello:%s\n",s)
fmt.Printf("n = %d",n)
}
1.2、可以有多个返回值
可以命名返回,也可非命名返回
package main
import "fmt"
var num int = 10
var numx2, numx3 int
func main() {
println("----------------")
numx2 , numx3 = getX2AndX3(num)
PrintValues()
numx2 , numx3 = getX2AndX3f(num)
PrintValues()
}
func PrintValues() {
fmt.Printf("num = %d,2x num = %d,3x num = %d\n", num, numx2, numx3)
}
func getX2AndX3(input int) (int, int) {
return 2 * input, 3 * input
}
func getX2AndX3f(input int) (x2 int, x3 int) {
x2 = 2 * input
x3 = 3 * input
return
}
1.2.1、使用空白符
能丢弃不需要的值
package main
import "fmt"
func main() {
var i int
var f float32
i, _, f = PrintValues()
fmt.Printf("int : %d ,float: %f \n", i, f)
}
func PrintValues() (int, int, float32) {
return 2, 4, 5.31
}
1.2.2、改变外部变量
package main
import "fmt"
func main() {
n := 0
reply := &n
Multiply(10, 5, reply)
fmt.Println("multiply:", *reply)
}
func Multiply(a, b int, reply *int) {
*reply = a * b
}
1.3、可变长参数
package main
import (
"fmt"
)
func main() {
x := min(1, 3, 2, 7)
fmt.Printf("minmum is : %d\n", x)
arr := []int{7, 9, 3, 5}
x = min(arr...)
fmt.Printf("minmum is : %d\n", x)
}
func min(a ...int) int {
if len(a) == 0 {
return 0
}
min := a[0]
for _, v := range a {
if v < min {
min = v
}
}
return min
}
1.4、defer和追踪
允许推迟执行所描述的语句,直到函数完成前
1.4.1、若是有多个defer,执行顺序类似出栈
package main
import "fmt"
func main() {
function()
}
func function() {
fmt.Printf("In function at the top\n")
defer function1()
defer function2()
defer function3()
fmt.Printf("In function at the bottom!\n")
}
func function1() {
fmt.Printf("function1 !")
}
func function2() {
fmt.Printf("function2 !")
}
func function3() {
fmt.Printf("function3 !")
}
1.4.2、语句中有变量时,至此值是定死了,虽然执行可能在变量重新赋值之后,但是变量值是不会再变的
package main
import "fmt"
func main() {
var a int = 2
function(a)
}
func function(a int) {
fmt.Printf("In function at the top,a=%d\n", a)
defer function1(a)
fmt.Printf("In function at the bottom,a=%d\n", a)
a = 4
fmt.Println(a)
}
func function1(a int) {
fmt.Printf("function1 a = %d!", a)
}
// 结果:
// In function at the top,a=2
// In function at the bottom,a=2
// 4
// function1 a = 2!
1.4.3、常见应用场景
关闭文件流
open a file
defer file.Close()
解锁
mu.Lock()
defer mu.Unlock()
打印最终报告
printHeader()
defer printFooter()
关闭数据库连接
defer disconnectFromDB()
使用defer实现追踪
此函数非常明显的展示了defer的调用时机
package main
import "fmt"
func main() {
b()
}
func b() {
trace("b")
defer untrace("b")
fmt.Println("in b")
a()
}
func a() {
trace("a")
defer untrace("a")
fmt.Println("in a")
}
func trace(s string) {
fmt.Println("entering:", s)
}
func untrace(s string) {
fmt.Println("leaving:", s)
}
使用defer记录函数的参数与返回值
package main
import (
"io"
"log"
)
func func1(s string) (n int, err error) {
defer func() {
log.Printf("func1(%q) = %d, %v", s, n, err)
}()
return 7, io.EOF
}
func main() {
func1("Go")
}
1.5、内置函数
go有一类不需要进行导入就能够直接使用的内置函数。
内置函数表:
名称 | 说明 |
close | 用于管道通信 |
len、cap | len 用于返回某个类型的长度或数量(字符串、数组、切片、map 和管道);cap 是容量的意思,用于返回某个类型的最大容量(只能用于切片和 map) |
new、make | new 和 make 均是用于分配内存:new 用于值类型和用户定义的类型,如自定义结构,make用于内置引用类型(切片、map 和管道)。它们的用法就像是函数,但是将类型作为参数:new(type)、make(type)。new(T) 分配类型 T 的零值并返回其地址,也就是指向类型 T的指针。它也可以被用于基本类型: v := new(int) 。make(T) 返回类型T 的初始化之后的值,因此它比 new 进行更多的工作;new() 是一个函数,不要忘记它的括号。 |
copy、append | 用于复制和连接切片 |
panic、recover | 两者均用于错误处理机制 |
print、println | 底层打印函数,在部署环境中建议使用 fmt 包 |
complex、realimag | 用于创建和操作复数 |
1.6、递归函数
Fibonacii数列
package main
import "fmt"
func main() {
fmt.Println(Fibonacci(10))
}
func Fibonacci(n int) (res int) {
if n <= 2 {
res = 1
} else {
res = Fibonacci(n-1) + Fibonacci(n-2)
}
return
}
1.7、将函数作为参数
package main
import "fmt"
func main() {
callback(1, Add)
}
func callback(y int, f func(int, int)) {
f(y, 2)
}
func Add(a, b int) {
fmt.Printf("The sum of %d and %d is:%d\n", a, b, a+b)
}
1.8、闭包
匿名函数赋给变量,然后调用
package main
import "fmt"
func main() {
f()
}
func f() {
for i := 0; i < 4; i++ {
g := func(i int) {
fmt.Printf("%d ", i)
}
g(i)
fmt.Printf("- g is of type %T and has value %v\n", g, g)
}
}
defer搭配匿名函数
常用来改变返回值
package main
import "fmt"
func main() {
fmt.Println(f())
}
func f() (ret int) {
defer func() {
ret++
}()
return 1
}
1.8.1、应用闭包
将函数作为返回值,这里非常神奇啊,乍一看还有点没反应过来,他将函数作为返回值给到变量,变量函数(此刻拿到的是匿名函数)还能继续传参
package main
import "fmt"
func main() {
p2 := Add2()
fmt.Printf("call Add2 for 3 gives: %v\n", p2(3))
TwoAdder := Adder(2)
fmt.Printf("The result is: %v\n", TwoAdder(3))
}
func Add2() func(b int) int {
return func(b int) int {
return b + 2
}
}
func Adder(a int) func(b int) int {
return func(b int) int {
return a + b
}
}
闭包所写的斐波那契数列值得好好分析
package main
import "fmt"
func main() {
f := fibonacci1()
for i := 0; i < 10; i++ {
fmt.Println(f())
}
}
func fibonacci1() func() int {
back1, back2 := 0, 1
return func() int {
temp := back1
back1, back2 = back2, back1 + back2
return temp
}
}
1.8.2计算函数执行时间
package main
import (
"fmt"
"time"
)
func main() {
f := fibonacci1()
start := time.Now()
for i := 0; i < 10; i++ {
fmt.Println(f())
}
end := time.Now()
delta := end.Sub(start)
fmt.Printf("this amount of time: %s\n", delta)
}
func fibonacci1() func() int {
back1, back2 := 0, 1
return func() int {
temp := back1
back1, back2 = back2, back1 + back2
return temp
}
}
1.8.3 妙哉、空间换时间,这斐波那契计算方法时间复杂度太高,而且有些重复计算
package main
import (
"fmt"
"time"
)
const LIM = 50
var fibs [LIM + 1]uint64
func main() {
var result uint64 = 0
start := time.Now()
result = fibonacci2(LIM)
fmt.Printf("fibonacci(%d) is: %d\n", LIM, result)
end := time.Now()
delta := end.Sub(start)
fmt.Printf("this amount of time: %s\n", delta)
}
func fibonacci2(n int) (res uint64) {
if fibs[n] != 0 {
res = fibs[n]
return
}
if n <= 1 {
res = 1
} else {
res = fibonacci2(n-1) + fibonacci2(n-2)
}
fibs[n] = res
return
}
func fibonacci1(n int) (res uint64) {
if n <= 2 {
res = 1
} else {
res = fibonacci1(n-1) + fibonacci1(n-2)
}
return
}