zoukankan      html  css  js  c++  java
  • GO开发[四]:golang函数

    函数

    1.声明语法:func 函数名 (参数列表) [(返回值列表)] {}

    2.golang函数特点:

    a. 不支持重载,一个包不能有两个名字一样的函数

    b. 函数是一等公民,函数也是一种类型,一个函数可以赋值给变量

    c. 匿名函数

    d. 多返回值

    定义函数类型type:

    package main
    
    import "fmt"
    
    type add_func func(int, int) int
    
    func add(a, b int) int {
       return a + b
    }
    
    func sub(a, b int) int {
       return a - b
    }
    
    func operator(op add_func, a int, b int) int {
       return op(a, b)
    }
    
    func main() {
       c := add
       fmt.Println(c)
       sum := operator(c, 100, 200)
       fmt.Println(sum)
    
       var x add_func
       x=sub
       fmt.Println(x)
       sub := operator(x, 100, 200)
       fmt.Println(sub)
       
    }
    

    3.函数参数传递方式:

    1). 值传递

    2). 引用传递

    注意1:无论是值传递,还是引用传递,传递给函数的都是变量的副本,不过,值传递是值的拷贝。

    引用传递是地址的拷贝,一般来说,地址拷贝更为高效。而值拷贝取决于拷贝的对象大小,对象越大,则性能越低。

    注意2:map、slice、chan、指针、interface默认以引用的方式传递

    package main
    
    import "fmt"
    
    func modify(a *int) {
       *a = 100
    }
    
    func main() {
       a := 8
       fmt.Println(a)
       modify(&a)
       fmt.Println(a)
    }
    

    参数类型省略:

    func f(i, j, k int, s, t string)
    func f(i int, j int, k int, s string, t string)
    

    4.命名返回值的名字:

    package main
    import "fmt"
    func split(sum int) (x, y int) {
    	x = sum / 10
    	y = sum % 10
    	return
    } 
    func main() {
    	fmt.Println(split(17))
    }
    

    _标识符,用来忽略返回值

    5.可变参数:

    func add(arg …int) int {
    }//0个或多个参数
    func add(a int, arg …int) int {
    }//1个或多个参数
    func add(a int, b int, arg …int) int {
    }//2个或多个参数
    

    注意:其中arg是一个slice,我们可以通过arg[index]依次访问所有参数,通过len(arg)来判断传递参数的个数

    练习:写一个函数add,支持1个或多个int相加,并返回相加结果

    练习:写一个函数concat,支持1个或多个string相拼接,并返回结果

    defer

    1.当函数返回时,执行defer语句。可以用来做资源清理

    2.多个defer语句,按先进后出的方式执行,即最后一个defer语句将最先被执行

    3.defer语句中的变量,在defer声明时就决定了。

    在函数将要返回前执行:

    package main
    
    import "fmt"
    
    func print() {
       defer func() {
          fmt.Println("defer")
       }()
       fmt.Println("hello")
    }
    
    func main()  {
       print()
    }
    

    多个defer语句:

    package main
    
    import "fmt"
    
    func main()  {
       var i int =1
       fmt.Println(i)
       defer fmt.Println(i)
       //不会立即执行,压到栈里面,函数执行结束后,再执行栈里的
       defer fmt.Println("a")
       i=10
       fmt.Println(i)
    }
    

    用途:

    1.关闭文件句柄

    2.锁资源释放

    3.数据库连接释放

    内置函数

    1.close:主要用来关闭channel

    2.len:用来求长度,比如string、array、slice、map、channel

    3.new:用来分配内存,主要用来分配值类型,比如int、struct。返回的是指针

    package main
    
    import "fmt"
    
    func main()  {
       var i int
       fmt.Println(i)
    
       j := new(int)
       fmt.Println(j)
       fmt.Println(*j)
    
       *j = 100
       fmt.Println(*j)
    }
    

    4.make:用来分配内存,主要用来分配引用类型,比如chan、map、slice

    new和make的区别:

    package main
    
    import "fmt"
    
    func test() {
       s1 := new([]int)
       fmt.Println(s1)
    
       s2 := make([]int, 10)
       fmt.Println(s2)
    
       *s1 = make([]int, 5)
       (*s1)[0] = 100
       s2[0] = 100
       fmt.Println(s1)
       fmt.Println(s2)
       return
    }
    
    func main() {
       test()
    }
    

    5.append:用来追加元素到数组、slice中

    package main
    
    import "fmt"
    
    func main()  {
       var a []int
       a = append(a,10,20,30)
       a = append(a,a...)
       fmt.Println(a)
    }
    

    错误处理error

    Go语言引入了一个关于错误处理的标准模式,即error接口,该接口的定义如下:

    type error interface {
    	Error() string
    }
    

    1.初始化失败,退出

    2.重试,比如if err !=nil,重试3次

    3.异常上抛

    package main
    
    import "fmt"
    
    func print() {
       var p *int
       fmt.Println(*p)
    }
    
    func main() {
    
       defer func() {
          err := recover()
          fmt.Println(err)
       }()
       panic("不想执行下去了")
    
    
       //print()//1.空指针引用错误
    
    
       //var n int
       //fmt.Println(10 / n) //2.除数为0
    
       /*
       var i=3
       var slice [3]int
       fmt.Println(slice[i])//3.下标越界
       */
    }
    

    EOF error

    recover.go:

    Go语言引入了两个内置函数panic()和recover()以报告和处理运行时错误和程序中的错误场景:

    当在一个函数执行过程中调用panic()函数时,正常的函数执行流程将立即终止,但函数中之前使用defer关键字延迟执行的语句将正常展开执行,之后该函数将返回到调用函数,并导致逐层向上执行panic流程,直至所属的goroutine中所有正在执行的函数被终止。错误信息将被报告,包括在调用panic()函数时传入的参数,这个过程称为错误处理流程。

    recover()函数用于终止错误处理流程。一般情况下, recover()应该在一个使用defer关键字的函数中执行以有效截取错误处理流程。如果没有在发生异常的goroutine中明确调用恢复过程(使用recover关键字) ,会导致该goroutine所属的进程打印异常信息后直接退出。

    package main
    
    import (
       "fmt"
       "time"
    )
    
    func test() {
       defer func() {
          if err := recover(); err != nil {
             fmt.Println(err)
          }
       }()
    
       b:=0
       a := 1/b
       fmt.Println(a)
       return
    }
    
    func main() {
       for {
          test()
          time.Sleep(time.Second)
       }
    }
    

    panic.go

    package main
    
    import (
       "fmt"
       "time"
       "errors"
    )
    func initConfig() (err error) {
       return errors.New("init config failed")
    }
       err := initConfig()
       if err != nil {
          panic(err)
       }
       return
    }
    
    func main() {
       for {
          test()
          time.Sleep(time.Second)
       }
    }
    

    递归

    一个函数调用自己,就叫做递归。

    package main
    
    import (
       "fmt"
       "time"
    )
    
    func recusive(n int) {
       fmt.Println("hello golang", n)
       time.Sleep(time.Second)
       if n > 10 {
          return
       }
       recusive(n + 1)
    }
    
    func main() {
       recusive(0)
    }
    

    递归实现阶乘和斐波那契数列:

    package main
    
    import (
       "fmt"
       "time"
    )
    
    func factor(n int) int {
       if n == 1 {
          return 1
       }
       return factor(n-1) * n
    }
    
    func fab(n int) int {
       if n <= 1 {
          return 1
       }
       return fab(n-1) + fab(n-2)
    }
    
    func main() {
       fmt.Println(factor(5))
       for i := 0; i < 10; i++ {
          fmt.Println(fab(i))
       }
    }
    

    函数类型

    package main
    
    import "fmt"
    
    func print1(){
       fmt.Println("print1")
    }
    
    func print2() {
       fmt.Println("print2")
    }
    
    func func1(n int) int {
       return n+1
    }
    
    func main() {
       //变量是个筐,装这个变量类型的数据
       //函数也是个筐,容器,装的函数
       var f func()
       f = print1
       f()
       f=print2
       f()
    
    
       var flist [3]func(int) int
       flist[0]=func1
       m:=flist[0](10)
       fmt.Println(m)
       fmt.Println(flist[0](10))
    }
    

    加减乘除:

    package main
    
    import (
       "fmt"
       "os"
       "strconv"
    )
    
    func add(m, n int) int {
       return m + n
    }
    
    func sub(m, n int) int {
       return m - n
    }
    
    func comp(m,n int) int {
       return m * n
    }
    
    func div(m,n int) int {
       return m/n
    }
    
    func main() {
       funcmap := map[string]func(int, int) int{
          "+": add,
          "-": sub,
          "*":comp,
          "/":div,
       }
    
       m, _ := strconv.Atoi(os.Args[1])
       n, _ := strconv.Atoi(os.Args[3])
    
       f := funcmap[os.Args[2]]
       if f != nil {
          fmt.Println(f(m, n))
          }
    }
    

    匿名函数

    匿名函数是指不需要定义函数名的一种函数实现方式

    在Go里面,函数可以像普通变量一样被传递或使用,这与C语言的回调函数比较类似。不同的是, Go语言支持随时在代码里定义匿名函数。

    package main
    import (
    	"fmt"
    	"strings"
    )
    func toupper(s string) string {
    	return strings.Map(func(r rune) rune {
    		return r - ('a' - 'A')
    	}, s)
    }
    
    
    func main() {
    	f := func(x,y int) int {
    		return x + y
    	}
    	fmt.Println(f(1,2))
    
    	f1:=func(x,y int) int {
    		return x + y
    	}(1,3)
    	fmt.Println(f1)
    	
    	fmt.Println(toupper("hello"))
    }
    

    闭包

    闭包:一个函数和与其相关的引用环境组合而成的实体

    package main
    
    import (
       "fmt"
    )
    
    func addn(n int) func(int) int {
       return func(m int) int {
          return m+n
       }
    }
    
    func main() {
       f := addn(3)
       fmt.Println(f(12))
    }
    

    生成器:

    package main
    
    import "fmt"
    
    func iter(s []int) func() int {
       var i = 0
       return func() int {
          if i >= len(s) {
             return 0
          }
          n := s[i]
          i += 1
          return n
       }
    }
    
    func main() {
       f := iter([]int{1, 2, 3})
       fmt.Println(f())
       fmt.Println(f())
       fmt.Println(f())
    }
    
  • 相关阅读:
    shell脚本批量启动jar
    springboot最简单的AOP
    springboot 将null字段输出为空串
    随便记录
    MySQL case when 用法
    JavaDate数据返回到前端变数字的问题
    多级菜单无限递归
    linux tomacat 之部署 war包
    linux tomcat部署 之 jre
    leetcode Best Time to Buy and Sell Stock
  • 原文地址:https://www.cnblogs.com/ningxin18/p/8331249.html
Copyright © 2011-2022 走看看