• go 函数


    函数声明和注释

    1、函数声明: func 函数名字 (参数列表)  [(返回值列表)] {}

    func add(a, b int) (int, int)  {
    }

    2. 注释,两种注释,单行注释: // 和多行注释 /* */

    3、 一个.go文件初始化,先执行全局变量,再执行init()函数,init()函数自动调用

    4、多个包引用,如果引用顺序是main -> add -> test,初始化顺序:test.go的全局变量->test.go的init()->add全局变量->add.go的init()->main.go全局变量->main.go的init()

     

    函数特点

    • 不支持重载,一个包不能有两个名字一样的函数
    • 函数是一等公民,函数也是一种类型,一个函数可以赋值给变量
    • 匿名函数
    • 多返回值

    样例:

    package main
    
    import "fmt"
    
    type op_func func(int, int) int
    
    func add(a, b int) int {
    	return a + b
    }
    
    func sub(a, b int) int {
    	return a - b
    }
    
    func operator(op op_func, a int, b int) int {
    	return op(a, b)
    }
    
    func main() {
    	c := add
    	fmt.Println(c)
    	sum := operator(c, 100, 200)
    	fmt.Println(sum)
    
    	var d op_func
    	d = sub
    	fmt.Println(d)
    	sub := operator(d, 100, 200)
    	fmt.Println(sub)
    }
    

    自定义函数

    demo

    package main
    
    import "fmt"
    
    type add_func func(int, int) int
    
    func add(a, b int) int {
    	return a + b
    }
    func operator(op add_func, a int, b int) int {
    	//使⽤用传进来的函数,进⾏行行操作
    	return op(a, b)
    }
    func main() {
    	c := add
    	fmt.Println(c)
    	sum := operator(c, 100, 200)
    	fmt.Println(sum)
    }
    

    函数参数传递方式

    • 值传递
    • 引用传递

    注意:无论是值传递,还是引用传递,传递给函数的都是变量的副本。不过,值传递是值的拷贝。引用传递是地址的拷贝,一般来说,地址拷贝更为高效。而值拷贝取决于拷贝的对象大小,对象越大,则性能越低。

    map、slice、chan、指针、interface默认以引用的方式传递。

    命名返回值的名字

    func add(a, b int) (c int) {
            c = a + b
            return
    }
    
    func calc(a, b int) (sum int, avg int) {
            sum = a + b
            avg = (a + b)/2
            return
    }
    

    _标识符,用来忽略返回值

    func calc(a, b int) (sum int, avg int) {
            sum = a + b
            avg = (a + b) / 2
            return
    }
    
    func main() {
          sum, _ := calc(100, 200)
    }
    

    可变参数

    • 0个或多个参数
    func add(arg…int) int {
    }
    
    • 1个或多个参数
    func add(a int, arg…int) int {
    }
    
    • 2个或多个参数
    func add(a int, b int, arg…int) int {
    }
    

    注意:其中arg是一个slice,我们可以通过arg[index]依次访问所有参数,通过len(arg)来判断传递参数的个数。

    样例:

    package main
    
    import "fmt"
    
    func add(a int, arg...int) int{
    	var sum int = a
    	for i := 0; i < len(arg); i ++ {
    		sum += arg[i]
    	}
    	return sum
    }
    
    func add_string(a string, arg...string) (result string) {
    	result = a
    	for i := 0; i < len(arg); i ++ {
    		result += arg[i]
    	}
    	return
    }
    
    func main() {
    	sum := add(10, 1 , 2, 3)
    	fmt.Println(sum)
    	str := add_string("hello ", "world ", "wang")
    	fmt.Println(str)
    }
    

    匿名函数

    样例:

    package main
    
    import "fmt"
    
    var(
    	result = func(a1, b1 int) int{
    		return a1 + b1
    	}
    )
    
    func test(a, b int) int {
    	result := func(a1, b1 int) int{
    		return a1 + b1
    	}(a, b)
    	return  result
    }
    
    func test1(a, b int) int {
    	result := func(a1, b1 int) int{
    		return a1 + b1
    	}
    	return  result(a, b)
    }
    
    func main() {
    	sum := test(10 , 20)
    	fmt.Println(sum)
    	sum1 := test1(1, 2)
    	fmt.Println(sum1)
    	fmt.Println(result(3,4))
    }

    defer用途

    • 当函数返回时,执行defer语句。因此,可以用来做资源清理
    • 多个defer语句,按先进后出的方式执行
    • defer语句中的变量,在defer声明时就决定了

    样例:

    package main
    
    import "fmt"
    
    func main() {
    	var i int = 0
    	defer fmt.Println(i)
    	defer fmt.Println("second")
    	i = 10
    	fmt.Println(i)
    }

    说明:上面代码执行,先将defer压入栈中,当main函数执行完成后,再执行defer内容。多个defer语句,按先进后出的方式执行。同时defer语句的变量i声明时为0,所以结果也为0

    使用场景举例:

    1、关闭文件句柄

    func read() {  
        //文件操作
        file := open(filename)
        defer file.Close()
    }
    

    2、锁资源释放

    func read() {
        mc.Lock()
        defer mc.Unlock()
        // 其他操作
    }
    

    3、数据库连接释放

    func read() {
        conn := openDatabase()
        defer conn.Close()
        //其他操作
    }
    

    内置函数

    • close:主要用来关闭channel
    • len:用来求长度,比如string、array、slice、map、channel
    • new:用来分配内存,主要用来分配值类型,比如int、struct。返回的是指针
    • make:用来分配内存,主要用来分配引用类型,比如chan、map、slice
    • append:用来追加元素到数组、slice中
    • panic和recover:用来做错误处理

    new和make的区别

    package main
    
    import "fmt"
    
    func test() {
    	s1 := new([]int)
    	fmt.Println(s1)
    
    	s2 := make([]int, 10)
    	fmt.Println(s2)
    
    	*s1 = make([]int, 5)
    	(*s1)[0] = 100
    	s2[0] = 100
    	fmt.Println(s1)
    	return
    }
    
    func main() {
    	test()
    }
    

    递归函数

    函数调用自己,就叫做递归。

    递归的设计原则

    • 一个大的问题能够分解成相似的小问题
    • 定义好出口条件

    样例:

    package main
    
    import (
    	"fmt"
    	"time"
    )
    
    func recusive(n int) {
    	fmt.Println("hello", n)
    	time.Sleep(time.Second)
    	if n > 10 {
    		return
    	}
    	recusive(n + 1)
    }
    
    func factor(n int) int {
    	if n == 1 {
    		return 1
    	}
    	return factor(n-1) * n
    }
    
    func fab(n int) int {
    	if n <= 1 {
    		return 1
    	}
    	return fab(n-1) + fab(n-2)
    }
    
    func main() {
    	//fmt.Println(factor(5))
    	recusive(0)
    	/*for i := 0; i < 10; i++ {
    		fmt.Println(fab(i))
    	}*/
    }
    

    闭包

    一个函数和与其相关的引⽤用环境组合⽽而成的实体。

    demo1:

    func Adder() func(int) int {
    
    	var x int
    	f := func(i int) int {
    		x = x + i
    		return x
    	}
    
    	return f
    }
    
    func testClosure() {
    
    	f1 := Adder()
    	fmt.Println(f1(10))
    	fmt.Println(f1(20))
    	fmt.Println(f1(30))
    
    	f2 := Adder()
    	fmt.Println(f2(10))
    	fmt.Println(f2(20))
    	fmt.Println(f2(30))
    }
    

    demo2:

    package main
    
    import (
    	"fmt"
    	"strings"
    )
    
    func makeSuffixFunc(suffix string) func(string) string {
    	return func(name string) string {
    		if !strings.HasSuffix(name, suffix) {
    			return name + suffix
    		}
    		return name
    	}
    }
    func main() {
    	bmp := makeSuffixFunc(".bmp")
    	jpg := makeSuffixFunc(".jpg")
    	fmt.Println(bmp("test"))
    	fmt.Println(jpg("test"))
    }
    
  • 相关阅读:
    centos7系统中忘记了root管理员账号密码的解决方式
    【python之路48】生成器表达式、推导式
    小米集团信息化中台战略
    分时函数
    函数节流
    JS浮点计算问题
    要转型做前端开发了
    优秀的开发人员和测试人员应有的态度
    C#数组的笔记
    LINQ不包含列表
  • 原文地址:https://www.cnblogs.com/shhnwangjian/p/7423251.html
Copyright © 2020-2023  润新知