go语言学习(二):函数、闭包、工程目录

1.不定参数类型
func MyFun01(a int, b int){
//a = 111
fmt.Println(“a =”, a,b)
}
//…type不定参数类型
func MyFunc02(args …int){ //传递的实参可以是0个或者多个
//fmt.Println(“len(args) =”,len(args)) //获取用户传递参数的个数
for i:=0;i<len(args);i++{
fmt.Printf(“args[%d] = %d\n”, i, args[i])
}
fmt.Println("===================")
//range返回2个值,第一个是下标,第二个是下标对应的数据
for i,data := range args{
fmt.Printf(“args[%d] = %d\n”, i, data)
}
}

func main() {
MyFunc02()
fmt.Println("+++++++++++++++++")
MyFunc02(1)
fmt.Println("+++++++++++++++++")
MyFunc02(1,2,3)
}
2.不定参数的传递

func myfunc(tmp ...int){
   for _,data := range tmp{
      fmt.Println("data =", data)
   }
}

func myfunc2(tmp ...int){
   for _,data := range tmp{
      fmt.Println("data =", data)
   }
}

func test(args ...int){
   //全部元素传递给myfunc
   //myfunc(args...)

   //只想把后2个参数传递给另外一个函数使用
   //myfunc2(args[0:2]...) //从0到2(不包括2)传递过去
   myfunc2(args[2:]...) //从args[2]开始(包括本身),把后面所有元素传递过去
}

func main() {
    test(1, 2, 3)
}

3.单返回值常用写法

func myfunc01() int{
   return 666
}

//给返回值起一个变量名,go推荐写法
//常用写法
func myfunc02() (result int) {
   result = 666
   return
}
func main() {
   //无参返回值函数调用
    var a int
    a = myfunc01()
    fmt.Println("a =", a)

    //自动推导类型
    b := myfunc02()
    fmt.Println("b =", b)
}

4.多个返回值

//多个返回值
func myfunc01() (int, int, int){
    return 1, 2, 3
}

//go官方推荐写法
func myfunc02() (a int, b int, c int){
   a, b, c = 111, 222, 333
   return
}

func myfunc03() (a, b, c int){
   a, b, c = 111, 222, 333
   return
}
func main() {
   //函数调用
   a, b, c := myfunc03()
   fmt.Println(a, b, c)
}

求最大最小值

//函数名小写私有,大写公有
func MaxandMin(a, b int) (max, min int){
   if a>b{
      max=a
      min=b
   }else {
      max=b
      min=a
   }
   return
}
func main() {
   //函数调用
   max, min := MaxandMin(10, 20)
   fmt.Println(max, min)
}

5.递归(斐波那且数列,汉诺塔)

;i<=100;i++{
      sum+=i
   }
   return
}

func test02(i int) int {
   if i==1{
      return 1
   }
   return i + test02(i-1)
}
func main() {
   //test(3)
   var sum int
   sum = test02(100)
   fmt.Println(sum)
}

函数多态,定义函数变量

func  Add(a, b int) int {
   return a+b
}




//函数也是一种数据类型,通过type给一个函数类型起名
//FuncType它是一个函数类型
type FuncType func(int, int) int  //没有函数名字,没有{}

func main() {
   var result int
   result = Add(1,1)
   fmt.Println(result)

   //声明一个函数类型的变量
   var fTest FuncType
   fTest = Add  //是变量就可以赋值
   result = fTest(10, 20)
   fmt.Println(result)
}

回调函数实现函数多态性

type FuncType func(int, int) int

//实现想法
func  Add(a, b int) int {
   return a+b
}

func minus(a, b int) int {
   return a-b
}
//回调函数,函数有一个参数是函数类型,这个函数就是回调函数
//计算器,可进行四则运算
//多态,多种形态,调用同一个接口,不同的表现,可以实现不同的表现,加减乘除的
//现有想法,后面再实现功能
func Calc(a, b int, fTest FuncType) (result int){
   fmt.Println("Calc")
   //result = Add(a, b)  //Add这个函数必须先定义后,才能调用
   result = fTest(a, b)  //这个函数还没有实现
   return
}

func main() {
   a := Calc(1, 1, Add)
   fmt.Println(a)
   b := Calc(1, 1, minus)
   fmt.Println(b)
}

4.闭包

所谓闭包就是一个函数"捕获"了和它在同一作用域的其他常量和变量,这就意味着当闭包被调用的时候,不管程序在什么地方调用,闭包都能使用这些常量或者变量。它不关心这些捕获了的变量和常量是否已经超出了作用域,所以只有闭包还在使用它,这些变量就还会存在。

