登 录
注 册
< 编程语言
Python
Java
Go
SQL
数据结构与算法
Go语言介绍及安装
Go常见语法及简单Demo
Go数据类型
Go函数与方法
热门推荐>>>
中台架构
中台建设与架构
Hadoop
源码分析-NN启动(三)
HBase
HBased对接Hive
Linux
Nginx高可用
Python
数据导出工具
Flink
3分钟搭建Flink SQL测试环境
Kafka
Kafka对接Flume
深度学习
卷积神经网络
数据结构与算法
选择合适的算法
MySQL
数据备份恢复
计算机系统
信号量同步线程
Hive
Hive调优参数大全
其他框架
Azkaban Flow1.0与2.0
ClickHouse
表引擎-其他类型
技术成长
最好的职业建议
精选书单
技术成长书单—机器学习
技术资讯
数据在线:计算将成为公共服务
开发工具
IntelliJ IDEA 20年发展回顾(二)
系统工具
Mac命令行工具
虚拟化
内存虚拟化概述
云原生
云原生构建现代化应用
云服务
一文搞懂公有云、私有云...
Java
Spring Boot依赖注入与Runners
SQL
SQL模板
安全常识
一文读懂SSO
当前位置:
首页
>>
Go
>>
Go函数与方法
Go函数与方法
2023-09-10 18:56:20 星期日 发表于北京 阅读:726
![](/static/images/article_images/1694343086.7132502.jpeg) 函数是基本的代码块,用于执行一个任务,Go 语言标准库提供了多种可动用的内置的函数 #### 函数 ##### go语言函数的特性 >递归:突破递归深度的限制(其他语言的递归深度调用栈在64KB-2MB之间,而GO是1GB左右) 匿名函数 错误处理等 函数签名(函数类型),两个函数拥有相同的形参列表和返回列表则签名相同。 没有默认参数的概念 不能指定参数名字 函数类型的零值是nil(空值),调用一个空的函数变量将导致宕机 考虑下面的一个函数 ``` func MyFunction(a int, b string) (aa int, bb string) { c := a * 100 d := b + "my email is libins810@gmail.com" return c, d } // main函数调用时 c, d := MyFunction(100, "hello") ``` 参数列表a,b时形参 第8行调用函数时传入的100和hello是实参 ##### 错误与异常 >错误:使用普通的值来报告错误(if 和return语句) 异常:只针对程序bug导致的预料外的错误 ##### 错误处理策略 >使用fmt.Errorf或者fmt.Sprintf函数自定义格式化一条错误消息并返回。 对于某些错误可在短暂间隔后对操作进行重试,如果达到一定的次数再报错退出。 调用者输出错误后优雅的停止程序os.Exit(1) 通过调用log.Fatalf()将时间和日期作为前缀加到错误消息前 使用log包只记录错误信息,程序继续运行。如:log.Printf() 某些情况下直接安全地忽略掉整个错误 文件结束标识io.EOF #### 匿名函数 考虑到如下的闭包代码 ``` func squares() func() int { var x int return func() int { x += 1 return x * x } } ``` 内层函数(匿名)使用外层函数的变量x。现在我们创建一个变量来接收外层函数的返回值(匿名函数) ``` func main() { f := squares() fmt.Println(f()) // 输出1 fmt.Println(f()) // 输出4 fmt.Println(f()) // 输出9 fmt.Println(f()) // 输出16 fmt.Println(f()) // 输出25 } ``` 这体现了变量的生命周期不是由它的作用域决定的。 #### 变长函数 其实就是被调用的时候可以有可变的参数个数。比如fmt.Printf函数。自定义一个变长函数实例如下。 ``` func MySum(base int, values ...int) int { for _, value := range values { base += value } return base } ``` 调用该函数的方法有两种 ``` // 第一种:直接传入多个参数 data := MySum(20,1, 3, 5, 6, 9) // base=20 // 第二种:传入slice类型 var s = []int{1, 3, 5, 6, 9} data := MySum(20, s...) ``` #### 延迟函数调用 defer语句的使用场景,类似于Python中的with语句 >文件打开和关闭 连接和断开 加锁和解锁等 调试复杂的函数(在函数入口和出口设置调试行为) 延迟函数不到外层函数的最后一刻是不会执行的 当一个程序发生宕机时,所有的延迟函数倒序执行,也就是从最里层执行到最外层(从栈最上面的函数开始一直返回至main函数) 正确使用defer语句的地方是在成功获得资源后。比如下面的实例展示了如何关闭一个打开的文件 ``` func ReadFile(filename string) ([]byte, error) { f, err := os.Open(filename) if err != nil { return nil, err } defer f.Close() /* 这个位置还可以对f进行操作,不必担心close问题,操作完后会自动close ... ...*/ return ioutil.ReadAll(f) } ``` #### 方法(面向对象) >方法是某种特定类型的函数 go可以将方法绑定到任何类型上 每个类型都有自己的命名空间,所以不同的结构体(包括一般的类型,像int/string等)可以使用相同的方法名 使用方法的好处 命名可以比函数更简短,在使用外部包的时候可以省略包名字来调用该方法 ##### 声明方法与函数 ``` // 首先声明一个结构体 type Point struct { X int Y int } // 普通函数的声明 func sum(a, b Point) (cx int, cy int) { cx = a.X + b.X cy = a.Y + b.Y return cx, cy } // 方法的声明(为Point类型的数据定制一个方法) func (a Point) sum(b Point) (cx int, cy int) { cx = a.X + b.X cy = a.Y + b.Y return cx, cy } ``` 方法与函数的调用 ``` func main() { // 初始化a、b两个结构体 var a = Point{ 100, 100, } var b = Point{ X: 200, Y: 200, } // 普通函数的调用 cx, cy := sum(a, b) fmt.Println(cx, cy) //方法的调用 dx, dy := a.sum(b) fmt.Println(dx, dy) } // 输出如下 300 300 300 300 ```