Go

区块链 GO 函数

2018-01-20  本文已影响47人  ze__lin

函数是基本的代码块,用于执行一个任务,是构成代码执行的逻辑结构。
在Go语言中,函数的基本组成为:关键字func、函数名、参数列表、返回值、函数体和返回语句。

函数定义

每个go程序都是从名为main的package包的main()函数开始执行包的概念不是这里的重点,以后做单独说明。同时main()函数是无参数,无返回值的。

格式

func funcName(形参1 type[, 形参2 type...]) [([[返回变量1] type[, [返回变量2] type...]])] {
[return [返回变量1[, 返回变量2...]]]
}
a. 如果形参类型都一样,可以这样写: 形参1, 形参2 type, 同时返回变量也一样
b. 如果只有一个返回值或者无返回值, 可以去掉对应的()
c. 如果返回有返回值,该函数中最外层要有return语句
d. 返回语句(), 返回变量名可以省略
e. []表示可省略
f. 不支持默认参数

package main

import "fmt"

func printName(name1 string, name2 string) {
    fmt.Println("name1 = ", name1, "  ", "name2 = ", name2)
}

func main() {

    printName("张三", "李四")

}
输出为:
name1 = 张三     name2 = 李四 
package main

import "fmt"

// 如果有多个参数,并且参数类型一致,可以省略掉前面的参数的类型
func printName(name1, name2 string) {
    fmt.Printf("%T\t%T\n", name1, name2)//输出验证name1, name2的类型是否为string
    fmt.Println("name1 = ", name1, "  ", "name2 = ", name2)
}

func main() {
    // var a,b,c,d int;

    printName("张三", "李四")
}
输出为:
string  string
name1 = 张三     name2 = 李四 
作用域

在 Go 中,定义在函数外的变量是全局的,那些定义在函数内部的变量,对于函数来说是局部的。如果命名覆盖 — 一个局部变量与一个全局变量有相同的名字 — 在函数执行的时候,局部变量将覆盖全局变量。

返回值

函数的返回值可以是一个也可以是多个

package main

import "fmt"

// func关键字
// aAddB函数名
// a、b 参数
// int 返回值类型
//下面是几种返回值类型与返回值的写法:
func aAddB(a, b int) int {
    return a + b
}

// func aSubB(a, b int) int {
//  return a - b
// }

// func aSubB(a, b int) (int) {
//  return a - b
// }

// func aSubB(a, b int) (s int) {
//  s = a - b
//  return s
// }

// func aSubB(a, b int) (s int) {
//  s = a - b
//  return
// }

func aSubB(a, b int) (s int) {

    return a - b
}

func main() {
    num := aAddB(5, 6)
    fmt.Println(num)
    fmt.Println(aSubB(5, 6))
}

多个返回值
go支持多个返回值
如: for k, v := range array ...
a. 如果不想要某个返回值,可以用 "_" 代替,如 for _, v := range array...,不能直接写为这样 for , v :=range array...,但可以省略 v(值), 写为 for k := range array...
b. 如果普通函数返回n个值时,不能用少于n个变量去接收
c. 不能直接打印有多个返回值的函数调用结果
d. 如果定义了返回值的变量名,就可以省略 return 语句后面的返回列表

函数参数

函数定义时指出,函数定义时有参数,该变量可称为函数的形参。形参就像定义在函数体内的局部变量。
但当调用函数,传递过来的变量就是函数的实参,函数可以通过两种方式来传递参数:

值传递:指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。
引用传递:是指在调用函数时将实际参数的地址传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。

在默认情况下,Go 语言使用的是值传递,即在调用过程中不会影响到实际参数。

变参

接受变参的函数是有着不定数量的参数的。其函数定义形式如下:

func funcname(arg ... type) { }

arg ... type 告诉 Go 这个函数接受不定数量的参数。注意,在函数体中,变量 arg 是一个type类型的 slice,可以使用 range 遍历,也可以将其作为实参全部或者部分传递给调用函数。

package main

import "fmt"

// 传的是一个slice,slice分片
func sortSlice(numbers []int) []int {
    fmt.Println(numbers)
//冒泡排序
    for j := 0; j < len(numbers)-1; j++ {
        for i := 0; i < len(numbers)-1-j; i++ {
            if numbers[i] > numbers[i+1] {
                temp := numbers[i]
                numbers[i] = numbers[i+1]
                numbers[i+1] = temp
            }
        }
    }

    return numbers
}

func main() {
    // 排序前
    numbers := []int{23, 45, 12, 56, 78, 89}

    // 排完序以后的numbers
    numbers = sortSlice(numbers)

    fmt.Println(numbers)

}

package main

import "fmt"

// 动态参数
func sortSlice(numbers ...int) []int {
    fmt.Println(numbers)
    //冒泡排序
    for j := 0; j < len(numbers)-1; j++ {
        for i := 0; i < len(numbers)-1-j; i++ {
            if numbers[i] > numbers[i+1] {
                temp := numbers[i]
                numbers[i] = numbers[i+1]
                numbers[i+1] = temp
            }
        }
    }

    return numbers
}