匿名函数基本语法

func main() {
   a := 10
   str := "mike"

   //匿名函数,没有函数名字
   f1 := func() {  //:=自动推导类型,常用
      fmt.Println(a,str)
   }

   f1()

   //给定一个函数类型起别名
   type FuncType func() //函数没有参数,每有返回值
   //声明变量
   var f2 FuncType
   f2 = f1
   f2()

   //定义匿名函数,同时调用
   func() {
        fmt.Printf("a =%d, str =%\n", a, str)
   }() //后面的()代表给匿名函数传参,调用此匿名函数

   //带参数的匿名函数
   f3 := func(i, j int){
      fmt.Println(i, j)
   }
   f3(1, 2)

   //定义时同时调用
   func(i, j int){
        fmt.Println(i, j)
   }(10,20)

   //匿名函数,有参有返回值
   x, y :=func(i, j int) (max, min int) {
      if i>j{
         max = i
         min = j
      } else {
         max = j
         min = i
      }
      return
   }(10, 20)

   fmt.Println(x,y)
}

在匿名函数内修改外部变量仍同步修改,闭包以引用方式捕获外部变量

//闭包捕获外部变量的特点
func main() {
  a := 10
  str := "mike"

  func(){  //在匿名函数内修改外部变量仍同步修改
     //闭包以引用方式捕获外部变量
     a = 666
     str = "gogogo"
     fmt.Println(a, str)
  }()

  fmt.Println(a, str)
}

变量的生命周期不是由闭包的作用域决定,它不关心这些捕获了的变量和常量是否已经超出了作用域,所以只有闭包还在使用它,这些变量就还会存在。

func test01() int {
   //函数被调用时,x才分配空间,才初始化为0
   var x int
   x++
   return x*x  //函数调用完毕,x自动释放
}

//函数的返回值是一个匿名函数,返回一个类型
func test02() func() int{
   var x int   //没有初始化,值为0

   return func() int{
      x++
      return x*x
   }
}
func main() {
   //fmt.Println(test01())
   //fmt.Println(test01())
   //fmt.Println(test01())
   //fmt.Println(test01())

   //返回值为一个匿名函数,返回一个函数类型,通过f来调用返回的匿名函数
   //变量的生命周期不是由闭包的作用域决定
   f := test02()
   fmt.Println(f())  //1
   fmt.Println(f())  //4
   fmt.Println(f())  //9
   fmt.Println(f())  //16
}

获取命令行参数

package main

import (
   "fmt"
   "os"
)

func main() {
   //接收用户传递的参数,是以字符串方式传递
   list := os.Args

   n := len(list)
   fmt.Println("n = ", n)

   for i := 0; i < n;i++{
      fmt.Printf("list[%d] = %s\n",i,list[i])
   }

   for i, data := range list {
      fmt.Printf("list[%d] = %s\n",i,data)
   }
}

全局变量:定义在函数外部的变量是全局变量
局部变量:定义在{}里面的变量就是局部变量,只能在大括号内有效。执行到定义变量那句话,才开始分配空间,离开作用域自动释放
不同作用域允许定义同名变量,遵循就近原则
5.工作区
go代码必须放在工作区中,工作区其实就是一个对英语特定工程的目录
它包含三个子目录:src目录、pkg目录和bin目录

  • src目录:用于以代码包的形式组织并保存Go源码文件(比如:.go、.c、.h)。分文件编程(多个源文件),必须放在src目录。
    1)如果有多个文件或多个包,配置src同级目录的绝对路径。
    2)如果要自动生成pkg、bin目录。需要使用go install命令。除了要配置GOPATH环境变量,还要配置GOBIN环境变量

  • pkg目录:用于存放经由gp install命令构建安装后的代码包(包含go库源码文件)的".a"归档文件

  • bin目录:与pkg目录类似,在通过go install命令完成安装后,保存由go命令源码生成的可执行文件

分文件编程:

同级目录:

  • 同一个目录,包名必须一样
  • 同一个目录,调用别的文件的函数,直接调用即可,无需包名引用

不同级目录:

  • 不同目录,包名不一样
  • 调用不同包里面的函数,格式:包名.函数名()
  • 调用别的包的函数,这个包函数名字如果是小写,无法让别人调用;要想别人能调用,必须首字母大写

main函数和init函数执行流程:
先执行导入包中的函数,再执行init(),最后执行main()。但有时用户可能需要导入一个包,但是不需要引用这个包的标识符,在这种情况,可使用空白标识符_来重命名这个导入:

import _ "fmt"

猜你喜欢

转载自blog.csdn.net/weixin_43011810/article/details/84699375