GO语言学习笔记:第七章 函数式编程

0x00 函数与闭包

函数是一等公民:即参数,变量,返回值都可以是函数

"正统的"函数式编程:

不可变性:不能有变量,只有常量和函数

函数只能有一个参数

因为go语言是一个通用的语言,所以不完全按照”正统“的函数式编程进行

 

闭包的底层原理:

package main

import "fmt"

func adder() func(int) int {
	sum := 0
	return func(v int) int {
		sum += v
		return sum
	}
}

func main() {
	a := adder()
	for i := 0; i < 10; i++ {
		fmt.Printf("0+1+...+%d=%d\n", i, a(i))
	}
}

执行结果:

因为函数adder返回的函数中调用了”自由变量“sum, 所以adder 函数返回的并不只是函数地址,而是

首先会在内存的堆中存储这些自由变量,然后在堆中创建一个结构体,把这些变量的地址和函数的地址打个包存起来

最后,将该结构体在堆中的地址打包返回。

正因如此,我们在执行反复执行a() 的时候 sum的值会累加。

更加详细的解释:https://zhuanlan.zhihu.com/p/56750616

0x01 闭包的应用

1.斐波那契数列:

package main

import "fmt"

func fibanacci() func() int {
	a, b := 0, 1
	return func() int {
		a, b = b, a+b
		return a
	}
}
func main() {
	f := fibanacci()
	fmt.Println(f())
	fmt.Println(f())
	fmt.Println(f())
	fmt.Println(f())
	fmt.Println(f())
	fmt.Println(f())
}

2.逐行读取文件 之 再深入

通过阅读源码我的总结如下:

    func printFile(filename string) {
    	file, err := os.Open(filename)
    	if err != nil {
    		panic(err)
    	}
        //file 具有一个Read方法 NewScanner 的作用其实就是将 file 和 其他相关信息 封装到一个 scanner结构体中,然后把该结构体的地址返回
    	scanner := bufio.NewScanner(file) 
        //scanner.Scan() 这个方法其实是在调用 file.Read() 方法
    	for scanner.Scan() {
    		fmt.Println(scanner.Text()) //scanner.Text() 方法只有一行代码,并不执行读相关的操作,只是将scanner.Scan()读到的信息转化为字符串
    	}
    }
     
    func forever() {
    	for {
    		fmt.Println("forever")
    	}
    }

 

因为io.Reader就是一个鸭子类型,所以我们完全可以自己写一个 io.Reader类型的东西  给NewScanner传进去

/*
 * @Author: your name
 * @Date: 2020-11-03 22:02:35
 * @LastEditTime: 2020-11-03 23:55:52
 * @LastEditors: Please set LastEditors
 * @Description: In User Settings Edit
 * @FilePath: /learngo/functional/fibanacc/fibanacci.go
 */
package main

import (
	"bufio"
	"fmt"
	"io"
	"strings"
)

type intGen func() int

func fibanacci() intGen {
	a, b := 0, 1
	return func() int {
		a, b = b, a+b
		return a
	}
}

//因为函数是一等公民,
//给这个函数添加一个成员函数 Read ,
//让它符合 io.Reader 这个interface的要求
func (g intGen) Read(p []byte) (n int, err error) {
	next := g()
	if next > 10000 {
		return 0, io.EOF
	}
	s := fmt.Sprintf("%d\n", next)

	reader := strings.NewReader(s) //创建一个从s读取数据的reader
	return reader.Read(p)          //从s读取数据存到p中,返回读取到的字符串的长度
}

//io.Reader io包中定义的一个鸭子类型,要求必须有成员函数Read
func printFileContents(reader io.Reader) {
	scanner := bufio.NewScanner(reader) //返回一个Scanner
	//sanner.Scan()本质上在反复调用 reader.Read()
	for scanner.Scan() {
		fmt.Println(scanner.Text())
	}
}
func main() {
	f := fibanacci()
	printFileContents(f)
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值