GO函数

Posted aresxin

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了GO函数相关的知识,希望对你有一定的参考价值。

函数定义

Go语言中定义函数使用func关键字。

func 函数名(参数)(返回值){
    函数体
}

函数名:由字母、数字、下划线组成。但函数名的第一个字母不能是数字。在同一个包内,函数名也称不能重名(包的概念详见后文)。
参数:参数由参数变量和参数变量的类型组成,多个参数之间使用,分隔。
返回值:返回值由返回值变量和其变量类型组成,也可以只写返回值的类型,多个返回值必须用()包裹,并用,分隔。
函数体:实现指定功能的代码块。
函数定义及调用

//定义一个不需要参数也没有返回值的函数
func say(){
    fmt.Println("Hello!")
}
//定义个接受string类型的name参数
func say2(name string)  {
    fmt.Println("hello ",name)
}
func main(){
    //函数调用
    say()   //Hello!
    say2("Ares")    //hello  Ares
}

参数

参数简写
函数的参数中如果相邻变量的类型相同,则可以省略类型

func intsum(x ,y int)  {
    //return x + y
    fmt.Println(x+y)
}

intSum函数有两个参数,这两个参数的类型均为int,因此可以省略x的类型.
可变参数
可变参数是指函数的参数数量不固定。Go语言中的可变参数通过在参数名后加...来标识。

func intsum2(x ... int) int {
    fmt.Println(x)
    sum := 0
    for _,v :=range x{
        sum += v
    }
    return sum
}

func main(){
    //函数调用
    ret1 := intsum2()   //[]
    ret2 := intsum2(2)  //[2]
    ret3 := intsum2(3,3,3,3,3)  //[3 3 3 3 3]
    fmt.Println(ret1,ret2,ret3)     //0 2 15
}

固定参数搭配可变参数时,可变参数要放固定参数后面。

func intsum3(x int,y ... int)int  {
    fmt.Println(x,y)
    sum := x
    for _,v :=range y{
        sum += v
    }
    return sum
}

func main(){
    //函数调用
    ret4 := intsum3(10)     //10 []
    ret5 := intsum3(10,10)  //10 [10]
    ret6 := intsum3(10,11,12,13)    //10 [11 12 13]
    fmt.Println(ret4,ret5,ret6)     //10 20 46
}

函数的可变参数是通过切片来实现的!
多返回值
函数如果有多个返回值时必须用()将所有返回值包裹起来。

//多返回值
func many(x,y int)(int, int)  {
    sum := x+y
    sub := x-y
    return sum,sub
}

func main(){
    //函数调用
    ret7,ret8 := many(2,3)
    fmt.Println(ret7,ret8)  // 5  -1
}

函数定义时可以给返回值命名,并在函数体中直接使用这些变量,最后通过return关键字返回。

//多返回值命名
func many1(x,y int)(sum,sub int)  {
    sum = x+y
    sub = x-y
    return
}
func main(){
    //函数调用
    ret7,ret8 := many1(2,3)
    fmt.Println(ret7,ret8)  // 5  -1
}

defer语句
Go语言中的defer语句会将其后面跟随的语句进行延迟处理。在defer归属的函数即将返回时,将延迟处理的语句按defer定义的逆序进行执行,也就是说,先被defer的语句最后被执行,最后被defer的语句,最先被执行。

func main(){
    fmt.Println("start")
    defer fmt.Println(1)
    defer fmt.Println(2)
    defer fmt.Println(3)
    fmt.Println("end")
}
输出:
start
end
3
2
1

defer语句能非常方便的处理资源释放问题!

函数进阶

全局变量
全局变量是定义在函数外部的变量,它在程序整个运行周期内都有效。 在函数中可以访问到全局变量。

//定义全局变量
var num int = 10

