【一Go到底】第十八天---函数的注意事项

92 阅读5分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第18天,点击查看活动详情

一、细节

  1. 函数的形参列表可以是多个,返回值列表也可以是多个。
  2. 形参列表和返回值列表的数据类型可以是值类型和引用类型。
  3. 函数的命名遵循标识符命名规范,首字母不能是数字,首字母大写该函数可以被本包文件和其它包文件使用,类似public , 首字母小写,只能被本包文件使用,其它包文件不能使用,类似private。
  4. 函数中的变量是局部的,函数外不生效 - 请看案例1
  5. 基本数据类型和数组默认都是值传递的,即进行值拷贝。在函数内修改,不会影响到原来的值- 请看案例2
  6. 如果希望函数内的变量能修改函数外的变量,可以传入变量的地址&,函数内以指针的方式操作变量。从效果上看类似引用 - 请看案例 3
  7. Go函数不支持重载。
  8. 在Go中,函数也是一种数据类型,可以赋值给一个变量,则该变量就是一个函数类型的变量了。通过该变量可以对函数调用。 - 请看案例 4
  9. 函数既然是一种数据类型,因此在Go中,函数可以作为形参,并且调用!--请查看 案例 5
  10. 为了简化数据类型定义,Go支持自定义数据类型,其基本语法为:--请查看 案例 6
type 自定义数据类型名 数据类型 // 相当于别名

案例: type myInt int // myInt 等于 int使用
案例: type mySum func(int, int) int // mySum 等价于一个函数类型func(int, int)int
  1. 支持对函数返回值命名.--请查看 案例 7
func

  1. 使用_标识符,忽略返回值。--请查看 案例 7
  2. Go支持可变参数--请查看 案例 8
// 支持0到多个参数
func sum(args... int) sun int{}

// 支持 1到多个参数
func sum(num1 int,args.... int) sum int{}

// args是 slice,通过args[index] 可以访问到各个值
// 如果一个函数的形参列表中有可变参数,则可变参数需要放在形参列表最后。

二、案例解析

2.1 案例1

在这个案例中,example()函数中的num1和main函数中的num1 并不是同一个,example()中的num1是其内部的局部变量

package main

import "fmt"

func example() {
	var num1 int = 100
	fmt.Println("num1 = ", num1)
}

func main() {
	var num1 int = 10010
	example()
	fmt.Println("main num1 = ", num1)
}

2.2 案例2

函数内的num1不会影响到main中num1的值

package main

import (
	"fmt"
)

func example2(num1 int) {
	num1 += 10
	fmt.Println("example num1 = ", num1)
}

func main() {

	num1 := 100
	example2(num1)                      // 输出 110
	fmt.Println("main函数的num1 = ", num1) //输出100
}

2.3 案例3

先执行main中内容,首先会有一个num1 中的地址;调用example3(),其中example3()的形参 num1 是一个指针类型,此时将 main()函数中的 num1 的地址传递进去,其example3()的操作此时是使用的 main()函数中的 num1的地址进行操作

package main

import (
	"fmt"
)

// num1 为 *int 类型
func example3(num1 *int) {
	*num1 += 10
	// *取值  &取地址
	fmt.Println("example num1 = ", *num1)
}

func main() {

	num1 := 100
	example3(&num1)                     // 输出 110
	fmt.Println("main函数的num1 = ", num1) //输出110
}


2.4 案例4

package main

import "fmt"

func getSum(num1 int, num2 int) int {
	return num1 + num2
}

func main() {

	a := getSum
	r := a(10, 20)
	// 输出 a的类型为: func(int, int) int, getSum()的类型:func(int, int) int
	fmt.Printf("a的类型为: %T, getSum()的类型:%T\n", a, getSum)
	// r的值为: 30
	fmt.Printf("r的值为: %v", r)
}

2.5 案例5

函数既然是-种数据类型,因此在Go中,函数可以作为形参,并且调用

package main

import "fmt"

func getSum(num1 int, num2 int) int {
	return num1 + num2
}

func myFunc(funvar func(int, int) int, num1 int, num2 int) int {
	return funvar(num1, num2)
}

func main() {

	result := myFunc(getSum, 100, 200)
	fmt.Printf("result = %v", result)
}


2.6 案例6

package main

import "fmt"

func main() {

	// 给int取别名, 在go中 myInt 和 int 是不同的数据类型
	type myInt int

	// 定义一个变量
	var num1 myInt
	// num1 = 0, type = main.myInt
	fmt.Printf("num1 = %v, type = %T", num1, num1)

}

2.7 案例7

package main

import "fmt"
// 注意返回这里的命名,就不需要在函数中 := 声明
func getSum(num1 int, num2 int) (sum int, sub int) {
	sum = num1 + num2
	sub = num1 - num2
	return
}

func main() {

	n1 := 10
	n2 := 20
	// 理解 _ 的用意
	sum, _ := getSum(n1, n2)
	_, sub := getSum(n1, n2)
	//sum = 30, sub=-10
	fmt.Printf("sum = %v, sub=%v", sum, sub)
}

2.8 案例8

编写sum函数,求出1到多个int的和

package main

import "fmt"

func sum(num1 int, args ...int) int {
	sum := num1
	// 遍历 args
	for i := 0; i < len(args); i++ {
		sum += args[i]
	}
	return sum
}

func main() {

	result := sum(100, 200, 300, 400)
	// sum = 1000
	fmt.Printf("sum = %v", result)
}

三、函数练习

3.1 判断代码是否正确,若正确输出什么内容

3.1.1 案例1


package main

import "fmt"

func sum(num1, num2 float32) float32 {
	fmt.Printf("num1 Type : %T\n", num1)
	return num1 + num2
}
func main() {
	fmt.Println("sum = ", sum(10, 20))
        //
	// num1 Type : float32
	// sum =  30
}

3.1.2 案例2

package main

import "fmt"

type mySum func(int, int) int

func sum(n1 int, n2 int) int {
	return n1 + n2
}

func sum2(n1, n2, n3 int) int {
	return n1 + n2
}

// 使用type自定义数据类型来简化定义
func myFunc(funcVar mySum, num1 int, num2 int) int {
	return funcVar(num1, num2)
}

func main() {
	a := sum
	b := sum2
	fmt.Println(myFunc(a, 10, 20))
	// b这里 sum2 有3个形参接收,myFunc只有2个形参接收,类型不匹配
	fmt.Println(myFunc(b, 100, 200))
}

3.3 请编写一个函数swap(n1 *int,n2 *int)可以交换n1和n2的值

// 编写一个函数swap(n1 int, n2 int)可以交换n1 n2的值
package main

import "fmt"

func swap(n1 *int, n2 *int) (int, int) {
	*n1, *n2 = *n2, *n1
	return *n1, *n2
}

func main() {
	a := 10
	b := 20
	swap(&a, &b) // 传入a,b地址
	fmt.Printf("a = %v, b = %v", a, b)
}