56.笔记go语言——go的函数类型

56.笔记go语言——go的函数类型

                  对于动态脚本语言Ruby,JavaScript,Python都有higher-order函数。但是很难直接转换成G知识,虽然GO看上去是同样方式获取。另一方面,之前从事静态语言特别是面向对象语言例如C++,JAVA的,那么问题是使用higher-order函数很少。

                  很难直接从之前编程中直接跨越过来,所以蛤蟆也是需要学习,那么和蛤蟆一起开始吧。

匿名函数闭包

                  Go语言支持匿名函数和闭包。

在GO中定义一个匿名函数非常简单

func() {

    fmt.Println("hello")

}

                  不过这个很少用,通常是保存到一个变量中,订到数据结构中,或传递到其他函数。

                  通常常见的如下代码:

fn :=func() {

    fmt.Println("hello")

}

                  这样fn变量就是一个函数了,类型是func().当调用fn()的时候就会激活函数,或赋值给其他感兴趣的函数。当然,因为有闭包,可以引用在函数范围中的一些数据。如下:

x := 5

fn :=func() {

    fmt.Println("x is", x)

}

fn()

x++

fn()

输出

X is 5

X is 6       

函数收集

                  在使用数据类型的地方都可以使用函数,例如,可以创建slice函数组,随机选择函数并执行。定义一个binFunc二进制函数,使用2个整型,返回一个整型。那么可以使用binFunc来替换func(int,int)int了。

                  代码如下:

packagemain
 
import"math/rand"
import"time"
import"fmt"
 
typebinFuncfunc(int,int)int
 
funcmain(){
    //seedyourrandomnumbergenerator.
    rand.Seed(time.Now().Unix())
 
    //createasliceoffunctions
    fns:=[]binFunc{
        func(x,yint)int{returnx+y},
        func(x,yint)int{returnx-y},
        func(x,yint)int{returnx*y},
        func(x,yint)int{returnx/y},
        func(x,yint)int{returnx%y},
    }
 
    //pickoneofthosefunctionsatrandom
    fn:=fns[rand.Intn(len(fns))]
 
    //andexecuteit
    x,y:=12,5
    fmt.Println(fn(x,y))
}

执行结果:

17

当然是随机了。

函数作为域

                  通常,使用函数类型作为一个结构中的域。这样可以让我们给函数附加一些信息,例如标签等。

如下代码:

packagemain
 
import"math/rand"
import"time"
import"fmt"
 
typeopstruct{
    namestring
    fn   func(int,int)int
}
 
funcmain(){
    //seedyourrandomnumbergenerator
    rand.Seed(time.Now().Unix())
 
    //createasliceofops
    ops:=[]op{
        {"add",func(x,yint)int{returnx+y}},
        {"sub",func(x,yint)int{returnx-y}},
        {"mul",func(x,yint)int{returnx*y}},
        {"div",func(x,yint)int{returnx/y}},
        {"mod",func(x,yint)int{returnx%y}},
    }
 
    //pickoneofthoseopsatrandom
    o:=ops[rand.Intn(len(ops))]
 
    x,y:=12,5
    fmt.Println(o.name,x,y)
    fmt.Println(o.fn(x,y))
}

执行如下:

add 12 5

17

此外,函数还可以被存储在maps中。

递归函数类型

                  另一个有意思的函数类型是允许定义递归函数类型。将自己类型作为参数或者使用自己的类型作为返回值。

例如递归函数:

typewalkFn func(*int) walkFn

合法的walkFn可以如下walkEqual函数

func walkEqual(i*int) walkFn {

    *i += rand.Intn(7) - 3

    return walkEqual

}

函数返回一个随机值并-3,然后返回本身。

函数作为接口值

                  GO语言中的函数类型也可以有方法。很少见。

                  任何有方法的类型都可以满足接口,所以函数类型可以来合法化接口类型。

                  GO中方法可以有指针或值接收。

                  PS:任何有Error() string方法的都是合法的error类型,函数可以作为或和error.

代码如下:

packagemain
 
import"fmt"
 
typebinFuncfunc(int,int)int
 
funcadd(x,yint)int{
    returnx+y
}
 
func(fbinFunc)Error()string{
    return"binFuncerror"
}
 
