go_day3 汉字回文_函数_defer_闭包

map的遍历和判断键是否存在

package main

import (
	"fmt"
	"strings"
)

func main() {
	// 统计how do you do 单词的出现次数
	s1 := "how do you do"
	sl1 := strings.Split(s1, " ")
	m1 := make(map[string]int, 10)
	for _, w := range sl1 {
		// fmt.Println(w)
		// 判断map中的键是否存在
		if _, ok := m1[w]; !ok {
			m1[w] = 1
		} else {
			m1[w] += 1
		}
	}
	for key, value := range m1 {
		fmt.Printf("%v %v\n", key, value)
	}
	// fmt.Println(m1)
}

判断字符串回文

package main

import (
	"fmt"
)

func main() {
	// 回文判断
	ss := "上海自来水来自海上"
	// 注意这里字符串汉字为rune类型,需要将字符串转成rune类型的切片来做
	// 下面的方法有误,无法判断,一个rune占了3位
	// for i := range ss {
	// 	if ss[i] != ss[len(ss)-1-i] {
	// 		fmt.Println(i, len(ss)-1-i)
	// 		fmt.Println("no")
	// 		return
	// 	}
	// }
	// fmt.Println("yes")
	fmt.Println(len(ss)) // 27
	r := make([]rune, 0, len(ss))
	for _, c := range ss {
		r = append(r, c)
	}
	for i := 0; i < len(r)/2; i++ {
		if r[i] != r[len(r)-1-i] {
			fmt.Println("不是回文")
			return
		}
	}
	fmt.Println("是回文")
}

注意汉字字符串的占位

函数#

几种命名函数的定义方法

基本格式#

参数的格式#

有参数的函数
参数类型简写
可变参数

返回值的格式#

有返回值
多返回值
命名返回值

package main

import "fmt"

// 函数
// 不允许命名函数的套娃声明,例如在main函数里再声明一个命名函数
// 不传参
func f1() {
	fmt.Println("hello")
}

// 传参
func f2(name string) {
	fmt.Println("hello", name)
}

// 传参+说明返回值类型
func f3(x int, y int) int {
	sum := x + y
	return sum
}

// 传参类型简写
func f4(x, y int) int {
	return x + y
}

// 可变参数
func f5(x string, y ...int) int {
	// y是一个int类型的切片
	fmt.Println(y)
	return 1
}

// 命名返回值
func f6(x, y int) (sum int) {
	// 如果使用命名的返回值,那么可以在函数中直接使用返回值变量
	sum = x + y
	// 如果使用命名的返回值,那么return 可以省略返回值变量
	return
}

// go 语言支持多个返回值
func f7(x, y int) (sum, sub int) {
	sum = x + y
	sub = x - y
	return
}
func main() {
	f1()
	f2("夜刀神")
	ret := f3(100, 200)
	fmt.Println(ret)
	fmt.Println(f4(100, 200))
	f5("yds", 1, 2, 3, 4, 5, 6, 7)
	fmt.Println(f6(100, 200))
	// sum, sub := f7(100, 200)
	// fmt.Println(sum, sub)
	fmt.Println(f7(100, 200))
}

defer
defer多用于函数结束之前释放资源(文件句柄、数据库连接)

package main

import "fmt"

func deferDemo() {
	fmt.Println("start")
	// defer把它后面的语句延迟到函数即将返回的时候再执行
	// 一个函数可以有多个defer语句,多个defer语句按照先进后出的顺序延迟执行,相当于是个栈
	defer fmt.Println("ydssx")
	defer fmt.Println("520")
	fmt.Println("end")
	/*start
	  end
	  520
	  ydssx
	*/
}
func main() {
	deferDemo()
}

defer的执行时机
image
return不是原子操作,先返回值赋值,再执行真正的RET指令。defer运行在两者之间

package main

import "fmt"

func f1() int {
	x := 5
	defer func() {
		x++ //修改的是x不是返回值
	}()
	return x //5
}

func f2() (x int) {
	defer func() {
		x++
	}()
	return 5 //返回值=x=6
}

func f3() (y int) {
	x := 5
	defer func() {
		x++ // 修改的是x
	}()
	return x // 返回值 = y = x= 5
}
func f4() (x int) {
	defer func(x int) {
		x++ // 改变的是函数的副本
	}(x)
	return 5 // 返回值 = x= 5
}
func main() {
	fmt.Println(f1())
	fmt.Println(f2())
	fmt.Println(f3())
	fmt.Println(f4())
}

函数也有类型,函数类型
func()
func() int
func(int,int) int
注意函数的返回类别和参数不同就是不同的函数类型

package main

import "fmt"

func f2() int {
	return 10
}
func f3(x func() int) {
	ret := x()
	fmt.Println(ret)
}
func main() {
	f3(f2)
}

所以函数既可以作为函数传入参数,又可以作为返回值

匿名函数:没有名字的函数
如果只是调用一次的函数,还可以简写成立即执行函数

package main

import "fmt"

func main() {
	f1 := func(x, y int) {
		fmt.Println(x + y)
	}
	f1(10, 20)
	// 没参数的立即执行函数
	func() {
		fmt.Println("hello")
	}()
	// 带参数的立即执行函数
	func(x, y int) {
		fmt.Println(x + y)
	}(10, 20)
}

闭包#

闭包是一个函数,这个函数包含了他外部作用域的一个变量
闭包的底层原理
1.函数可以作为返回值
2.函数内部查找变量的顺序,先在自己内部找,再在外部找

package main

import "fmt"

func adder(x int) func(int) int {
	return func(y int) int {
		x += y
		return x
	}
}

// 闭包 = 函数 + 外部变量的引用
func main() {
	ret := adder(100)
	fmt.Println(ret(200))
}
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)
// f1是不可修改,希望在f1中执行f2
func f3(x, y int) func() {
	tmp := func() {
		fmt.Println(x + y)
	}
	return tmp
}

//怎么用上f2?在f3中传入f2
// 等于就是不直接将x,y输入func2,而是通过一个函数中的匿名函数包装一下
func f4(f func(int, int), x, y int) func() {
	tmp := func() {
		f(x, y)
	}
	return tmp
}
func main() {
	// f1(f3(100, 200))
	// f1(f4(f2, 100, 200))
	ret := f4(f2,100,200)
	f1(ret)
}

就是多了个参数的函数套函数

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)
	fmt.Println(f1(1), f2(2)) //11 9
	fmt.Println(f1(3), f2(4)) //12 8
	fmt.Println(f1(5), f2(6)) //13 7
}

image
所以上面例子中base一直有效

作者:ydssx7

出处:https://www.cnblogs.com/ydssx7/p/15837570.html

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @   ydssx  阅读(26)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
more_horiz
keyboard_arrow_up dark_mode palette
选择主题
menu
点击右上角即可分享
微信分享提示