zoukankan      html  css  js  c++  java
  • [go]函数

    init执行顺序

    对同一个 go 文件的 init( ) 调用顺序是从上到下的
    对同一个 package 中的不同文件,将文件名按字符串进行“从小到大”排序,之后顺序调用各文件中的init()函数
    
    对于不同的 package,如果不相互依赖的话,按照 main 包中 import 的顺序调用其包中的 init() 函数
    如果 package 存在依赖,调用顺序为最后被依赖的最先被初始化,例如:导入顺序 main –> A –> B –> C,则初始化顺序为 C –> B –> A –> main,一次执行对应的 init 方法
    

    main函数

    //main不支持参数,传参使用os.Args
    func main() {
    	fmt.Println(os.Args)
    }
    
    //$: go run main.go 1 2 3
    //[/var/folders/4g/nfky9hks3j39qhvz741tmcn40000gn/T/go-build150967295/b001/exe/main 1 2 3]
    
    //main函数不支持返回值
    
    func main() int{
    	return 10
    }
    //$: go run main.go
    //# command-line-arguments
    //./main.go:3:6: func main must have no arguments and no return values
    
    //main函数返回状态值的方法: os.Exit
    func main() {
    	fmt.Println("hello")
    	os.Exit(-1)
    }
    //$: go run main.go
    //hello
    //exit status 255
    

    定义

    - 特点
    函数是结构化编程的最小模块单元.
    将复杂的算法过程分解为若干较小任务, 隐藏相关细节. 使得程序结构更加清晰.便于维护.
    
    普通函数则专注于算法流程,通过接收参数来完成特定逻辑运算,并返回最终结果
    
    支持前置声明
        func main() {
            test()
        }
    
        func test() {
            println("100")
        }
    
    不支持同名重载
        func test() {
            println("100")
        }
    
        func test() {
            println("200")
        }
    
    不支持命名嵌套定义
        func main() {
            func test() {
                println("200")
            }
        }
    不支持默认参数
    支持不定长边参
        func test(a int, n ...int) {
            fmt.Println(a, n) //10 [1 2 3]
        }
    
        func main() {
            arr := []int{1, 2, 3}
            test(10, arr...)
        }
    支持多返回值
    支持命名返回值
    支持匿名函数和闭包
    
    
    - 闭包
    func test() func() {
    	age := 0
    	return func() {
    		age++
    		println(age)
    	}
    }
    
    func main() {
    	f := test()
    	f()
    	f()
    	f()
    
    }
    
    
    - 延迟调用
    func test(fn func()) func() {
    	time := 0
    	return func() {
    		time++
    		if time > 2 {
    			fn()
    		}
    	}
    
    }
    
    func main() {
    	run := test(func() {
    		println("hello world")
    	})
    	run()
    	run()
    	run() //在执行第三次时才触发
    }
    
    只能和nil比较
    func(){} == nil
    

    参数

    - 参数
    不支持可选,不支持命名实参
    
    按顺序传参数
    func test(x, y int, s string, _ bool) *int {
    	return nil
    }
    
    func main() {
    	test(1, 2, "", false) 
    }
    
    形参类似是局部变量, 重复声明会出错
        func test(x, y int) {
            x := 100
            var y int
        }
    
    
    - 无论是哪种类型都传参都是值传递,无非是拷贝的是指(尽管他们指向的同一个对象)针还是值.
    func test(x *int) {
    	fmt.Printf("%p
    ", &x)
    }
    
    func main() {
    	a := 10
    	fmt.Printf("%p
    ", &a)
    	test(&a)
    }
    //0xc0000160c0
    //0xc000006030
    
    
    - 参数过多可以放到一个符合类型中, 变向的实现可选参数和命名实参的功能
    type serverOption struct{ 
       address string
       port  int
       path  string
       timeout time.Duration
       log    *log.Logger
    } 
      
    func newOption() *serverOption{ 
       return&serverOption{             // 默认参数 
           address: "0.0.0.0", 
           port:   8080, 
           path:    "/var/test", 
           timeout:time.Second*5, 
           log:    nil, 
        } 
    } 
      
    func server(option*serverOption) {} 
      
    func main() { 
       opt:=newOption() 
       opt.port=8085         // 命名参数设置 
      
       server(opt) 
    }
    
    
    
    - 可变参数(本质是一个切片,只能放在尾部)
    func test(s string,a...int) { 
       fmt.Printf("%T, %v
    ",a,a)       // 显示类型和值 
    } 
      
    func main() { 
       test("abc",1,2,3,4) 
    }
    
    - 切片作为变参时,必须进行展开操作, 如果是数组,则将其转换为切片
    func test(a...int) { 
       fmt.Println(a) 
    } 
      
    func main() { 
       a:= [3]int{10,20,30} 
       test(a[:]...)            // 转换为slice后展开 
    }
    
    既然变参是切片,那么参数复制的仅是切片自身,并不包括底层数组,也因此可修改原数据。
    
    
    

    返回值

    必须要有明确的return语句
    - 不明确
    func test(x int) int {
    	if x > 0 {
    		return 1
    	} else if x < 0 {
    		return 0
    	}
    }
    
    - 多返回值用括号括起来
    func div(x,y int) (int,error) { 
       if y==0{ 
           return 0,errors.New("division by zero") 
        } 
    
    - 命名多返回值
    func paging(sql string,index int) (count int,pages int,err error) { 
    }
    
    
    - 隐式返回
    func div(x,y int) (z int,err error) { 
       if y==0{ 
           err=errors.New("division by zero") 
           return
        } 
      
       z=x/y
       return         // 相当于 "return z,err" 
    }
    
    
    - 要命名都命名
    
    

    匿名函数

    没有定义名字符号的函数
    可以在函数内部定义匿名函数
    
    可以被直接调用
    可保存到变量
    可以作为参数和返回值
    
    
    - 直接执行
    	func(s string){
    		println(s)
    	}("hello mm")
    
    
    - 存储为变量
    	s := "hello"
    	fn := func(s string) {
    		println(s)
    	}
    	fn(s)
    
    - 作为参数
    func test(f func()) { 
       f() 
    } 
      
    func main() { 
       test(func() { 
           println("hello,world!") 
        }) 
    }
    
    - 作为返回值
    func test()func(int,int)int{ 
       return func(x,y int)int{ 
           return x+y
        } 
    } 
      
    func main() { 
       add:=test() 
       println(add(1,2)) 
    }
    
    
    - 匿名结构体类型
       type calc struct{                // 定义结构体类型 
           mul func(x,y int)int         // 函数类型字段 
        } 
      
    - 作为chan元素
       x:=calc{ 
           mul:func(x,y int)int{ 
               return x*y
            }, 
        } 
    
        c:=make(chan func(int,int)int,2) 
    
    
    - 闭包的延迟特性
    函数和其引用环境的组合
    
    func test(x int)func() { 
       return func() { 
           println(x) 
        } 
    } 
      
    func main() { 
       f:=test(123) 
       f() 
    }
    
    
    

    延迟调用

    defer想当前函数注册时候执行的函数调用
    因为他直到当前函数执行结束前才执行
    常用语资源释放,解除锁定,错误处理等操作
    
    
    func main() { 
       f,err:=os.Open("./main.go") 
       if err!=nil{ 
           log.Fatalln(err) 
        } 
      
       defer f.Close()          // 仅注册,直到main退出前才执行 
      
        ...do something... 
    }
    
    
    延迟调用注册的是调用,必须提供执行所需的参数
    参数值是在注册时候, 被赋值缓存起来, 如对状态敏感, 可改用指针或闭包
    func main() {
    	x := 1
    	defer println(x) //注册时拷贝一份当前变量值
    	x = 100
    	println(x)
    }
    // 100 1
    
    
    多个延迟注册按FILO次序执行。
    func main() { 
       defer println("a") 
       defer println("b") 
    }
    
    
    
    
  • 相关阅读:
    【Mybatis plus 3.2】怎么操作?看看我!(update、limit、between)
    #1024程序员节# 节日快乐
    ERROR: ...hbase.PleaseHoldException: Master is initializing
    【Flume】安装与测试
    【Storm】与Hadoop的区别
    【Storm】核心组件nimbus、supervisor、worker、executor、task
    LeetCode124:Binary Tree Maximum Path Sum
    LeetCode123:Best Time to Buy and Sell Stock III
    LeetCode122:Best Time to Buy and Sell Stock II
    LeetCode121:Best Time to Buy and Sell Stock
  • 原文地址:https://www.cnblogs.com/iiiiiher/p/12002171.html
Copyright © 2011-2022 走看看