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()
    

    执行结果:

    方法二
    方法一
    
  • 相关阅读:
    开博的第一天!
    使用EditText的addTextChangedListener(new TextWatcher())方法
    Activity的四种launchMode
    MySQL数据库
    BaseAdapter中重写getview的心得以及发现convertView回收的机制
    与数据库打交道的Adapter----SimpleCursorAdapter
    [原创] Fragment的添加、移除问题
    Datum Form Goole Android
    app包中的fragment和v4包中的fragment的使用的区别
    LayoutInflater类详解
  • 原文地址:https://www.cnblogs.com/louyefeng/p/11316868.html
Copyright © 2011-2022 走看看