func main() {
    // 排序前
    numbers := []int{23, 45, 12, 56, 78, 89}

    // 排完序以后的numbers
    numbers = sortSlice(numbers...)

    fmt.Println(numbers)

}

函数作为值
package main

import "fmt"

// 内容:
// 函数本身也是一个类型
// 函数也有变量
// 函数也可以赋值

var a int = 9

// greating : 函数变量
// 函数值:
// func () {
//  fmt.Println("Hello World!")
// }

// 全局的函数的声明
func greating() {
    fmt.Println("Hello World!")
}

// func(int, int) int

// 判断函数类型的方法:
// 只需要把函数名和其他行参名字去掉,剩下的就是函数类型
func addAB(a int, b int) (s int) {
    return a + b
}

func aSubB(a, b int) int {
    return a - b
}

func main() {
    greating()
    // 函数赋值
    greating1 := greating

    greating1()
    // 打印类型
    fmt.Printf("%T \t %T\n", greating1, greating)
    /*
       Hello World!
       Hello World!
       func()    func()
    */

    fmt.Printf("%T\n", addAB)
}

匿名函数

匿名函数即没有函数名的函数,只能放在函数中,可以实现函数嵌套定义的功能。

package main

import "fmt"

func main() {
    // greating局部变量
    greating := func() {
        fmt.Println("Hello World!")
    }
    // 只有调用函数的时候,函数体里面的代码才会被执行
    greating()
    // 函数值,匿名函数
    func() {
        fmt.Println("函数值,匿名函数!")
    }()
}

返回值为函数
package main

import "fmt"

func main() {
    fmt.Println(printName("张三"))

    // 函数赋值
    name := printName
    fmt.Println(name("李四"))

    // 局部变量
    name1 := func(name string) string {
        return name
    }
    fmt.Println(name1("王五"))
    
    // 函数里面返回函数
    // func(string) string
    name2 := makeNameFunc()
    fmt.Printf("name2的类型为:%T\n", name2)
    fmt.Println(name2("赵六"))
}

// 返回值为函数
// 返回的函数的类型为func(string) string
//函数类型:func() func(string) string
func makeNameFunc() func(string) string {
    return func(name string) string {
        return name
    }
}

func printName(name string) string {
    return name
}

输出为:
张三
李四
王五
name2的类型为:func(string) string
赵六
匿名函数/闭包
varName := func() {...}
    varName() //调用匿名函数
    //匿名函数也可以作为一个返回值赋值给变量
    func func1(m int) func(int) int {
      return func2(n int) int {
        return m + n
      }
    }
    varName := func1(m) //func1(m)返回的结果就是func2函数
    varName(n)//就相当于下面这个函数
    func2(n int) int {
      return m + n//m在func1(m)已确定值
    }

example code list

import "fmt"

func main() {
  //5. 函数作为值/类型
  //匿名函数
  varFunc := testFunc
  varFunc()
  //闭包
  varFunc1 := closure(10)
  fmt.Println(varFunc1(20)); //30
  /**************************/
  /*运行结果:               */
  /*func as a var           */
  /*30                      */
  /**************************/
}

func testFunc() {
  fmt.Println("func as a var")
}

func closure(m int) func(int) int {
  return func(n int) int {
    return m + n
  }
}
回调函数

函数也可以作为另一个函数的参数,即回调函数。回调函数需要调用函数的形参格式和被调用函数原型相同。

package main

import "fmt"

// 函数类型:func ( []int, func ())
// 参数一类型:[]int
// 参数二:func ([]int)
func method(array []int, callback func([]int)) {
    callback(array)
}

func main() {

    a := []int{2, 5, 1, 67, 89}
    callback := func(array []int) {
        fmt.Println(array)
    }
    fmt.Println("========")
    method(a, callback)
}

递归的使用
package main

import "fmt"

// 10的阶乘
// 10*9*8*..*2*1

// 10 * 9*jieceng(8)

func jieceng(num int) int {
    if num == 1 {
        return 1
    }
    return num * jieceng(num-1)
}

func main() {
    num := jieceng(10)
    fmt.Println(num)
}

defer

defer声明的语句会存在类型于栈的结构中,先进后出,在函数快执行完毕(或者return)时执行,类型于析构函数
格式
defer 表达式|函数
常用于文件关闭等操作,还有重要的 recover 函数

package main

import "fmt"

func printWord(s string) {
    fmt.Println(s)
}

func main() {
    defer printWord("World!")
    printWord("Hello!")
    defer printWord("Wecome!")
    printWord("To Beijing!")
    defer printWord("123!")
    printWord("456!")
}

输出为:
Hello!
To Beijing!
456!
123!
Wecome!
World!
上一篇 下一篇

猜你喜欢

热点阅读