1. 程式人生 > 其它 >Go語言學習——匿名函式、閉包

Go語言學習——匿名函式、閉包

匿名函式

匿名函式的定義格式:

func(引數)(返回值){
    函式體
}

沒有名字的函式

package main

import "fmt"

// 匿名函式

// var f1 = func (x, y int)  {
// 	fmt.Println(x + y)

// }

func main(){
	// f1(10, 20)
	// 函式內部沒有辦法宣告帶名字的函式
	// 匿名函式
	f1 := func (x, y int)  {
		fmt.Println(x + y)
	}
	f1(10, 20)

	// 如果只是呼叫一次的函式,還可以簡寫成立即執行函式
	func (x, y int)  {
		fmt.Println(x + y)
		fmt.Println("Hello world")
	} (10, 20)
}

閉包

閉包=函式+引用環境

package main

import "fmt"

// 閉包

func f1(f func()) {
	fmt.Println("this is f1")
	f()
}

func f2(x, y int) {
	fmt.Println("this is f2")
	fmt.Println(x + y)
}

// 定義一個函式對f2進行包裝
func f3() func() {
	tmp := func ()  {
		fmt.Println("Hello")
	}
	return tmp
}

func test(x int) {
	tmp := func ()  {
		fmt.Println(x) // 先在自己這裡面找
	}
	tmp()
}

func test2(x func (int, int), m, n int) {
	tmp := func ()  {
		x (m, n)
	}
	tmp() // x(m, n)
}

func test3(x func(int, int), m, n int) {
	x (m, n)
}

func test4(x func (int, int), m, n int) func() {
	tmp := func ()  {
		x (m, n)
	}
	return tmp
}

func main(){
	test(100)
	test2(f2, 100, 200)
	test3(f2, 100, 200)
	ret := test4(f2, 100, 200)
	ret()
}

一個函式除了用到它內部定義的語句之外還可以引用它外部的變數

package main

import "fmt"

// 閉包

func f1(f func()) {
	fmt.Println("this is f1")
	f()
}

func f2(x, y int) {
	fmt.Println("this is f2")
	fmt.Println(x + y)
}

// 要求:
// f1(f2)
func f3(f func(int, int), x, y int) func() {
	tmp := func ()  {
		// fmt.Println(x + y)
		// f2()
		f(x, y)
	}
	return tmp
}

// 定義一個函式對f2進行包裝
// func f3() func() {
// 	tmp := func ()  {
// 		fmt.Println("Hello")
// 	}
// 	return tmp
// }

// func test(x int) {
// 	tmp := func ()  {
// 		fmt.Println(x) // 先在自己這裡面找
// 	}
// 	tmp()
// }

// func test2(x func (int, int), m, n int) {
// 	tmp := func ()  {
// 		x (m, n)
// 	}
// 	tmp() // x(m, n)
// }

// func test3(x func(int, int), m, n int) {
// 	x (m, n)
// }

// func test4(x func (int, int), m, n int) func() {
// 	tmp := func ()  {
// 		x (m, n)
// 	}
// 	return tmp
// }

func main(){
	// test(100)
	// test2(f2, 100, 200)
	// test3(f2, 100, 200)
	// ret := test4(f2, 100, 200)
	// ret()

	ret := f3(f2, 100, 200) // 把原來需要傳遞兩個int 型別的引數包裝成一個不需要傳參的函式
	fmt.Printf("%T\n", ret)
	f1(ret)
}

閉包 = 函式 + 外部變數的引用

package main

import "fmt"

// 閉包是什麼
// 閉包是一個函式,這個函式包含了它外部作用域的一個變數

// 底層的原理:
// 1. 函式可以作為返回值
// 2. 函式內部查詢變數的順序,先在自己內部找,找不到往外層找

func adder(x int) func(int) int {
	// var x int
	// var x = 100
	return func(y int) int {
		x += y
		return x
	}
}
func main() {
	// ret := adder()
	ret := adder(100)
	ret2 := ret(200)
	fmt.Println(ret2)

	// var f = adder()
	// fmt.Println(f(10)) //10
	// fmt.Println(f(20)) //30
	// fmt.Println(f(30)) //60

	// f1 := adder()
	// fmt.Println(f1(40)) //40
	// fmt.Println(f1(50)) //90
}

閉包例子

package main

import (
	"fmt"
	"strings"
)

// 閉包

func makeSuffixFunc(suffix string) func(string) string {
	return func(name string) string {
		if !strings.HasSuffix(name, suffix) {
			return name + suffix
		}
		return name
	}
}

func main() {
	jpgFunc := makeSuffixFunc(".jpg")
	txtFunc := makeSuffixFunc(".txt")
	fmt.Println(jpgFunc("test")) //test.jpg
	fmt.Println(jpgFunc("test1.jpg")) //test1.jpg
	fmt.Println(txtFunc("test")) //test.txt
	fmt.Println(txtFunc("test2.txt")) //test2.txt
}package main

import (
	"fmt"
	"strings"
)

// 閉包

func makeSuffixFunc(suffix string) func(string) string {
	return func(name string) string {
		if !strings.HasSuffix(name, suffix) {
			return name + suffix
		}
		return name
	}
}

func main() {
	jpgFunc := makeSuffixFunc(".jpg")
	txtFunc := makeSuffixFunc(".txt")
	fmt.Println(jpgFunc("test")) //test.jpg
	fmt.Println(jpgFunc("test1.jpg")) //test1.jpg
	fmt.Println(txtFunc("test")) //test.txt
	fmt.Println(txtFunc("test2.txt")) //test2.txt
}

閉包=函式+引用環境

package main

import "fmt"

// 關鍵字 函式名(引數)(返回值){}
func calc(base int) (func(int) int, func(int) int) {
	add := func(i int) int {
		base += i
		return base
	}

	sub := func(i int) int {
		base -= i
		return base
	}
	return add, sub
}

func main() {
	f1, f2 := calc(10)
	// 修改的是同一個base
	fmt.Println(f1(1), f2(2)) //11 9
	fmt.Println(f1(3), f2(4)) //12 8
	fmt.Println(f1(5), f2(6)) //13 7
}