函数
基本概念
基本语法

return

函数使用细节
- go函数形参和返回值列表都可以是多个、且数据类型可以是值类型也可以是引用类型
- 函数名首字母大写表示公有、小写表示私有
- 基本数据类型和数组都是值传递 (值拷贝),在函数内修改不会影响到原来的值

如果希望函数内修改函数外的值,需要使用指针,传递地址
func test1(x int){x++fmt.Printf("test1 : %d\n",x)}func test2(x *int){*x++fmt.Printf("test2 : %d\n",*x)}func main() {var x int = 10test1(x)fmt.Println(x)test2(&x)fmt.Println(x)}

go不支持函数重载
- 函数也是一种数据类型,可以赋值给一个变量,通过该变量就可以实现函数的调用 ```go func test1(x int){ x++ fmt.Printf(“test1 : %d\n”,x) } func main() { var func1 = test1 func1(100) }
//输出 test1 : 101
函数也可以作为一种形参,并且调用```gofunc test1(x int){x++fmt.Printf("test1 : %d\n",x)}func test2(add func(int),x int){add(x)}func main() {test2(test1,100)}//输出 test1 : 101
Go支持自定义数据类型
type mySum func(int,int) int //mySum等价于一个函数类型func(int,int) int
Go支持对函数返回值命名
func cal(n int,n2 int)(sum int,sub int){sum = n1 + n2sub = n1 - n2return}
可以用下划线 _ 忽略一个或多个返回值
- go 支持可变参数,放于参数列表最末
args… 数据类型 (args是slice切片,通过args[index]可以访问到各个值)
func sum(args... int){re := 0for i:=0;i< len(args);i++ {re += args[i]}fmt.Println(re)}func main() {sum(1,2,3,4,5,6,7)}// 输出 : 28
- 变量作用域
- 函数内部定义的变量叫局部变量,作用域仅在函数内部
- 函数外部定义的变量叫全局变量,作用域在整个包都有效,如果其首字母大写
则作用域在整个程序都有效。 - 如果一个变量在一个代码块,如for/if,那么这个变量的作用域在该代码块
init函数



通常可以在init函数中完成初始化工作
- 如果一个文件中包含全局变量定义、init函数、main函数,则执行流程为
全局变量定义=》init函数=》main函数


- 外部导入执行顺序

匿名函数
- 仅调用一次

- 通过变量多次调用

闭包
闭包就是一个函数与其相关的引用环境组合成一个整体
func AddUpper() func(int) int{var n = 10return func (x int) int {n = n + xreturn n}}func main() {f := AddUpper()fmt.Println(f(1))fmt.Println(f(2))fmt.Println(f(3))}//输出111316
理解:
var n = 10
return func (x int) int {
n = n + x
return n
}
就算是一个闭包。可以理解为: 闭包是类、函数是操作、n是字段。
案例:
只需要传递一次后缀返回闭包,不用每次都传递后缀。
func makeSuffix(suffix string) func(string) string{return func(name string) string {if strings.HasSuffix(name,suffix){return name}return name + suffix}}func main() {var myfun = makeSuffix("后缀")fmt.Printf(myfun("一个后缀")+"\n")fmt.Printf(myfun("一个前缀")+"\n")var myfun2 = makeSuffix("前缀")fmt.Printf(myfun2("一个后缀")+"\n")fmt.Printf(myfun2("一个前缀")+"\n")}
defer

//当执行到defer语句时,吧defer后面的语句加到独立的栈中(defer栈)//当函数执行完毕、或者发生异常时,会从栈中按照先入后出的方式出栈执行func sum(n1 int,n2 int) int{defer fmt.Println(n1)defer fmt.Println(n2)res := n1 + n2fmt.Println(res)return res}func main() {sum(10,20)}//输出302010
//当涉及到值的时候,当时的值也会被拷贝func sum(n1 int,n2 int) int{defer fmt.Println(n1)defer fmt.Println(n2)res := n1 + n2n1 = 0n2 = 0fmt.Println(res)return res}//输出302010
包

- 通常包名和其所在文件夹名一致
- 要使用其他包中的函数和路径时,要先引入对应的包 import
- package在文件第一行,然后是import指令
在import包时,路径从 $GOPATH 的 src下开始,不用带src,编译器自动从src下开始
package mainimport "go_code/package2"//引入外部函数func main() {package2.Add(50,60)}
大写函数为公有,小写函数为私有,跨包访问只能访问公有
别名可以给包起个别名,起别名后只能用别名访问
package mainimport nickname "go_code/package2"//别名func main() {nickname.Add(50,60)}
同一包下不可以有相同函数名
- 如果要编译成一个可执行文件,就需要将包名声明为main
在 GOPATH 目录进行 build 操作生成可执行文件 go build main包路径(从src下开始写路径)
配置路径 go build -o bin\my.exe(在GOPATH下的bin文件夹下生成my.exe) main包路径
