GO语言基础(二)函数

1.函数基本结构

func   FuncName(参数列表) (返回类型){

           函数体

            return

}

GO语言基础(二)函数_第1张图片

2.无参无返回值函数和无参有返回值函数

package main

import (
	"fmt"
)

//无参无返回值函数
func Display() {
	fmt.Printf("hello go\n")
}

//无参有返回值函数
func Test1() int { //当只有一个返回值时可以不写括号
	return 666 //return后面接的是要返回的值,多个值之间用逗号隔开
}
func Test2() (i int) { //可以在返回值列表中注明返回值名称
	i = 10 //一个return即可返回所有要返回的值
	return
}
func Test3() (i int, j int) { //可以返回多个值
	i, j = 10, 20
	return
}
func Test4() (int, float64) { //返回值的类型不限
	return 10, 20.2
}

func main() {
	Display()
	var (
		a, b, c, d, e int
		f             float64
	)
	a = Test1()
	b = Test2()
	c, d = Test3()
	e, f = Test4()
	fmt.Println("——————————————无参无返回值函数—————————————")
	fmt.Println("a=", a)
	fmt.Println("b=", b)
	fmt.Println("c=", c, "	d=", d)
	fmt.Println("e=", e, "	f=", f)
	fmt.Println("———————————————————————————————————")
}

输出:

GO语言基础(二)函数_第2张图片

3.有参无返回值函数

package main

import (
	"fmt"
)

//有参无返回值函数
func Add(a int, b int) {
	//func Add(a,b int){   也可以这样写
	var sum int
	sum = a + b
	fmt.Println("a+b=", sum)
}

func main() {
	Add(10, 20)
}

输出:

4.不定参数列表

当不确定传入参数个数时使用

package main

import (
	"fmt"
)

//有参无返回值函数,求用户输入所有数字之和
//...Type为不定参数类型,传入的参数可以是0个或多个
//不定参数只能放在形参的最后一个参数
func Add(args ...int) {
	var sum int
	for _, data := range args {   //注意这一块的data不需要定义
		sum += data
	}
	fmt.Println("sum=", sum)
}

func main() {
	Add(10, 20, 30, 40, 50)
}

不定参数的传递:

package main

import (
	"fmt"
)

//有参无返回值函数,求用户输入所有数字之和
//...Type为不定参数类型,传入的参数可以是0个或多个
//不定参数只能放在形参的最后一个参数
func Add(args ...int) {
	var sum int
	for _, data := range args { //注意这一块的data不需要定义
		sum += data
	}
	fmt.Println("sum=", sum)
}

func test(tmp ...int) {
	Add(tmp...)     //将所有参数传递给tmp
	Add(tmp[2:]...) //将第三个数字及后面的数字传递给Add
}

func main() {
	test(10, 20, 30, 40, 50)
}

输出:

5.有参有返回值函数

package main

import (
	"fmt"
)

//有参有返回值
func Add(a, b int) (sum int) {
	sum = a + b
	return
}

func main() {
	sum := Add(10, 20) //使用sum接收返回值
	fmt.Println("sum=", sum)
}

6.函数类型

package main

import (
	"fmt"
)

//函数也是一种类型,通过type给一个函数类型起名
type FuncName func(int, int) int //FuncName为一个函数类型,没有函数名称和{}

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

func Minus(a, b int) int {
	return a - b
}

func main() {
	var ftest FuncName //定义函数类型变量ftest
	ftest = Add        //ftest的值为函数Add,也就只说调用ftest就等同于调用Add
	sum := ftest(10, 20)
	fmt.Println("sum=", sum)
	ftest = Minus
	sum = ftest(50, 20)
	fmt.Println("Minus=", sum)
}

7.回调函数

package main

import (
	"fmt"
)

//函数也是一种类型,通过type给一个函数类型起名
//FuncName为一个函数类型,没有函数名称和{}
type FuncName 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 FuncName) (result int) {
	fmt.Println("Calc")
	result = fTest(a, b)
	return
}