funcmain(){
    varerrerror
    err=binFunc(add)
    fmt.Println(err)
}

在这个例子中,将add函数从func(int,int) int转换为binFunc。

                  然后实现func(int,int) int的error.

再定义如下:

type loudBinFunc func(int, int) int
 
func (f loudBinFunc) Error() string {
    return "THIS ERROR IS A LOT LOUDER"
}

                  定义类型loudBinFunc,然后实现Error()函数。如果同时有 binFunc  loudBinFunc,那么go就不知道如何转换add函数了。一开始可能会反感,但是其实会让我们避免代码BUG。

      在标准库net/http包中,可以看到使用函数类型来满足接口的例子。

作为Channel的函数

                  使用Channels来合并函数类型。

                  定义channel类型如下:

chan func()

                  创建函数组成的slice如下:

x := 10
fns := []func(){
    func() { x += 1 },
    func() { x -= 1 },
    func() { x *= 2 },
    func() { x /= 2 },
    func() { x *= x },
}

在定义一个函数来随机获取,如下:

func pickFunc(fns ...func()) func() {
    return fns[rand.Intn(len(fns))]
}

然后创建函数的channel.

c := make(chan func())

在定义一个函数,将CHANNEL,数量描述,函数集作为参数,如下:

func produce(c chan func(), n int, fns ...func()) {
    defer close(c)
    for i := 0; i < n; i++ {
        c <- pickFunc(fns...)
    }
}

在函数开始处,使用了deferclose( c)来确保channel能得到关闭。

何在一起代码如下:

package main
 
import (
    "fmt"
    "math/rand"
    "time"
)
 
var delay = 200 * time.Millisecond
 
func pickFunc(fns ...func()) func() {
    return fns[rand.Intn(len(fns))]
}
 
func produce(c chan func(), n int, fns ...func()) {
    defer close(c)
    for i := 0; i < n; i++ {
        c <- pickFunc(fns...)
    }
}
 
func main() {
    // time is frozen on Playground, so this is always the same.
    rand.Seed(time.Now().Unix())
 
    x := 10
    fns := []func(){
        func() { x += 1 },
        func() { x -= 1 },
        func() { x *= 2 },
        func() { x /= 2 },
        func() { x *= x },
    }
 
    c := make(chan func())
    go produce(c, 10, fns...)
 
    for fn := range c {
        fn()
        fmt.Println(x)
        time.Sleep(delay)
    }
}

执行输出如下:

20

10

20

40

1600

3200

3201

6402

40985604

81971208

友情链接

http://jordanorelli.com/post/42369331748/function-types-in-go-golang

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Go语言学习笔记.pdf》是一本关于Go语言学习的学习笔记,内容丰富且简洁明了。本书从基础知识开始,逐步介绍了Go语言的语法、特性和常用库函数等。在学习笔记中,作者通过实际的示例和练习帮助读者理解Go语言的概念和用法。 第一章介绍了Go语言的起源和发展,为读者提供了对Go语言背景的整体了解。第二章讲解了Go语言的基本语法,例如变量声明、循环和条件语句等。通过大量的代码示例,读者能够更好地理解Go语言的语法和结构。 接下来的章节重点介绍了Go语言的并发编程和高级特性。第三章详细介绍了Go语言中的goroutine和channel,这是Go语言并发编程的核心机制。作者通过生动的示例代码和实际应用案例,向读者展示了如何使用goroutine和channel实现并发编程。 第四章和第五章分别介绍了Go语言中的面向对象编程和函数式编程。通过深入讲解Go语言中的结构体、接口和函数,读者能够更好地应用这些特性进行代码设计和开发。 最后几章则介绍了Go语言中常用的库函数和工具。例如,第六章介绍了Go语言中用于网络编程的net包和http包。读者可以学习到如何使用这些库函数构建基于网络的应用程序。 总的来说,《Go语言学习笔记.pdf》是一本非常实用的Go语言学习资料。通过阅读这本书,读者能够系统地学习和理解Go语言的基本概念和高级特性,为之后的Go语言开发打下坚实的基础。无论是初学者还是有一定编程经验的开发者,都能从中获得丰富的知识和经验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值