func test()  {
    fmt.Printf("num=%d
",num)
}
func main()  {
    test()  //num=10
}

局部变量
如果局部变量和全局变量重名,优先访问局部变量!

//定义全局变量
var num int = 10

//函数内定义局部变量
func test1()  {
    var num1 int =  20
    fmt.Printf("num=%d,num1=%d
",num,num1)
}
//语句块内定义
func test2(x,y int)  {
    fmt.Println(x,y)    //函数参数只在本函数中有效 2 1
    if x > y{
        z := 1      //z只在if语句中有效
        fmt.Println(z)  //1
    }
}
func main()  {
    test1() //num=10,num1=20
    test2(2,1)
}

函数作为变量

func main()  {
    aa := test //将函数test赋值给aa
    fmt.Printf("%T
",aa)   //func()
    aa()    //num=10
}

函数作为参数

//函数作为参数
func add(x,y int) int {
    return x + y
}
func sub(x,y int)int  {
    return x-y
}
//op是函数名,接受两个int类型参数,返回一个int类型
func calc(x,y int,op func(int,int) int) int  {
    return op(x,y)
}
func main()  {
    ret := calc(10,20,add)
    fmt.Println(ret)    //30
    ret1 := calc(10,20,sub)
    fmt.Println(ret1)   //-10
}

匿名函数
匿名函数就是没有函数名的函数,匿名函数多用于实现回调函数和闭包。
格式:

func(参数)(返回值){
    函数体
}

定义完匿名函数后直接执行:

func main()  {
//方式1
    func(x,y int){
        fmt.Println(x + y)
    }(1,2)  //3,定义完匿名函数后加()直接执行
}
//方式2
say := func(){
        fmt.Println("匿名函数") 
    }
    say()   //匿名函数

闭包
闭包=函数+引用环境
只要引用到外部变量的,就是闭包!

//闭包
//定义一个函数返回值是一个函数
func a() func() {
    name := "ares"
    return func(){
        fmt.Println("hello ",name)
    }
}
//方式2
func b(name string) func() {
    return func(){
        fmt.Println("hello ",name)
    }
}
func main()  {
    r := a()   //此时r就是一个闭包
    r() //相当于执行了a函数背部的匿名函数
}
r2 := b("ares")
r2()

使用闭包做文件名后缀检测实例:

func makeSuffixFunc(suffix string) func(string) string {
    return func(name string) string {
        //若文件后缀是不是以suffix结尾
        if !strings.HasSuffix(name, suffix) {
            //如果不是,返回name + suffix
            return name + suffix
        }else{
            //如果是,返回ok
            return "ok"
        }
        return name
    }
}
func main()  {
    jpgFunc := makeSuffixFunc(".jpg")
    txtFunc := makeSuffixFunc(".txt")
    fmt.Println(jpgFunc("test")) //test.jpg
    fmt.Println(txtFunc("test.txt")) //ok
}

闭包实例:

func calc(base int) (func(int) int, func(int) int) {
    add := func(i int) int {
        base += i
        return base
    }

    sub := func(i int) int {
        base -= i
        return base
    }
    return add, sub
}
func main()  {
    x,y := calc(10)
    ret1 := x(10)   //base=10+10=20
    fmt.Println(ret1)   //20
    ret2 := y(30)   //base=20-30
    fmt.Println(ret2)   //-10
}

内置函数

技术图片?
panic/recover
GO可以使用panic/recover模式来处理错误。 panic可以在任何地方引发,但recover只有在defer调用的函数中有效。
实例:

func a()  {
    fmt.Println("func a")
}
func b()  {
    panic("func b")
}
func c()  {
    fmt.Println("func c")
}
func main()  {
    a()
    b()
    c()
}

执行到func b的时候会抛出异常,程序崩溃,可以使用recover将程序恢复

func a()  {
    fmt.Println("func a")
}
func b()  {
    defer func() {
        err := recover()
        if err != nil{
            fmt.Println("recover fun b")
        }
    }()
    panic("func b")
}
func c()  {
    fmt.Println("func c")
}
func main()  {
    a() //func a
    b() //recover fun b
    c() //func c
}
  • recover()必须搭配defer使用。
  • defer一定要在可能引发panic的语句之前定义。

以上是关于GO函数的主要内容,如果未能解决你的问题,请参考以下文章

解决go: go.mod file not found in current directory or any parent directory; see ‘go help modules‘(代码片段

Go 系列教程 —— 17. 方法

golang代码片段(摘抄)

VSCode自定义代码片段——声明函数

VSCode自定义代码片段8——声明函数

npm : 无法加载文件 D:softcodeProcess ode ode_global pm.ps1,因为在此系统上禁止运行脚本。有关详细信息,请参阅 https:/go.micr +(代码片段