func main() {
	sum := Calc(10, 20, Add)
	fmt.Println("sum=", sum)

	sum = Calc(50, 20, Minus)
	fmt.Println("Minus=", sum)
}

8.匿名函数和闭包

  • 所谓闭包就是一个函数“捕获”了和它在同一个作用域的其他常量和变量。这就意味着当闭包被调用的时候,不管在程序什么地方调用,闭包能够使用这些变量和常量。他不关心这些捕获了的变量或常量是否已经超出了作用域,所以只要闭包还在使用它,这些变量就还会存在。在go语言中,所有的匿名函数都是闭包,匿名函数是指不需要定义函数名称的一种函数实现方式。
package main

import (
	"fmt"
)

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

	//无参无返回值
	func() {
		fmt.Println("i=", i)
		fmt.Println("str=", str)
	}() //后面的()表示调用匿名函数
	//有参无返回值
	func(i, j int) {
		fmt.Println("i=", i, "	j=", j)
	}(10, 20)
	//无参有返回值
	z := func() int {
		return 666
	}()
	fmt.Println("z=", z)
	//有参有返回值
	max, min := func(i, j int) (max, min int) {
		if i > j {
			max = i
			min = j
		} else {
			max = j
			min = i
		}
		return
	}(20, 30)
	fmt.Println("max=", max, "	min=", min)
}

闭包捕获参数的特点:

package main

import (
	"fmt"
)

func main() {
	i := 10
	str := "mike"
	//闭包是以引用方式捕获外部变量
	func() {
		i = 666
		str = "go"
		fmt.Println("外部:i=", i, "  str=", str)
	}()
	fmt.Println("内部:i=", i, "  str=", str)
}

输出:

package main

import (
	"fmt"
)

//函数的返回值是一个匿名函数
func test() func() int {
	var x int //没有初始化,值为0
	return func() int {
		x++
		return x * x
	}
}

func main() {
	//返回值为一个匿名函数,返回一个函数类型,通过f调用匿名函数
	//他不关心这些捕获了的变量或常量是否已经超出了作用域
	//所以只要闭包还在使用它,这些变量就还会存在
	f := test()
	fmt.Println(f())
	fmt.Println(f())
	fmt.Println(f())
	fmt.Println(f())
}

输出:

GO语言基础(二)函数_第3张图片

9.defer语句

defer用于延迟一个函数或者方法的执行。

多个defer同时使用遵寻FILO原则

10.defer与匿名函数结合使用

package main

import (
	"fmt"
)

func main() {
	i, j := 10, 20
	defer func(i, j int) {
		fmt.Printf("内部:i=%d,j=%d\n", i, j)
	}(i, j) //把参数传递过去,先不调用,相当于(10,20)
	i, j = 111, 222
	fmt.Printf("外部:i=%d,j=%d\n", i, j)
}

输出:

11.获取命令行参数

package main

import (
	"fmt"
	"os" //调用os包
)

func main() {
	args := os.Args                 //获取命令行参数,命令行参数都是以字符串的方式进行接受的。
	n := len(args)                  //获取命令行参数的个数
	for index, data := range args { //遍历命令行参数方法一
		fmt.Printf("args[%d]=%s\n", index, data)
	}
	for i := 0; i < n; i++ { //遍历命令行参数方法二
		fmt.Println(args[i])
	}
}

输出:
GO语言基础(二)函数_第4张图片

12.GOPATH的设定

  • 为了能够构建这个工程,需要先把所需工程目录加入到环境变量GOPATH中。否则,即使处于同一工作目录(工作区)代码之间也无法通过绝对代码包路径完成调用。
  • 在实际开发环境中,工作目录往往有多个,多个工作目录的目录路径都需要添加至GOPATH。当有多个目录时,请注意分隔符,多个目录的时候windows是分号,Linux是冒号,当有多个GOPATH时,默认会将go get的内容放在第一个目录下。

13.包

