Golang基础语法(go语言函数)

文章目录

同其他语言一样,go语言也有函数的概念,主要是为了代码复用,函数是基本的代码块,用于执行一个任务。

Go 语言最少有个 main() 函数,同时main函数也是整个程序执行的入口。

函数定义

Go 语言函数定义格式如下:

go 复制代码
func function_name( [parameter list] ) [return_types] {
    // 函数体
}
  • func:函数关键字,任何一个函数都有func关键字开始声明。
  • function_name:函数名称,参数列表和返回值类型构成了函数签名。
  • parameter list:参数列表,参数列表指定的是参数类型、顺序、及参数个数。参数是可选的,也就是说函数也可以不包含参数。
  • return_types:返回类型,函数返回一列值。return_types 是该列值的数据类型。有些功能不需要返回值,这种情况下 return_types 不是必须的。
  • 函数体:函数定义的代码集合。
  • 注意:go语言函数区别于c++和java语言的地方是可以有多个返回值,多个返回值用小括号括起来,中间用逗号分隔。

代码展示:

go 复制代码
package main

import "fmt"

func swap(x, y string) (string, string) {
    return y, x
}

func main() {
    a, b := swap("Google", "Hello")
    fmt.Println(a, b)
}

运行结果:

bash 复制代码
Hello Google

函数调用

当创建函数时,你定义了函数需要做什么,通过调用该函数来执行指定任务。

调用函数,向函数传递参数,并返回值,例如:

go 复制代码
package main

import "fmt"

func main() {
    /* 定义局部变量 */
    var a int = 100
    var b int = 200
    var ret int

    /* 调用函数并返回最大值 */
    ret = max(a, b)

    fmt.Printf("最大值是:%d\n", ret)
}

/* 函数定义:返回两个数的最大值 */
func max(num1, num2 int) int {
    /* 定义局部变量 */
    var result int

    if num1 > num2 {
        result = num1
    } else {
        result = num2
    }
    return result
}

运行结果:

bash 复制代码
最大值是:200

参数传递

在golang中函数的参数传递都是值传递,不存在引用传递(区别于c++)

注意:使用值传递的时候,虽然会改变形参的值,但并不会改变函数外变量即实参的值。

代码展示:

go 复制代码
package main

import "fmt"

func main() {
    /* 定义局部变量 */
    var a int = 100

    fmt.Printf("自增前 a 的值为:%d\n", a)

    add(a)

    fmt.Printf("自增后 a 的值:%d\n", a)
}

/* 函数定义:自增1 */
func add(a int) {
    a++;
    fmt.Printf("add里a的值:%d\n", a)
}

运行结果:

bash 复制代码
自增前 a 的值为:100
add里a的值:101
自增后 a 的值:100

函数用法

函数变量

一切皆变量,go语言里什么都可以当作变量来使用,当然函数也不例外,函数可以作为函数变量。

Go 语言可以很灵活的创建函数,并作为另一个函数的实参。以下实例中我们在定义的函数中初始化一个变量,该函数仅仅是为了使用内置函数

代码展示:

go 复制代码
package main

import (
    "fmt"
    "math"
)

func main() {
    /* 声明函数变量 */
    getSquareRoot := func(x float64) float64 {
        return math.Sqrt(x) // 求一个数的平方根
    }

    /* 使用函数变量调用函数 */
    fmt.Println(getSquareRoot(9))
}

运行结果:

bash 复制代码
3

再举一个用函数变量作回调函数的例子:

go 复制代码
package main

import "fmt"

// 声明一个函数类型
type fc func(int) int

func main() {
    CallBack(1, callBack) //执行函数--CallBack
}

func CallBack(x int, f fc) { //定义了一个函数 testCallBack
    f(x) //由于传进来的是callBack函数,该函数执行需要传入一个int类型参数,因此传入x
}

func callBack(x int) int {
    fmt.Printf("我是回调,x:%d\n", x)
    return x
}

运行结果:

bash 复制代码
我是回调,x:1

函数闭包

所谓闭包,就是匿名函数 ,go语言支持匿名函数调用。匿名函数就是一个"内联"语句或表达式。

匿名函数的优越性在于可以直接使用函数内的变量,不必声明,这样有时候可以使代码更简单,增强代码的可读性

代码展示:

go 复制代码
package main

import "fmt"

func getNumber() func() int {
    i:=0
    return func() int {
        i+=1
        return i
    }
}

