golang函数
函数定义#
/*
函数定义关键字 func
func 函数名 (参数 参数类型) 函数返回值的类型
*/
func getInfo(name string, age int) string {
return name
}
// 函数返回多个返回值:则返回类型括号包裹(返回值类型,类型..),即时返回两个int,也需要(int,int)
func getNum(x int, status bool) (int, bool) {
return x, status
}
// 函数返回值命名:函数定义时给返回值命名,并在函数体内可以直接使用这些变量,最后通过return返回
// 返回值是int类型,给返回值命名为num,并且可以直接调用
func sumNumber(x, y int) (sum int) {
sum = x + y
return sum
}
// 函数参数简写:如果参数的类型一样,可以只写一个类型
func setName(name, nickname string, age, height int) string {
return nickname
}
// 函数可变参数:可变参数是指函数的参数数量不固定,在参数名后加...来标识
func getParam(x ...int) []int {
// 传递可变参数,传递的参数类型是一个切片
return x
}
// 函数可以没有参数和返回值
func test(){
fmt.Println("t")
}
函数类型#
可以使用type关键字来定义一个函数类型
/* 语法 */
// 类型的名字 该函数类型要传递的参数、该函数类型要返回的类型
type name func(string,string) string
// 自定义一个name类型
type name func(string, string) string
// 定义一个yoyo函数
func yoyo(a, b string) string {
return a
}
func main() {
// 定义一个test变量,是一个name类型
var test name
// 给test赋值的时候,因为上面声明了name类型,如果参数和返回值不符合name类型的条件,就会报错
test = yoyo
fmt.Printf("%T", test) // main.name main文件里面的name类型
// yoyo赋值给test,可以通过test()来当函数调用
test("1", "1")
}
/*
也可以自定义其他类型,比如自定义一个myInt类型,需要是int
type myInt int
*/
函数当做参数传递和返回值#
当参数传递:
/* 语法一 */
func a(num int) int {
return num
}
func b(num int) int {
return num
}
// 定义c方法,传递num参数,然后传递一个函数,这个函数是有一个int参数,返回也是int
func c(num int, f func(int) int) int {
return f(num)
}
func main() {
fmt.Println(c(1, a))
}
/* 语法二 */
// 自定义Number类型
type number func(int) int
// 定义c方法,传递num参数,然后传递一个函数,符合Number类型
func c(num int, f number) int {
return f(num)
}
func main() {
fmt.Println(c(1, a))
}
函数当做返回值:
/* 语法一 */
func b(num int) int {
return num
}
// 自定义Number类型
type number func(int) int
// 定义c方法 返回类型是number
func c(num int) number {
return b
}
/* 语法二 */
func b(num int) int {
return num
}
// 定义c方法 指定返回值类型为 一个int参数且返回值值为int的函数
func c() func(int) int {
return b
}
func main() {
fmt.Println(c()(1))
}
匿名函数#
匿名函数就是没有函数名的函数
func main() {
// 匿名自执行函数,可以传递参数也可以不传
func() {
fmt.Println("test")
}() // 在后面+()调用
// 匿名函数赋值变量
var fn = func(x int, y int) int {
return x + y
}
// 调用匿名函数变量
fn(1, 1)
}
函数递归#
func A(n int) {
fmt.Println("n")
n--
// n大于1的时候递归调用自身, 递归调用需要注意死循环问题
if n > 1 {
A(n)
}
}
函数闭包#
// 写法:函数里面嵌套一个函数,最后返回里面的函数
func testA() func() int {
i := 10
return func() int {
i++
return i
}
}
func main() {
// testA 赋值给a testA返回的是匿名函数
var a = testA()
// 调用a(),调用的是testA中的匿名函数 i常驻内存中,依次++
fmt.Println(a()) // 11
fmt.Println(a()) // 12
fmt.Println(a()) // 13
}
defer语句#
// 执行顺序 1、4、3、2
fmt.Println(1)
defer fmt.Println(2)
defer fmt.Println(3)
fmt.Println(4)
// eeee、aaa
func testA() {
defer func() {
fmt.Println("aaa")
}()
fmt.Println("eeee")
}
defer在命名返回值和匿名返回函数中的区别:
defer注册要延迟执行的函数时该函数所有的参数都要确定其他值,然后执行的时候按照执行顺序
// 匿名返回值
func testA() int {
var a int
defer func() {
a++
}()
return a
}
// 命名返回值
func testB() (b int) {
defer func() {
b++
}()
return b
}
func main() {
fmt.Println(testA()) // 0
fmt.Println(testB()) // 1
}
内置函数panic/recover#
panic的作用是主动抛出异常并终止程序执行
-
recover()必须放在defer里面执行,recover的作用是监听panic抛出的异常,如果panic没有抛出异常,则是nil,可以以此来判断
-
recover()必须搭配 defer 使用。
-
defer 一定要在可能引发 panic 的语句之前定义
func testA() {
fmt.Println("A")
// 使用defer延迟执行
defer func() {
// recover 监听panic抛出的异常,如果!=nil,说明panic有抛出的异常,可以进行对应的处理,不终止程序执行
err := recover()
if err != nil {
fmt.Println(err)
}
}()
// 主动使用panic 抛出异常
panic("抛出异常")
}
func testB() {
fmt.Println("B")
}
func main() {
testA()
testB()
}
func sum(a, b int) int {
defer func() {
err := recover()
if err != nil {
fmt.Println(err) // runtime error: integer divide by zero
}
}()
// 10 不能 / 0 ,所以会发生错误,go本身会使用panic抛出异常
return a / b
}
func main() {
fmt.Println(sum(10, 0))
}
搭配使用:
import (
"errors"
"fmt"
)
func name(n string) error {
if n == "li"{
return nil
}
return errors.New("名字错误")
}
func main() {
defer func() {
// 3. 监听到抛出的异常
err := recover()
if err!=nil{
fmt.Println("err")
}
}()
// 1.调用name,如果返回nil 说明没有异常,不是nil则有异常
nick := name("1")
// 2. 如果有异常 则使用panic主动抛出
if nick != nil{
panic("error")
}
}
风月都好看,人间也浪漫.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
2021-02-20 7.类属性、类方法、静态方法
2021-02-20 6.多态
2021-02-20 5.多继承
2021-02-20 4.父类私有属性和方法
2021-02-20 3.单继承和方法的重写