所有GO语言的程序都会组织成若干组文件,每组文件被称为一个包。这样每个包的代码都可以作为很小的复用单位,被其他项目引用。一个包的源代码保存在一个或者多个以.go文件后缀名的源文件中,通常一个包所在目录路径的后缀是包导入的路径。

14.自定义包

      对于一个较大的应用程序,我们应该将他的功能分割成逻辑单元,分别在不同的包里实现,我们创建的自定义包最好放在GOPATH的str目录下(或者GOPATH src的某个子目录)。
      在GO语言中,代码包中的源码文件名可以是任意的。但是,这些任意名称的源码文件都必须以包声明语句作为文件中的第一行,每个包都对应一个独立的名字空间。
       包中成员以名称大小写决定访问权限:

  • public:首字母大写,可被包外访问
  • private:首字母小写,仅包内成员可以访问。

注意:同一个目录下不能定义不同的package。

附加:

调用包的方式:

  1. import    .     "fmt"    报名前加点表示使用包里面的函数可以直接使用函数名,必须要加报名,如Println("hello go")   

  2. import   _     "fmt"    下滑线表示调用包而不使用包,即调用后不适用编译不会报错,该操作其实是不直接调用该包里面的函数,而是调用了该包里面的init函数。

  3. import   NewName   "fmt"    给包起别名。   

15.main函数和init函数

     在go语言中,命名为main的包具有特殊的含义。go语言的编译程序会试图把这种名字的包编译为二进制可执行文件。所有用go语言编译的可执行程序都必须有一个名叫main的包。一个可执行程序有且仅有一个main包。当编译器发现某个包的名字为main是它也会发现名为main()的函数,某则不会创建可执行文件。main()函数是程序的入口,所以,如果没有这个函数,程序就没有办法喀什执行。程序编译时,会使用声明为main包的代码所在的目录名作为二进制可执行文件的文件名。

       go语言中有两个保留的函数:init函数(能够应用于所有的package)和main函数(只能应用于package main)。这两个函数在定义时不能有任何的参数和返回值。虽然一个package里面可以写任意多个init函数,但这无论是对于可读性还是以后的可维护性来所,我们都强烈建议一个package中每个文件中只写一个init函数。

       每个包可以包含任意多个init函数,这些函数都会在程序执行开始的时候被调用。所有被编译器发现的init函数都会安排在main函数之前执行。init函数用在设置包、初始化变量或者其他要在程序运行前优先完成的引导工作。

16.工程管理

【1】同级目录

  • 分文件编程(多个源文件),必须放在src目录。
  • 设置GOPATH环境变量
  • 同一个目录,包名必须一样
  • go  env查看GO相关的环境路径
  • 同一个目录,调用别的文件的函数,直接调用即可,无需包名引用。

例子:

在GOPATH底下的src目录里面创建两个go文件:

文件内容:

package main  //文件test.go

import (
	"fmt"
)

func test() {
	fmt.Println("hello go")
}
package main   //文件main.go

func main() {
	test()
}

在liteide中通过Ctrl  +  R执行结果:

GO语言基础(二)函数_第5张图片

【2】不同级目录

  • 不同目录包名不一样
  • 调用不同包里面的函数,格式为:包名.函数名(args)
  • 调用别的包的函数,函数名首字母大写才可以调用,小写不能调用。

例子:
目录结构:

C:\GOPATH\src\不同级目录\src\main.go

C:\GOPATH\src\不同级目录\src\calc\calc.go                      

文件内容:

package main  //main.go

import (
	"calc"
	"fmt"
)

func main() {
	sum := calc.Add(10, 20)
	fmt.Printf("sum=%d\n", sum)
}
package calc  //calc.go

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

执行结果:

GO语言基础(二)函数_第6张图片

17.go install命令使用

  1. 配置GOPATH和GOBIN环境变量
  2. 进入src目录执行go install
  3. 系统自动生成bin和pkg目录

你可能感兴趣的:(#,Go基础教程)