[golang note] 函数定义

普通函数定义


       golang函数基本组成:关键字func函数名参数列表返回值函数体返回语句

• 语法如下

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

• 示例如下

package main

import "fmt"
import "errors"

func Add(a int, b int) (ret int, err error) {
    if a < 0 || b < 0 { // 假定只支持两个非负数字的加法
        err = errors.New("Should be non-negative numbers!")
        return
    }
    return a + b, nil
}

func main() {
    fmt.Println(Add(-1, 1))
    fmt.Println(Add(10, 1))
}

• 注意事项

       ▪ golang函数支持多返回值,返回时没有被明确赋值的返回值将被设置为默认值

       ▪ golang函数返回值可以命名,但不是强制规则,给返回值命名可以让让代码更清晰,可读性更强,同时也可以用于文档。

       ▪ golang函数定义中左花括号的位置被强制规范,如果左花括号放置不规范,golang编译器报告编译错误:syntax error: unexpected semicolon or newline before {。

       ▪ golang函数定义中如果参数列表中若干个相邻参数的类型相同,则可以在参数列表中省略前面的变量类型声明。

func Add(a, b int) (ret int, err error) {
    // 函数体
}

       ▪ golang函数定义中如果返回值列表中若干个相邻返回值的类型相同,则可以在返回值列表中省略前面的变量类型声明。

func Add(a, b int) (ret, err int) {
    // 函数体
}

       ▪ golang函数定义中如果返回值只有一个,那么返回值列表可以简略表示。

func Add(a, b int) int {
    // 函数体
}

固定类型的不定参数函数定义


• 语法如下

func 函数名(args ...Type) (返回值列表) {
    // 函数体
}

       形如args ...Type的用法只能作为函数的参数类型,并且必须是最后一个参数

       形如args ...Type的用法是一个语法糖(syntactic sugar),即对语言功能没有影响,但可以增加程序的可读性。

       形如args ...Type的用法从内部实现上说,其本质上是一个数组切片,即[]type,因此可以用for循环来获得每个传入的参数。

• 示例如下

package main

import "fmt"

func myfunc(prefix string, args ...int) {
    fmt.Print(prefix, " : ")

    for _, arg := range args {
        fmt.Print(arg, " ")
    }

    fmt.Println()
}

func main() {
    myfunc("data1", 1, 2, 3, 4)
    myfunc("data2", 4, 3, 2, 1, 0)
}

• 不定参数函数互相调用

▶ 原样传递

▪ 语法如下

func myfunc1(args ...Type) {
    // 函数体
}

func myfunc2(args ...Type) {
    ...
    myfunc1(args...)
    ...
}

▪ 示例如下

package main

import "fmt"

func myfunc1(args ...int) {
    fmt.Println("myfunc1() invoked")

    for _, arg := range args {
        fmt.Print(arg, " ")
    }

    fmt.Println()
}

func myfunc2(args ...int) {
    fmt.Println("myfunc2() invoked")
    myfunc1(args...)
}

func main() {
    myfunc2(1, 2, 3, 4)
}

▶ 片段传递

▪ 语法如下

func myfunc1(args ...Type) {
    // 函数体
}

func myfunc2(args ...Type) {
    ...
    myfunc1(args[m:n]...)
    ...
}

▪ 示例如下

package main

import "fmt"

func myfunc1(args ...int) {
    fmt.Println("myfunc1() invoked")

    for _, arg := range args {
        fmt.Print(arg, " ")
    }

    fmt.Println()
}

func myfunc2(args ...int) {
    fmt.Println("myfunc2() invoked")
    myfunc1(args[2:3]...)
}

func main() {
    myfunc2(1, 2, 3, 4)
}

任意类型的不定参数函数定义


• 语法如下

func 函数名(args ...interface{}) (返回值列表) {
    // 函数体
}

       形如args ...interface{}的用法只能作为函数的参数类型,并且必须是最后一个参数。

• 示例如下

package main

import "fmt"

func MyPrintf(info string, args ...interface{}) {
    fmt.Println(info)
    for _, arg := range args {
        switch arg.(type) {
        case int:
            fmt.Println(arg, "is an int value.")
        case string:
            fmt.Println(arg, "is a string value.")
        case int64:
            fmt.Println(arg, "is an int64 value.")
        default:
            fmt.Println(arg, "is an unknown type.")
        }
    }
}

func main() {
    var v1 int = 1
    var v2 int64 = 234
    var v3 string = "hello"
    var v4 float32 = 1.234

    MyPrintf("MyPrintf", v1, v2, v3, v4)
}

匿名函数与闭包


• 匿名函数

        匿名函数是指不需要定义函数名的一种函数实现方式,函数可以像普通变量一样被传递或使用。

▶ 匿名函数赋值给变量

▪ 语法如下

f := func(参数列表) (返回值列表) {
    // 函数体
}

▪ 示例如下

package main

import "fmt"

func main() {
    f := func(x, y int) int {
        return x + y
    }

    fmt.Println("Result =", f(1, 2))
}

▶ 匿名函数直接调用

▪ 语法如下

        匿名函数定义的花括号后直接跟参数列表表示函数调用。

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

▪ 示例如下

package main

import "fmt"

func main() {
    fmt.Println("Result =",
        func(x, y int) int {
            return x + y
        }(1, 2))
}

• 闭包

▶ 闭包概念

        闭包是可以包含自由变量(未绑定到特定对象)的代码块。这些自由变量不在该代码块内或任何全局上下文中定义,而是在定义代码块的环境中定义。要执行的代码块为自由变量提供绑定的计算环境,即作用域。

        自由变量包含在代码块中,这些自由变量以及其引用的对象将不被释放。闭包的实现确保只要闭包还被使用,那么被闭包引用的变量会一直存在。

        golang的匿名函数就是一个闭包,闭包函数可以存储到变量中作为参数传递给其他函数,最重要的是能够被函数动态创建和返回。

        自由变量的值将被隔离,在闭包外不可修改,只有内部匿名函数才能访问,而无法通过其他途径访问,因此确保了变量的安全性。

▶ 闭包使用

▪ 语法如下

c := func() func(参数类型列表) 返回值类型列表 {
    // 自由变量定义
...
return func(参数列表) 返回值列表 { // 函数定义 } }()

▪ 示例如下

package main

import (
    "fmt"
)

func main() {
    result := 0

    // 闭包定义
    c := func() func(int) int {
        i := 0
        return func(j int) int {
            i += 10
            fmt.Printf("i = %d, j = %d\n", i, j)
            return i + j
        }
    }()

    result = c(10)
    fmt.Printf("i + j= %d\n", result)

    result = c(20)
    fmt.Printf("i + j= %d\n", result)

    result = c(30)
    fmt.Printf("i + j= %d\n", result)
}

main函数


        main函数是golang可执行程序的执行起点。

        main函数不能带有参数,命令行传入的参数在os.Args变量中保存。

package main

import (
    "fmt"
    "os"
)

func main() {
    for i, v := range os.Args {
        fmt.Printf("os.Args[%d] = %s\n", i, v)
    }
}

 

posted @ 2016-03-02 12:10  碎语心弦  阅读(2230)  评论(0编辑  收藏  举报