zoukankan      html  css  js  c++  java
  • Go 函数

    Go 函数

    函数是Go语言基本的代码块,拥有自己的作用域,用于指向一个任务,Go语言最少有个main()入口函数。

    函数定义格式如下:

    func function_name([parameter list]) [return_types]{
        //函数体,需要编写的逻辑代码
    }
    

    定义分析:

    • func:使用func关键字来定义一个函数
    • function_name:为函数名称,函数名和参数列表一个构成函数签名
    • parameter list:参数列表,参数就像一个占位符,当函数被调用时,你可以将值传递给参数,这个值称为实际参数,参数列表知道的是参数类型、顺序、个数。
    • return_types:返回类型,函数返回值,可以有返回值,也可以没有返回值,还可以拥有多个返回值。

    函数实例:

    package main
    import "fmt"
    const PI = 3.14
    func main(){
        num = area(10)
        fmt.Printf("面积为: %v", num)
    }
    
    func area(radius int) float64{
        num := float64(radius) * float64(radius) * PI
    	return num
    }
    

    函数传若干参数

    如果一个函数需要传入若干不确定个数的参数,就可以使用"..."的方式来表达这若干个参数,如:

    func test(args ...string){
        fmt.Printf("%T", args) //打印类型是数组
    }
    

    ...其实是Go语言的一种语法糖,方便使用,上面这种方式是用法之一,另一种常用方式是slice可以被打散进行传递。

    案例如下:

    type Cruncher func(int) int //定义了一个Cruncher类型,表示所有参数是一个int类型返回值是一个int类型的所有函数都是Cruncher类型
    
    func mul(n int) int {
    	return n * 2
    }
    
    func add(n int) int {
    	return n + 100
    }
    
    func sub(n int) int {
    	return n - 1
    }
    
    func crunch(nums []int, a ...Cruncher) (rnums []int) {
    	rnums = append(rnums, nums...)
    
    	for _, f := range a {
    		for i, n := range rnums {
    			rnums[i] = f(n)
    			fmt.Println(i, n)
    		}
    	}
    
    	return rnums
    }
    

    使用

    var nums = []int{1,2,3,4,5}
    fmt.Println(crunch(nums, mul, add, sub))
    // 输出结果为:[101, 103, 105, 107, 109]
    

    匿名函数

    匿名函数就是没有名字的函数,它以函数字面量的方式在行内进行声明。

    拥有同样的函数签名形式,同样拥有参数列表和返回值。案例:

    func (a,b,c int) bool{
        return a + b
    } 
    

    匿名函数只是作为一个表达式,那是非常没有意义的。匿名函数可以直接赋给一个变量,作为结构字段,或者把它传递到另外的函数当中或者直接执行。

    匿名函数可以通过变量赋值来给他一个名字,并且可以使用这个名字加()的方式来调用,如:

    fn:= func (a,b,c int) bool{
        return a + b
    }
    // 调用该函数
    fn()
    

    或者直接在匿名函数最后加括号来调用函数,如:

    var res string
    res = func(name string) string {
    	return name + "dsb"
    }("abc")
    fmt.Println(res) // 结果为abcdsb
    

    闭包函数

    闭包是可以包含自由(未绑定到特定对象)变量的代码块,这些变量不在这个代码块内或者任何全局上下文中定义,而是在定义代码块的环境中定义。要执行的代码块(由于自由变量包含在代码块中,所以这些自由变量以及它们引用的对象没有被释放)为自由变量提供绑定的计算环境(作用域)。

    闭包函数的功能实现,简单的说就是编写一个函数,返回值是另一个函数,所有函数可以作为参数传递的语言都可以实现闭包,闭包的好处参考:https://www.cnblogs.com/cxying93/p/6103375.html

    Go实现闭包:

    package main
    import "fmt"
    
    func main(){
        isPng = makeSuffixFunc(".png")
        res = isPng("Yven")
        fmt.Println(res) // 结果输出Yven.png
    }
    
    func makeSuffixFunc(suffix string) func(string) string{
        return func(name string) string{
            if strings.HasSuffix(name,suffix){
                return name
            }
            return name + suffix
        }
    }
    

    延时函数

    延时函数只在其父函数返回时被调用。多个延时函数会以栈的形式一个接一个被调用。

    延时函数使用关键字defer,每当defer执行的时候,它后面的函数值和函数参数会被求值,但是函数不会立即调用,直到外围的函数返回,或者外围函数运行到最后,或者相应的goroutine panic。

    案例:

    func readFile(filename string){
        file, err := os.Open(filename)
        if err != nil{
            fmt.Println("错误信息:",err)
            return 
        }
        defer file.Close()
        content. err := ioutil.ReadAll(file)
        if err != nil{
            fmt.Println("错误信息:",err)
            return 
        }
        return string(content)
    }
    

    如果defer后面的file.Close()没有延迟执行,那么文件描述符都关闭了,就不会读取到任何内容。

    注意:如果存在多个defer语句,最后的defer函数的执行顺序与defer出现的顺序相反,如:

    func1 := func (){
        fmt.Println("方法一")
    }
    func2 := func (){
        fmt.Println("方法二")
    }
    defer func1()
    defer func2()
    

    执行结果:

    方法二
    方法一
    
  • 相关阅读:
    springboot文件上传: 单个文件上传 和 多个文件上传
    Eclipse:很不错的插件-devStyle,将你的eclipse变成idea风格
    springboot项目搭建:结构和入门程序
    POJ 3169 Layout 差分约束系统
    POJ 3723 Conscription 最小生成树
    POJ 3255 Roadblocks 次短路
    UVA 11367 Full Tank? 最短路
    UVA 10269 Adventure of Super Mario 最短路
    UVA 10603 Fill 最短路
    POJ 2431 Expedition 优先队列
  • 原文地址:https://www.cnblogs.com/louyefeng/p/11316868.html
Copyright © 2011-2022 走看看