• go入门快速学习笔记二:函数、数组与切片


    1、函数

    1.1、不支持重载,暂无泛型

    普通函数

    1. package main
    2. import "fmt"
    3. func main() {
    4. println("----------------")
    5. prt("你好")
    6. println("!!!!!!!!!!!!!!!!")
    7. }
    8. func prt(s string) {
    9. fmt.Printf("hello:%s",s)
    10. }
    11. func prt(s string,n int16) {
    12. fmt.Printf("hello:%s\n",s)
    13. fmt.Printf("n = %d",n)
    14. }

    1.2、可以有多个返回值

    可以命名返回,也可非命名返回

    1. package main
    2. import "fmt"
    3. var num int = 10
    4. var numx2, numx3 int
    5. func main() {
    6. println("----------------")
    7. numx2 , numx3 = getX2AndX3(num)
    8. PrintValues()
    9. numx2 , numx3 = getX2AndX3f(num)
    10. PrintValues()
    11. }
    12. func PrintValues() {
    13. fmt.Printf("num = %d,2x num = %d,3x num = %d\n", num, numx2, numx3)
    14. }
    15. func getX2AndX3(input int) (int, int) {
    16. return 2 * input, 3 * input
    17. }
    18. func getX2AndX3f(input int) (x2 int, x3 int) {
    19. x2 = 2 * input
    20. x3 = 3 * input
    21. return
    22. }

    1.2.1、使用空白符

    能丢弃不需要的值

    1. package main
    2. import "fmt"
    3. func main() {
    4. var i int
    5. var f float32
    6. i, _, f = PrintValues()
    7. fmt.Printf("int : %d ,float: %f \n", i, f)
    8. }
    9. func PrintValues() (int, int, float32) {
    10. return 2, 4, 5.31
    11. }

    1.2.2、改变外部变量

    1. package main
    2. import "fmt"
    3. func main() {
    4. n := 0
    5. reply := &n
    6. Multiply(10, 5, reply)
    7. fmt.Println("multiply:", *reply)
    8. }
    9. func Multiply(a, b int, reply *int) {
    10. *reply = a * b
    11. }

    1.3、可变长参数

    1. package main
    2. import (
    3. "fmt"
    4. )
    5. func main() {
    6. x := min(1, 3, 2, 7)
    7. fmt.Printf("minmum is : %d\n", x)
    8. arr := []int{7, 9, 3, 5}
    9. x = min(arr...)
    10. fmt.Printf("minmum is : %d\n", x)
    11. }
    12. func min(a ...int) int {
    13. if len(a) == 0 {
    14. return 0
    15. }
    16. min := a[0]
    17. for _, v := range a {
    18. if v < min {
    19. min = v
    20. }
    21. }
    22. return min
    23. }

    1.4、defer和追踪

    允许推迟执行所描述的语句,直到函数完成前

    1.4.1、若是有多个defer,执行顺序类似出栈

    1. package main
    2. import "fmt"
    3. func main() {
    4. function()
    5. }
    6. func function() {
    7. fmt.Printf("In function at the top\n")
    8. defer function1()
    9. defer function2()
    10. defer function3()
    11. fmt.Printf("In function at the bottom!\n")
    12. }
    13. func function1() {
    14. fmt.Printf("function1 !")
    15. }
    16. func function2() {
    17. fmt.Printf("function2 !")
    18. }
    19. func function3() {
    20. fmt.Printf("function3 !")
    21. }

    1.4.2、语句中有变量时,至此值是定死了,虽然执行可能在变量重新赋值之后,但是变量值是不会再变的

    1. package main
    2. import "fmt"
    3. func main() {
    4. var a int = 2
    5. function(a)
    6. }
    7. func function(a int) {
    8. fmt.Printf("In function at the top,a=%d\n", a)
    9. defer function1(a)
    10. fmt.Printf("In function at the bottom,a=%d\n", a)
    11. a = 4
    12. fmt.Println(a)
    13. }
    14. func function1(a int) {
    15. fmt.Printf("function1 a = %d!", a)
    16. }
    17. // 结果:
    18. // In function at the top,a=2
    19. // In function at the bottom,a=2
    20. // 4
    21. // function1 a = 2!

    1.4.3、常见应用场景

    关闭文件流

    1. open a file
    2. defer file.Close()

    解锁

    1. mu.Lock()
    2. defer mu.Unlock()

    打印最终报告

    1. printHeader()
    2. defer printFooter()

    关闭数据库连接

    defer disconnectFromDB()

    使用defer实现追踪

    此函数非常明显的展示了defer的调用时机

    1. package main
    2. import "fmt"
    3. func main() {
    4. b()
    5. }
    6. func b() {
    7. trace("b")
    8. defer untrace("b")
    9. fmt.Println("in b")
    10. a()
    11. }
    12. func a() {
    13. trace("a")
    14. defer untrace("a")
    15. fmt.Println("in a")
    16. }
    17. func trace(s string) {
    18. fmt.Println("entering:", s)
    19. }
    20. func untrace(s string) {
    21. fmt.Println("leaving:", s)
    22. }

    使用defer记录函数的参数与返回值

    1. package main
    2. import (
    3. "io"
    4. "log"
    5. )
    6. func func1(s string) (n int, err error) {
    7. defer func() {
    8. log.Printf("func1(%q) = %d, %v", s, n, err)
    9. }()
    10. return 7, io.EOF
    11. }
    12. func main() {
    13. func1("Go")
    14. }

    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数列

    1. package main
    2. import "fmt"
    3. func main() {
    4. fmt.Println(Fibonacci(10))
    5. }
    6. func Fibonacci(n int) (res int) {
    7. if n <= 2 {
    8. res = 1
    9. } else {
    10. res = Fibonacci(n-1) + Fibonacci(n-2)
    11. }
    12. return
    13. }

    1.7、将函数作为参数

    1. package main
    2. import "fmt"
    3. func main() {
    4. callback(1, Add)
    5. }
    6. func callback(y int, f func(int, int)) {
    7. f(y, 2)
    8. }
    9. func Add(a, b int) {
    10. fmt.Printf("The sum of %d and %d is:%d\n", a, b, a+b)
    11. }

    1.8、闭包

    匿名函数赋给变量,然后调用

    1. package main
    2. import "fmt"
    3. func main() {
    4. f()
    5. }
    6. func f() {
    7. for i := 0; i < 4; i++ {
    8. g := func(i int) {
    9. fmt.Printf("%d ", i)
    10. }
    11. g(i)
    12. fmt.Printf("- g is of type %T and has value %v\n", g, g)
    13. }
    14. }

    defer搭配匿名函数

    常用来改变返回值

    1. package main
    2. import "fmt"
    3. func main() {
    4. fmt.Println(f())
    5. }
    6. func f() (ret int) {
    7. defer func() {
    8. ret++
    9. }()
    10. return 1
    11. }

    1.8.1、应用闭包

    将函数作为返回值,这里非常神奇啊,乍一看还有点没反应过来,他将函数作为返回值给到变量,变量函数(此刻拿到的是匿名函数)还能继续传参

    1. package main
    2. import "fmt"
    3. func main() {
    4. p2 := Add2()
    5. fmt.Printf("call Add2 for 3 gives: %v\n", p2(3))
    6. TwoAdder := Adder(2)
    7. fmt.Printf("The result is: %v\n", TwoAdder(3))
    8. }
    9. func Add2() func(b int) int {
    10. return func(b int) int {
    11. return b + 2
    12. }
    13. }
    14. func Adder(a int) func(b int) int {
    15. return func(b int) int {
    16. return a + b
    17. }
    18. }

    闭包所写的斐波那契数列值得好好分析

    1. package main
    2. import "fmt"
    3. func main() {
    4. f := fibonacci1()
    5. for i := 0; i < 10; i++ {
    6. fmt.Println(f())
    7. }
    8. }
    9. func fibonacci1() func() int {
    10. back1, back2 := 0, 1
    11. return func() int {
    12. temp := back1
    13. back1, back2 = back2, back1 + back2
    14. return temp
    15. }
    16. }

    1.8.2计算函数执行时间

    1. package main
    2. import (
    3. "fmt"
    4. "time"
    5. )
    6. func main() {
    7. f := fibonacci1()
    8. start := time.Now()
    9. for i := 0; i < 10; i++ {
    10. fmt.Println(f())
    11. }
    12. end := time.Now()
    13. delta := end.Sub(start)
    14. fmt.Printf("this amount of time: %s\n", delta)
    15. }
    16. func fibonacci1() func() int {
    17. back1, back2 := 0, 1
    18. return func() int {
    19. temp := back1
    20. back1, back2 = back2, back1 + back2
    21. return temp
    22. }
    23. }

    1.8.3 妙哉、空间换时间,这斐波那契计算方法时间复杂度太高,而且有些重复计算

    1. package main
    2. import (
    3. "fmt"
    4. "time"
    5. )
    6. const LIM = 50
    7. var fibs [LIM + 1]uint64
    8. func main() {
    9. var result uint64 = 0
    10. start := time.Now()
    11. result = fibonacci2(LIM)
    12. fmt.Printf("fibonacci(%d) is: %d\n", LIM, result)
    13. end := time.Now()
    14. delta := end.Sub(start)
    15. fmt.Printf("this amount of time: %s\n", delta)
    16. }
    17. func fibonacci2(n int) (res uint64) {
    18. if fibs[n] != 0 {
    19. res = fibs[n]
    20. return
    21. }
    22. if n <= 1 {
    23. res = 1
    24. } else {
    25. res = fibonacci2(n-1) + fibonacci2(n-2)
    26. }
    27. fibs[n] = res
    28. return
    29. }
    30. func fibonacci1(n int) (res uint64) {
    31. if n <= 2 {
    32. res = 1
    33. } else {
    34. res = fibonacci1(n-1) + fibonacci1(n-2)
    35. }
    36. return
    37. }

  • 相关阅读:
    docker 启动容器
    `英语` 2022/8/12
    【网工必备】CIDR-路由聚合你了解了没!?
    Item 42: Consider emplacement instead of insertion.
    java计算机毕业设计ssm二手商品交易平台
    1、深入了解MySQL中内部组件架构(连接器,查询缓存,分析器,优化器,执行器等)
    域内令牌窃取伪造
    vue3学习(二)--- ref和reactive
    什么是腾讯云云硬盘?有哪些优势?应用于哪些场景?
    Day 10:100322. 删除星号以后字典序最小的字符串
  • 原文地址:https://blog.csdn.net/qq_35515283/article/details/127123236