func main(){
    /* nextNumber 为一个函数,函数中 i 为 0 */
    nextNumber := getNumber()

    /* 调用 nextNumber 函数,i 变量自增 1 并返回 */
    fmt.Println(nextNumber())
    fmt.Println(nextNumber())
    fmt.Println(nextNumber())

    /* 创建新的函数 nextNumber1,并查看结果 */
    nextNumber1 := getNumber()
    fmt.Println(nextNumber1())
    fmt.Println(nextNumber1())
}

运行结果:

bash 复制代码
1
2
3
1
2

注意:多次调用同一个函数nextNumber,其中的变量是同一个,初始值为0,每调用一次,自增1。

下面补充解释一下上面代码为什么会出现这样的结果:

首先,getNumer这个函数会返回一个闭包函数,我们先理解闭包是啥,闭包就是等于 匿名函数+捕获的变量,我们可以看到第7行-第10行,闭包函数里面捕获了变量,因为i不是在闭包函数里面定义的,

15行代码,通过getNumber获取了一个闭包函数 ---nextNumber

18,19,20行分别执行一次nextNumber函数,每次就会自增1,并且因为每次调用都是固定的,结果会累计,所以会输出1,2,3

23行重新获取了一个闭包函数,是独立于上面闭包函数的,所以重新输出1,2,3

同一个闭包会引用同一个变量,因此这里的i会递增。

修改代码加深印象

go 复制代码
package main

import "fmt"

func getNumber() func() int {
	i := 0
	fmt.Printf("getNumber中i的地址%v\n", &i)
	return func() int {
		i += 1
		fmt.Printf("闭包里i的地址%v\n", &i)
		return i
	}
}

func main() {
	/* nextNumber 为一个函数,函数中 i 为 0 */
	nextNumber := getNumber()

	/* 调用 nextNumber 函数,i 变量自增 1 并返回 */
	fmt.Println(nextNumber())
	fmt.Println(nextNumber())
	fmt.Println(nextNumber())

	/* 创建新的函数 nextNumber1,并查看结果 */
	nextNumber1 := getNumber()
	fmt.Println(nextNumber1())
	fmt.Println(nextNumber1())
}
bash 复制代码
root@GoLang:~/proj/goforjob# go run main.go 
getNumber中i的地址0xc000012098
闭包里i的地址0xc000012098
1
闭包里i的地址0xc000012098
2
闭包里i的地址0xc000012098
3
getNumber中i的地址0xc000102000
闭包里i的地址0xc000102000
1
闭包里i的地址0xc000102000
2

执行顺序例子

go 复制代码
package main

import "fmt"

func 铁扇公主() func() string {
	法宝 := "芭蕉扇"

	return func() string {
		fmt.Println("🐵:宝宝肚肚打雷了")
		return 法宝
	}
}

func main() {
	something := 铁扇公主()
	fmt.Printf("猴哥拿到了 %v! \n", something())
}
bash 复制代码
root@GoLang:~/proj/goforjob# go run main.go 
🐵:宝宝肚肚打雷了
猴哥拿到了 芭蕉扇! 
root@GoLang:~/proj/goforjob# 

之后我会持续更新,如果喜欢我的文章,请记得一键三连哦,点赞关注收藏,你的每一个赞每一份关注每一次收藏都将是我前进路上的无限动力 !!!↖(▔▽▔)↗感谢支持!

相关推荐
王老师青少年编程21 小时前
信奥赛C++提高组csp-s之拓扑排序详解
c++·算法·拓扑排序·csp·信奥赛·csp-s·提高组
No0d1es21 小时前
2025年12月电子学会青少年软件编程Python六级等级考试真题试卷
开发语言·python·青少年编程·等级考试·电子学会
zlp199221 小时前
xxl-job java.sql.SQLException: interrupt问题排查(二)
java·开发语言
superman超哥21 小时前
Rust HashSet与BTreeSet的实现细节:集合类型的底层逻辑
开发语言·后端·rust·编程语言·rust hashset·rust btreeset·集合类型
浩瀚地学21 小时前
【Java】异常
java·开发语言·经验分享·笔记·学习
kaikaile199521 小时前
matlab计算流场
人工智能·算法·matlab
张np21 小时前
java基础-LinkedHashMap
java·开发语言
gihigo199821 小时前
基于MATLAB的周期方波与扫频信号生成实现(支持参数动态调整)
开发语言·matlab
行者9621 小时前
Flutter适配OpenHarmony:国际化i18n实现中的常见陷阱与解决方案
开发语言·javascript·flutter·harmonyos·鸿蒙
csbysj202021 小时前
RSS 阅读器:全面解析与使用指南
开发语言