zoukankan      html  css  js  c++  java
  • go:函数

    1. 简介

    1.1 函数类型

      1. 普通带有名字的函数;

      2. 匿名函数或者 lambda 函数;

      3. 方法(Methods)

    1.2 函数签名

      除了main()、init()函数外,其它所有类型的函数都可以有参数返回值。函数参数、返回值以及它们的类型被统称为函数签名

      go里面函数不允许重载,函数名需保证在包内的唯一性;

    1.3 函数作为参数

      函数可以将其他函数作为它的参数,只要这个被调用函数的返回值个数、返回值类型和返回值的顺序与调用函数所需求的实参是一致的;

      示例:

    package main
    
    import "fmt"
    
    func main()  {
    
        fun1(fun2())
    }
    
    func fun1(a int,b int,c int)  {
        fmt.Println(a,b,c)
    }
    
    func fun2()(a int,b int,c int)  {
        return 1,2,3
    }
    View Code

     1.4 函数类型

      函数也可以以申明的方式被使用,作为一个函数类型;

      函数类型可以赋值给变量,就像 add := binOp 一样,这个变量知道自己指向的函数的签名,所以给它赋一个具有不同签名的函数值是不可能的;

      函数值(functions value)之间可以相互比较:如果它们引用的是相同的函数或者都是 nil 的话,则认为它们是相同的函数;

    type binOp func(int, int) int

     1.5 声明外部定义的函数

      如果需要申明一个在外部定义的函数,你只需要给出函数名与函数签名,不需要给出函数体:

    func flushICache(begin, end uintptr) // implemented externally

     2. 函数参数和返回值

      go 语言的函数可以返回多个返回值,称为一组返回值;

      函数定义时,它的形参一般是有名字的,不过我们也可以定义没有形参名的函数,只有相应的形参类型,就像这样:func add ( int, int )

      没有参数的函数通常被称为 niladic 函数(niladic function),就像 main.main()

    2.1 值传递和引用传递

      函数调用时默认采用值传递的方式传递参数,传递的都是变量的副本,函数中对参数副本的修改不影响参数的值;

      如果需要函数直接修改参数的值,可以传递参数的地址(即指针),这样函数就可以直接修改参数的值,传递参数地址的形式:&varName;

        传递指针赋予了函数改变外部变量的能力,还可以节省内存,被修改的变量也不用return

      传递参数地址的本质也是值传递,指针也是变量类型,有自己的地址和值,通常指针的值指向一个变量的地址。所以,按引用传递也是按值传递;

    2.2 返回值命名

      尽量使用命名返回值:会使代码更清晰、更简短,同时更加容易读懂

      返回值只有数据类型,没有命名返回参数名称的时候,直接返回对应类型的值即可;

    func func3()(int,int)  {
        return 2,3
    }

      返回值命名了参数名称时,在对返回参数赋值后,直接return即可,不用显示return 返回参数,如果没有对返回参数进行赋值操作,则返回该参数类型的零值;

    func main()  {
    
        i, i2 := func3()
        fmt.Println(i,i2)
    
        a1, a2 := func4()
        fmt.Println(a1,a2)
    
        a12, a22 := func5()
        fmt.Println(a12,a22)
    }
    
    func func3()(int,int)  {
        /**
            输出:2 3
         */
        return 2,3
    }
    
    func func4()(a1 int,a2 int)  {
        /**
        输出: a1:12  a2:13
         */
        a1=12
        a2=13
        return
    }
    
    func func5()(a1 int,a2 int)  {
        /**
            输出: a1:12  a2:0
         */
        a1=12
        a3:=13
        fmt.Println("temp var",a3)
        return
    }

    2.3 空白符_

      如果不需要某个返回值,可以将这个返回值赋值给空白符

    2.4  变长参数

      类似于Java,变长参数必须作为参数列表中的最后一个,形式如下:

    func func6(a int, s... int ) {
    
    }
    

    2.5 defer

      defer 的用法类似于 Java 的 finally,用于在函数执行完成后进行释放资源的操作;

      defer 关键字可以允许程序在 return 之后执行某个语句或者函数;

      如果一个函数内有多个 defer,则会按照 defer 的定义顺序的逆序执行;

      程序按照语句顺序执行到 defer 位置时,会先计算确定 defer 函数的参数(此处已经计算确定了参数值,后面就算再修改这个参数变量的值也不会影响 defer 函数调用时的参数值 ),然后在程序 return 后执行该函数;

      被 defer 的函数可以读取并修改有变量名的返回参数,一般配合匿名函数使用;

      示例:

    package main
    
    import "fmt"
    
    func main() {
    
        deferOrder()
        defineDeferParamFuncValue()
        defineDeferParamValue()
        fmt.Println(modifyReturnParamValue())
    }
    
    func trace(s string) string {
        fmt.Println("entering:", s)
        return s
    }
    
    func un(s string) {
        fmt.Println("leaving:", s)
    }
    func deferOrder() {
        /**
            输出:
            in func deferOrder
            a2
            a1
         */
        defer fmt.Println("a1")
        fmt.Println("in func deferOrder")
        defer fmt.Println("a2")
    }
    
    func defineDeferParamFuncValue() {
        /**
            输出:
            entering: func defineDeferParamFuncValue
            in func defineDeferParamFuncValue
            leaving: func defineDeferParamFuncValue
         */
        // 程序执行到此处时,会先计算确定 defer 函数的参数,然后在程序 return 后执行该函数;
        defer un(trace("func defineDeferParamFuncValue"))
        fmt.Println("in func defineDeferParamFuncValue")
    }
    
    func defineDeferParamValue() {
        /**
            输出: 0
         */
        // defer 函数的参数在计算确定之后,即使参数发生变化,对已经 defer 函数的参数也没有影响
        i:=0
        defer fmt.Println("define defer param value:",i)
        i+=1
    }
    
    func modifyReturnParamValue() (x int) {
        defer func() { x++ }()
        x = 2
        return 3
    }
  • 相关阅读:
    STM32驱动WS2811
    Arduino编程器 USBasp USBtinyISP FT232-ISP 对比 区别
    USBasp制作资料及全过程(菜鸟版)
    用74HC165读8个按键状态
    C++ 使用TinyXML解析XML文件
    SD卡中FAT32文件格式快速入门(图文详细介绍)
    一个UUID生成算法的C语言实现——WIN32版本
    关于STM8S使用硬件SPI收发问题
    设计模式介绍、分类、原则
    构建完整的知识体系
  • 原文地址:https://www.cnblogs.com/virgosnail/p/12918680.html
Copyright © 2011-2022 走看看