Golang 函数

Golang 函数

基本语法

	func (函数所属类型对象)函数名 (形参列表) 返回值{
		//body
        return 返回值
}

(函数所属类型对象)只有指定的类型对象采用调用该方法

  • 不带返回值

    func say(str string){
    	fmt.Println(str)
    }
    say("world")
    
  • 带单个返回值

    func Hello(a int32, b int32) int32{
    	return a+b
    }
    hello := Hello(10, 20)
    
  • 带多个返回值

    func number(a int, b int) (int, int) {
    	return a, b
    }
    a, b := number(10, 20)
    c,_ := number(10,30) // _ 表示忽略返回的值
    
  • 回调函数

    //作为参数
    func test1(num1 int, num2 int) int {
    	return num1 + num2
    }
    //和Js中调用回调函数相同
    func test2(method func(int, int) int, a int, b int) int {
    	return method(a, b)
    }
    func main() {
    	i := test2(test1, 10, 20)
    	fmt.Println(i)
    }
    
  • 闭包

    无返回值

    func test2(a int, b int) func() {
    	return func() {
    		fmt.Println(a+b)
    	}
    }
    func main() {
    	f := test2(10, 20)
    	f()
    }
    

    有返回值

    func test2(a int, b int) func(string) {
    	return func(s string) {
    		fmt.Println(s)
    		fmt.Println(a+b)
    	}
    }
    func main() {
    	//作为返回值
    	f := test2(10, 20)
    	f("hello world")
    }
    

init函数

每一个源文件都可以包含一个init函数,该函数会在 main函数之前执行,被Go运行框架调用

注意事项

如果一个文件同时包含全局变量定义,init函数和main函数

则执行的流行全局变量定义 -> init函数 -> main函数

//age := test() 不能被用作全局变量
var age = test() //和Java一样优先初始化成员变量,所以先调用test(),然后init()
func init() {
	fmt.Println("invoke init")
}
func test() int {
	fmt.Printf("invoke method")
	return 100
}
func main() {
	fmt.Println(age)
}

优先执行,导入包的变量定义和init方法

匿名函数

func main() {
	a:=10
	//和Js中的匿名函数一样, 可以省去func的括号
	res := (func(a int, b int) int {
		return a + b
	})(a, 20)
	fmt.Println(res)
	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
	(func() {
		fmt.Println("hello world")
	})()
}

闭包

func method() func(int) int {
	a := 10
	return func(num int) int {
		return a + num
	}
}
func main() {
	f := method()
	fmt.Println(f(1)) // 11
	fmt.Println(f(2)) // 13
	fmt.Println(f(3)) // 16 a相当于method实例f的成员变量
}

注意事项

  1. 函数的形参列表可以是多个,返回值列表也可以是多个。

  2. 形参列表和返回值列表的数据类型可以是值类型和引用类型。

  3. 函数的命名遵循标识符命名规范,首字母不能是是数字,首字母大写该函数可以被本包文件和其他包文件使用,类似于public,首字母小写,只能被本包文件使用,其他包文件不能使用,类似private

  4. 函数中的变量是局部的,函数外不生效

  5. 如果参数类型相同,可以省略参数类型

    func Method(a,b float64) float64{
    	return a + b
    }
    func main() {
    	num:=Method(10.2,10.2)
    	fmt.Println(num)
    }
    
  6. 基本数据类型数组默认都是值传递,即进行值拷贝。在函数内修改,不会影响到原来的值

  7. 如果希望函数内的变量能修改函数外的变量(指的是默认以值传递的方式的数据类型),可以传入变量的地址&,函数内以指针的方式操作变量。

    func test(a *int)*int{
    	*a = 30 //使用指针访问地址
    	return a
    }
    i := 20
    test(&i)
    fmt.Println(i)//30
    
  8. Go函数不支持重载

  9. 函数也是一种数据类型

    func test(a int,b int)int{
    	return a+b
    }
    func main() {
    	//和Js中相似, 函数是reference
    	a := test
    	fmt.Println(a(30 ,50))// 调用函数
    	fmt.Printf("a的类型为%T",a)
    	fmt.Printf("test的类型为%T",test)
    }
    
  10. 支持对函数返回值命名

    func method(a uint32, b uint32) (res uint32, tmp int) {
    	res = a + b
    	//自动返回res
    	tmp = int(a+b)
    	return
    }
    func main() {
    	res, tmp := method(10, 10)
    	//相当于Java System.err.print()
    	print(res,tmp)
    }
    
  11. 使用_表示符,忽略返回值

    func main() {
    	//忽略返回值中err
    	num, _ := strconv.ParseInt("110", 2, 64)
    	fmt.Println(num)
    }
    
  12. 支持可变参数

    • argsslice切片,通过args[index]可以访问到各个值
    • 如果一个函数的形参列表中有可变参数,则可变参数需要放在列表的最后
    //本质是切片,和Js中相似
    func function(args... int){
    	fmt.Println("args = ",args)
    	fmt.Println("len = ",len(args))//本质是一个数组
    	for i := 0; i < len(args); i++ {
    		fmt.Printf("args[%d] = %d \t",i,args[i])
    	}
    }
    func main() {
    	function(1,2,3,4)
    }
    
posted @ 2020-08-07 18:26  CyberPelican  阅读(98)  评论(0编辑  收藏  举报