首页 » Go » 正文

Go 语言集训(二)

闭包

Go的匿名函数是一个闭包
* 基本概念
闭包是可以包含自由(为绑定到特定对象)变量的代码块,这些变量不在这个代码块内或者任何全局上下文中定义,而是在定义代码块的环境中定义。要执行的代码块(由于自由变量包含在代码块中,所以这些自由变量以及他们引用的对象没有被释放)为自由变量提供绑定的计算环境(作用域)
* 闭包的价值
闭包的机制在于可以作为函数对象或者匿名函数,对于类型系统而言,这意味着不仅要标识数据还要表示代码。支持闭包的多数语言都将函数作为第一级对象,这就是说这些函数可以存储到变量中作为参数传递给其他函数,最重要的是能够被函数动态创建和返回
* Go语言中的闭包
GO语言中的闭包同样也会引用到函数外的变量。闭包的实现确保只要闭包还被使用,那么被闭包引用的变量会一直存在。

package main

import "fmt"

func main() {
    var j int = 5
    a := func() func() {
        var i int = 10
        return func() {
            fmt.Printf("i,j: %d,%d\n", i, j)
        }
    }()
    a()
    j *= 2
    a()
    fmt.Println("闭包另外尝试")
    i := incr()
    fmt.Println(i())      //1
    fmt.Println(i())      //2
    fmt.Println(i())      //3
    fmt.Println(incr()()) //1 incr()返回一个func() int ;所以还需要incr()()l对 func()int进行执行
    fmt.Println(incr()()) //1

}

func incr() func() int { // func() int 作为 func的返回值
    var x int
    return func() int {  //这是返回的指针函数
        x++
        return x
    }
}

对于Map的 函数的使用

package main

import "fmt"

func f(p string) {
    fmt.Println("function f parameter:", p)
}

func g(p string, q int) {
    fmt.Println("function g parameters:", p, q)
}

func main() {
    m := map[string]interface{}{//使用interface更加安全,可以匹配不同的接口。
        "f": f,
        "g": g,
    }
    for k, v := range m {
        switch k {
        case "f":
            v.(func(string))("astring")
        case "g":
            v.(func(string, int))("astring", 42)
        }
    }
}

排序的案例

.
├── algorithms
│   ├── bubblesort
│   │   ├── bubblesort.go
│   │   └── buddlesort_test.go
│   └── qsort
│   ├── qsort.go
│   └── qsort_test.go
├── input.data
├── output.data
└── sorter.go

sourter.go

// sorter.go
package main

import "flag"
import "fmt"
import "io"
import "bufio"
import "os"
import "strconv"
import "time"

import "algorithms/bubblesort"
import "algorithms/qsort"

var infile *string = flag.String("i", "infile", "File contains values for sorting")
var outfile *string = flag.String("o", "outfile", "File to receive sorted values")
var algorithm *string = flag.String("a", "qsort", "Sort algorithm")

func main() {
    flag.Parse()

    if infile != nil {
        fmt.Println("inflie =", *infile, "outfile =", *outfile, "algortihm =", *algorithm)
    }
    values, err := readValues(*infile)
    if err == nil {
        t1 := time.Now()
        switch *algorithm {
        case "qsort":
            qsort.QuickSort(values)
        case "bubblesort":
            bubblesort.BubbleSort(values)
        default:
            fmt.Print("sorting algortim", *algorithm, "is either unkonw or unsported")
        }
        t2 := time.Now()
        fmt.Println("The sorting process costs", t2.Sub(t1), "to complete")
        writeValues(values, *outfile)
    } else {
        fmt.Println(err)
    }
}

func writeValues(value []int, outfile string) error {
    file, err := os.Create(outfile)
    if err != nil {
        fmt.Println("Failed to create the output file ", outfile)
        return err
    }

    defer file.Close()
    for _, value := range value {
        str := strconv.Itoa(value)
        file.WriteString(str + "\n")
    }
    return nil
}

func readValues(infile string) (values []int, err error) {
    file, err := os.Open(infile)
    if err != nil {
        fmt.Println("failed to open the input file ", infile)
        return
    }
    defer file.Close()

    br := bufio.NewReader(file)
    values = make([]int, 0)

    for {
        line, isPrefix, err1 := br.ReadLine()

        if err1 != nil {
            if err1 != io.EOF {
                err = err1
            }
            break
        }
        if isPrefix {
            fmt.Println("A too long line, seems unexpted")
            return
        }

        str := string(line) //转换字符数组为字符串

        value, err1 := strconv.Atoi(str)
        fmt.Println(err1)
        if err1 != nil {
            err = err1
            return
        }
        values = append(values, value)
    }
    return
}

sqort.go

package qsort

func quicSort(values []int, left, right int) {
    temp := values[left]
    p := left
    i, j := left, right
    for i <= j {
        for j >= p && values[j] >= temp {
            j--
        }
        if j >= p {
            values[p] = values[j]
            p = j
        }
        if values[i] <= temp && i <= p {
            i++
        }
        if i <= p {
            values[p] = values[i]
            p = i
        }
    }
    values[p] = temp
    if p-left > 1 {
        quicSort(values, left, p-1)
    }
    if right-p > 1 {
        quicSort(values, p+1, right)
    }
}

func QuickSort(values []int) {
    quicSort(values, 0, len(values)-1)
}

bubblesort.go

package bubblesort

func BubbleSort(values []int) {
    flag := true
    for i := 0; i < len(values)-1; i++ {
        flag = true
        for j := 0; j < len(values)-i-1; j++ { //存在交换就把flag变为false,没有的话,则说明排序完成
            if values[j] > values[j+1] {
                values[j], values[j+1] = values[j+1], values[j]
                flag = false
            }
        }
        if flag == true {
            break
        }
    }
}

bubblesort_test.go

package bubblesort

import "testing"

func TestBuddleSort1(t *testing.T) {
    values := []int{5, 4, 3, 2, 1}
    BubbleSort(values)
    if values[0] != 1 || values[2] != 3 || values[3] != 4 || values[4] != 5 {
        t.Error("BubbleSort() failed. Got", values, "exptected 1 2 3 4 5")
    }
}

func TestBuddleSort2(t *testing.T) {
    values := []int{5, 5, 3, 2, 1}
    BubbleSort(values)
    if values[0] != 1 || values[2] != 3 || values[3] != 5 || values[4] != 5 {
        t.Error("BubbleSort() failed. Got", values, "exptected 1 2 3 5 5")
    }
}

func TestBuddleSort3(t *testing.T) {
    values := []int{5}
    BubbleSort(values)
    if values[0] != 5 {
        t.Error("BubbleSort() failed. Got", values, "exptected 5")
    }
}

qsort_testing.go

package qsort

import "testing"

func TestQsort1(t *testing.T) {
    values := []int{5, 4, 3, 2, 1}
    QuickSort(values)
    if values[0] != 1 || values[2] != 3 || values[3] != 4 || values[4] != 5 {
        t.Error("QuickSort() failed. Got", values, "exptected 1 2 3 4 5")
    }
}