一起学习go语言的函数-发帖测试

我是沐风晓月
山东智码未来互联网科技有限公司官方账号
2023-03-22 14:49:18

# 前言
本文go语言入门-掌握go语言函数收录于《[go语言学习专栏](https://blog.csdn.net/wisdom_futrue/category_12160013.html)》专栏,此专栏带你从零开始学习go语言。

@[toc]

![在这里插入图片描述](https://img-blog.csdnimg.cn/7bfd1690bb514789b470c6d9b901c486.png)

# 一. go语言函数介绍
## 1.1 函数的介绍

在每一种编程语言中都有函数的概念,函数是基本的代码快,用于执行一个任务。

我们之前写的函数代码中,都包含一个main函数:

![在这里插入图片描述](https://img-blog.csdnimg.cn/6e686867f0fe4948a958ea89b5217aae.png#pic_center)
这个```main```就是一个函数的定义,包含了以下几部分:
- 关键字func
- 函数名字funcName
- 函数的参数params,用来定义形参的变量名和类型,可以有一个参数,也可以有多个,也可以没有
- result用于定义返回值的类型,如果没有返回值,省略即可,也可以有多个返回值
- body是函数体,可以在这里写函数的代码逻辑。

## 1.2 函数的特点
golang函数特点:

支持:

 - 无需声明原型;
 - 支持不定 变参;
 - 支持多返回值;
 - 支持命名返回参数;
 -  支持匿名函数和闭包;
 - 函数也是一种类型,一个函数可以赋值给变量。

不支持:

- 不支持 嵌套 (nested) 一个包不能有两个名字一样的函数。
- 不支持 重载 (overload)
- 不支持 默认参数 (default parameter)。

## 二.  函数的语法
## 2.1 函数的表达式
函数的语法格式:

```bash
func name( [parameter list] ) [return_types] {
   函数体
}

```
在这个语法格式中:

1. 函数的声明包含了一个函数名字,参数列表,返回值列表和函数体四个部分;
2. func 是声明函数的关键字,类似于我们声明变量要用var
3. name在这里是函数名字
4. parameter list:参数列表,参数就像一个占位符,当函数被调用时,你可以将值传递给参数,这个值被称为实际参数。
参数列表中指定了参数的类型,顺序以及参数的个数。
5. return_types:返回类型,函数返回一列值。return_types 是该列值的数据类型,比如(string ,string)表示返回两个字符串。当然并不是所有的函数都需要返回值。

    注意: 如果有多个返回值,需要用括号。
6. 函数体: 代码集合(一般是为了实现一个功能)

## 2.2 函数表达式案例
![在这里插入图片描述](https://img-blog.csdnimg.cn/43db729438224a8893dac001a29faec1.png)

###   2.2.1 案例一 :利用函数求最大值

```bash
package main

import "fmt"

func max(num1, num2 int) int {

    var result int

    if num1 > num2 {

        result = num1
    } else if num1 < num2 {
        result = num2
    } else {
        result = 0
    }
    return result

}

func main() {
    ret := max(1, 2)
    fmt.Println(ret)

}

```
### 2.2.2 案例二: 不需要参数也不需要返回值的函数
函数的参数和返回值都是可选的,我们可以实现一个既不需要参数也没有返回值的函数:
```bash
package main

import "fmt"
# 创建一个不需要参数也不需要返回值的函数
func sayhi() {
    fmt.Println("hi,沐风晓月")
}

#函数的调用
func main() {
    sayhi()
}

```


# 二. 函数的调用

定义了函数之后,我们可以通过函数名()的方式调用函数:

在上面的例子中,我们调用了sayhi()函数

```bash
#函数的调用
func main() {
    sayhi()
}
```
在main函数中进行函数的调用,根据函数的类型来赋值。

函数名的定义要求:
在避免冲突的情况下,函数命名要本着精简短小、见文知意的原则:

- 避免不必要的缩写,printError 要比 printEr 更好一些。
- 避免使用类型关键字,比如 buildUserStruct 看上去会很别扭。
- 避免歧义,不能有多种用途的解释造成误解。
- 避免只能通过大小写区分的同名函数。
- 避免与内置函数同名,这会导致误用。
- 避免使用数字,除非是特定专有名词,例如UTF8。
- 使用习惯用语,比如 init 表示初始化,is/has 返回布尔值结果。
- 使用反义词组命名行为相反的函数,比如 get/set、min/max 等。


# 三. 函数的参数
Go 对参数的处理比较保守,不支持有默认值的可选参数,不支持命名实参,调用时必须按照签名顺序传递指定类型和数量的实参,就算以```_```命名的参数也不能忽略。

形参: 函数定义中的参数
实参: 函数调用时所传递的参数
## 3.1 类型简写
函数的参数中如果相邻变量的类型相同,则可以省略类型,例如:
<font color=red> func test(x,y int ,string,_book)*int{} </font>

```bash
package main

func intsum(x, y int) int {
    return x + y
}

func main() {
    ret := intsum(5, 6)
    print(ret)

}
```

在上面的函数 intsum中,x和y都是int类型,所以 写的是```x,y ```只加```y```后面的一个int,```x```位置的int省略。  在```intsum(x,y) int```此处的第二个```int```,是<font color=red>函数返回值类型.</font>


## 3.2 可变参数
可变参数是指函数的参数数量不固定。Go语言中的可变参数通过在参数名后加```...```来标识。

这里需要主要的是,可变参数通常要作为函数的最后一个参数。

```bash
# 此处是可变参数
func intsum(x int, y ...int) int {
    fmt.Println(x, y)
    sum := x
    #函数的可变参数是通过切片来实现的
    for _, v := range y {

        sum = sum + v

    }
    return sum
}

func main() {
    ret := intsum(5, 6)
    ret1 := intsum(100)
    ret2 := intsum(100, 10, 20)
    fmt.Println(ret, ret1, ret2)

}
```
输出结果:

```bash
5 [6]
100 []     
100 [10 20]

11 100 130 

```

#  四.  返回值
Go语言中通过```return```关键字向外输出返回值。

## 4.1 多返回值
Go语言中函数支持多返回值,函数如果有多个返回值时必须用()将所有返回值包裹起来。

案例一:

```bash
package main

import "fmt"

func mufeng(x, y int) (int, int) {
    sum := x + y
    sub := x - y
    return sum, sub

}

func main() {
# 多返回值需要用两个变量来接受
    k, v := mufeng(40, 50)

    fmt.Println(mufeng(20, 10))
    fmt.Println(k, v)
}
```
执行结果:

```bash
30 10
90 -10
```

**案例二:**

```bash
package main

import "fmt"

func multi() (string, int) {
    return "沐风晓月", 19
}

func main() {
    name, age := multi()
    fmt.Println("name:", name, "age:", age)
}
```

## 4.2 返回值命名
函数定义时可以给返回值命名,并在函数体中直接使用这些变量,最后通过return关键字返回。
在之前的函数中,我们都是只指定类型,比如 ```int```,实际上我们除了指定类型之外,还可以直接返回值名称。

```bash
package main

import "fmt"

func mufeng(x, y int) (sum, sub int) {
    sum = x + y
    sub = x - y
    return
    // 对两个返回值进行了命名,一个是,一个是sub,这时候return后的返回值就可以不写。

}
## 函数值接收
func main() {

    fmt.Println(mufeng(20, 10))
    // 30 10

}

```
虽然Go语言支持函数返回值命名,但这并不是太常用,可以根据自己的需求情况,酌情选择是否对函数返回值命名。
## 4.3 返回值补充

当我们的一个函数返回值类型为slice时,nil可以看做是一个有效的slice,没必要显示返回一个长度为0的切片。

```bash
package main

import "fmt"

func mufeng(x string) []byte {

    if x == "" {
        return nil  
        // 此处没有必要返回一个[]byte{}

    }

    return []byte(x)

}
func main() {

    arr := mufeng("it")
    a := mufeng("")
    fmt.Println(arr)
    fmt.Println(a)
}
```

# 五. 函数进阶

## 5.1 全局变量

全局变量是定义在函数外部的变量,它在程序整个运行周期内都有效。 在函数中可以访问到全局变量。

```bash
package main

import "fmt"
// 定义全局变量

var num int32 = 100

func mufeng() {
// 在函数中打印全局变量
    fmt.Println(num)

}

func main() {
    mufeng()
}
```

## 5.2 局部变量

局部变量分两种:
-  函数内定义的变量无法在该函数外使用
- 如果局部变量和全局变量重名,优先访问局部变量

1. 先来看第一种:函数内定义的变量无法在该函数外使用

![在这里插入图片描述](https://img-blog.csdnimg.cn/aa0bc4d10dc24f68a0e6090b276b161a.png#pic_center)

2. 再来看第二种:

**如果局部变量和全局变量重名,优先访问局部变量。**

```bash
package main

import "fmt"

var num int64 = 100

func mufeng() {

    num := 10
    fmt.Println(num)
}

func main() {
    mufeng()
     // 最终结果是10
}

```
可以看到,一开始全局变量是100,局部变量是10,但两个重名,所以最终结果是10,优先访问局部变量。

3. 各种语快中定义变量也遵循上面的原则:

```bash
package main

import "fmt"

func mufeng(x, y int) {
    fmt.Println(x, y)
    //函数的参数也是只在本函数中生效
    if x > 0 {
        z := 100
        //变量z只在if语句块生效
        fmt.Println(z)

    }
    //fmt.Println("看看能否打印", z)
    //此处无法使用变量z

}
func main() {
    mufeng(3, 5)
}

```
在这个代码中可以看到,在if语句快外面就无法打印变量z了。

# 六 . 匿名函数和闭包
匿名函数就是没有名字的函数,也就是没有定义名字符号的函数,这是它与正常函数的主要区别。

而且匿名函数可以直接调用,保存到变量,作为参数和返回值。

我们来看一个案例:

```bash
package main

import "fmt"

func main() {
//匿名函数复制给了变量sum2
    sum2 := func(a, b int) int {
        return a + b
    }
    fmt.Println(sum2(2, 3))
}

```
这这里变量sum2所对应的值就是一个匿名函数。需要注意的是,这里的sum2只是一个函数类型的变量,并不是函数的名字。

有了匿名函数,就可以在函数中再定义函数(函数嵌套),定义的这个匿名函数也可以被称为内部函数。更重要的是,在函数内定义的内部函数,可以使用外部函数的变量等,这种方式也称为闭包。

举个例子:

```bash
package main

import "fmt"

func main() {
    c1 := colsure()
    fmt.Println(c1())
    fmt.Println(c1())
    fmt.Println(c1())

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

}
```
在这里,我们自定义的函数 ```colsure```可以返回一个匿名函数,并且这个匿名函数持有外部函数colsure的变量```i```.因而在main函数中,每调用一次cl(),i的值都会加1。

闭包时函数和引用环境的组合。
 

 

...全文
205 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

2,197

社区成员

发帖
与我相关
我的任务
社区描述
go语言学习与交流版
社区管理员
  • go语言社区
  • Freeman Z
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