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的执行时机
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
}
作者:ydssx7
出处:https://www.cnblogs.com/ydssx7/p/15837570.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?