【Go语言学习笔记】Go的函数

函数还是这几块:

  • 参数
  • 返回值
  • 作用域
  • 执行顺序

参数和返回值

func FuncName(/*参数列表*/) (o1 type1, o2 type2/*返回类型*/) {
    //函数体
 
    return v1, v2 //返回多个值
}

和C差不多,但是有点不一样的是:

  • 函数名首字母小写即为private,大写即为public。(即跨文件调用需要大写)
  • 可以有多个返回值,而且返回值可以预订变量名。
  • 可以有不定参数
package main

import "fmt"

func Test() { //无参无返回值函数定义
	fmt.Println("this is a test func")
}

//有参无返回值
func Test01(v1 int, v2 int) { //方式1
	fmt.Printf("v1 = %d, v2 = %d
", v1, v2)
}

func Test02(v1, v2 int) { //方式2, v1, v2都是int类型
	fmt.Printf("v1 = %d, v2 = %d
", v1, v2)
}

//不定参数
//形如...type格式的类型只能作为函数的参数类型存在,并且必须是最后一个参数
func Test03(args ...int) {
	for _, n := range args { //遍历参数列表
		fmt.Println(n)
	}
}

//不定参数的传递
func Test04(args ...int) {
	Test03(args...)     //按原样传递, Test()的参数原封不动传递给MyFunc01
	Test03(args[1:]...) //Test()参数列表中,第1个参数及以后的参数传递给MyFunc02
}

//不定参数且类型不一样
func MyPrintf(args ...interface{}) {
	for _, arg := range args {
		switch arg.(type) {
		case int:
			fmt.Println(arg, "is an int value.")
		case string:
			fmt.Println(arg, "is a string value.")
		case int64:
			fmt.Println(arg, "is an int64 value.")
		default:
			fmt.Println(arg, "is an unknown type.")
		}
	}
}

func main() {
	Test() //无参无返回值函数调用

	Test01(10, 20) //函数调用
	Test02(11, 22) //函数调用

	Test03(1)
	Test03(1, 2, 3)

	Test04(4, 5, 6)

	var v1 int = 1
	var v2 int64 = 234
	var v3 string = "hello"
	var v4 float32 = 1.234
	MyPrintf(v1, v2, v3, v4)
}

package main

import "fmt"

func test01() int { //方式1
	return 250
}

//官方建议:最好命名返回值,因为不命名返回值,虽然使得代码更加简洁了,但是会造成生成的文档可读性差
func test02() (value int) { //方式2, 给返回值命名
	value = 250
	return value
}

func test03() (value int) { //方式3, 给返回值命名
	value = 250
	return
}

//多个返回值
//求2个数的最小值和最大值
func MinAndMax(num1 int, num2 int) (min int, max int) {
	if num1 > num2 { //如果num1 大于 num2
		min = num2
		max = num1
	} else {
		max = num2
		min = num1
	}

	return
}

func main() {
	v1 := test01() //函数调用
	v2 := test02() //函数调用
	v3 := test03() //函数调用
	fmt.Printf("v1 = %d, v2 = %d, v3 = %d
", v1, v2, v3)

	min, max := MinAndMax(33, 22)
	fmt.Printf("min = %d, max = %d
", min, max) //min = 22, max = 33
}

作用域

作用域为已声明标识符所表示的常量、类型、变量、函数或包在源代码中的作用范围。

函数内定义的变量称为局部变量。
函数外定义的变量称为全局变量。

在不同作用域可以声明同名的变量,其访问原则为:在同一个作用域内,就近原则访问最近的变量,如果此作用域没有此变量声明,则访问全局变量,如果全局变量也没有,则报错。

局部变量

在函数体内声明的变量、参数和返回值变量就是局部变量,它们的作用域只在函数体内:

func test(a, b int) {
    var c int
    a, b, c = 1, 2, 3
    fmt.Printf("a = %d, b = %d, c = %d
", a, b, c)
}
 
func main() {
    //a, b, c = 1, 2, 3 //err, a, b, c不属于此作用域
    {
        var i int
        i = 10
        fmt.Printf("i = %d
", i)
    }
 
    //i = 20 //err, i不属于此作用域
 
    if a := 3; a == 3 {
        fmt.Println("a = ", a)
    }
    //a = 4 //err,a只能if内部使用
}

全局变量

在函数体外声明的变量称之为全局变量,全局变量可以在整个包甚至外部包(被导出后)使用。

var a int //全局变量的声明
 
func test() {
    fmt.Printf("test a = %d
", a)
}
 
func main() {
    a = 10
    fmt.Printf("main a = %d
", a) //main a = 10
 
    test() //test a = 10
}

不同作用域同名变量

在不同作用域可以声明同名的变量,其访问原则为:在同一个作用域内,就近原则访问最近的变量,如果此作用域没有此变量声明,则访问全局变量,如果全局变量也没有,则报错。

var a int //全局变量的声明
 
func test01(a float32) {
    fmt.Printf("a type = %T
", a) //a type = float32
}
 
func main() {
    fmt.Printf("a type = %T
", a) //a type = int, 说明使用全局变量的a
 
    var a uint8 //局部变量声明
 
    {
        var a float64                  //局部变量声明
        fmt.Printf("a type = %T
", a) //a type = float64
    }
 
    fmt.Printf("a type = %T
", a) //a type = uint8
 
    test01(3.14)
    test02()
}
 
func test02() {
    fmt.Printf("a type = %T
", a) //a type = int
}

执行顺序

和C一样,顺序执行,有递归还是按栈的顺序。

唯一的区别,在于defer,单独开一篇写。

原文地址:https://www.cnblogs.com/HappyTeemo/p/15457348.html