函数
函数定义格式
func FuncName(/参数列表/)(o1 type,o2 type/返回类型/){
//函数体
return v1,v2 //返回多个值
}
自定义函数
无参无返回值
func MyFunc(){
a:=666
fmt.Println(“a=”,a)
}
func main(){
MyFunc() //调用方法
}
有参无返回值
//定义函数时,在函数名后面()定义的参数叫形参
//参数传递,只能由实参传递给形参,不能反过来,单向传递
func MyFunc(a int){
//a=111
fmt.Println(“a=”,a)
}
func main(){
MyFunc(666) //调用函数输入的666为实参
} //输出结果为666
不定参数
func MyFunc(a int,b int){ //固定参数
}
//像…int类型这样的类型,…type不定参数类型
func MyFunc(arge …int){//传递的实参可以是0个或多个
fmt.Println(“len(args) =”,len(args))//获取用户传递参数的个数
for i:=0;i<len(args);i++{
fmt.Printf(“args[%d]=%d/n”,i,args[i])
}
//迭代,返回两个值,第一个是下标,第二个是下标所对应的数
fori,data:=range args{
fmt.Printf(“args[%d]=%d/n”,i,args[i])
}
}//不定参数只能放在形参之后的最后一个参数
//固定参数一定要传参,不定参数根据需求
go语言函数作为实参
Go 语言可以很灵活的创建函数,并作为另外一个函数的实参。以下实例中我们在定义的函数中初始化一个变量,该函数仅仅是为了使用内置函数
package main
import (
“fmt”
“math”
)
func main(){
/* 声明函数变量 */
getSquareRoot := func(x float64) float64 {
return math.Sqrt(x)
}
/* 使用函数 */
fmt.Println(getSquareRoot(9))
}
运行结果为3
函数调用流程
函数调用流程:先调用后返回,先进后出
函数递归,函数调用自己本身,利用此特点
函数类型
起别名
(1)函数也是一种数据类型,通过type给一个函数类型起别名
比如:func Add(a,b int) int {
return a+b
}
type FuncType func(int,int)int //没有函数名,没有{}
var a FuncType //声明一个函数类型的变量,变量名为a
a=Add
result=a(10,20)
fmt.Println(“result=”,result)
//运行结果为30
回调函数
//回调函数,函数有一个参数是函数类型,这个函数就是回调函数
//计算器,可以进行四则运算
//多态,多种形态,调用同一个接口,不同的表现,可以实现不同表现,加减乘除
//先有想法,后面再实现功能
type FuncType func(int int) int
func Add(a,b int) int{
return a+b
}
func Calc(a,b int,fTest FuncType)(result int){
fmt.Println(“Calc”)
result = fTest(a,b) //这个函数还没有实现
//result=Add(a,b) //Add()必须先定义后,才能调用,如果直接使用这个语句,整个程序就直接被写死了。
return
}
func main(){
a:=Calc(1,1,Add)
fmt.Println(“a=”,a)
}
//运行结果为2
匿名函数和闭包
匿名函数和闭包 闭包捕获外部变量的特点:以引用变量捕获外部变量,内部变量改,外部也会改。
func main(){ 闭包的特点:它不关心这些捕获了的变量和常量是否已经超出了作用域,所以只要闭包
a:=10 还在使用它,这些变量就会一直存在。
str :=“mike”
- f1 :=func(){ //:=自动推导类型
fmt.Println(“a=”,a)
fmt.Println(“str =”,str)
}//匿名函数调用a和str,就是闭包
f1()//不常用
//定义匿名函数,同时调用
2.func(){
fmt.Printf(“a=%d,str=%s\n”,a,str)
}() //后面的()代表调用此匿名函数 //常用
}
defer
(1)defer用于延迟一个函数或者方法(或者当前所创建的匿名函数)的执行。注意:defer语句只能出现在函数或方法的内部。在main结束前调用
defer fmt.Println(“bbbbbbb”)
fmt.Println(“aaaaaaaa”)
输出结果为:aaaaaaaa
bbbbbbb
fmt.Println(“bbbbbbb”)
fmt.Println(“aaaaaaaa”)
输出结果为:bbbbbbb
aaaaaaaa
(2)多个defer的执行顺序
如果一个函数中有多个defer语句,会以先进后出的顺序执行,先defer的后输出,哪怕函数或某个延迟调用发生错误,这些调用依旧会被执行。
(3)defer和匿名函数结合使用
func main(){
a:=10
b:=20
defer func(){
fmt.Printf(“a=%d,b=%d\n”,a,b)
}()//()表示调用此匿名函数
a=111
b=222
fmt.Printf(“a=%d,b=%d\n”,a,b)
}
//输出结果为a=111,b=222,a=111,b=222
这是因为下面的a和b的值已经改变了,又因为defer把第一个输出语句延迟了,所以输出的也是111和222.
func main(){
a:=10
b:=20
defer func(a,b int){
fmt.Printf(“a=%d,b=%d\n”,a,b)
}(a,b)//()表示调用此匿名函数,把参数传递过去,已经先传递参数,只是没有调用
a=111
b=222
fmt.Printf(“a=%d,b=%d\n”,a,b)
}
//输出结果为a=111,b=222,a=111,b=222
作用域
(1)局部变量:定义在{}里面的变量就是局部变量,只能在{}里面起作用
作用域:变量作用的范围
(2)全局变量:定义在函数外面的变量是全局变量,全局变量在任何地方都可以使用。
(3)不同作用域同名变量:不同作用域允许定义同名变量。
使用变量的原则,就近原则。
包
(1)点操作
import(
“.fmt”
)
func main(){
Println(“hello”)
}
(2)别名操作
import(
io"fmt"
)
func main(){
io.Println(“hello”)
}
(3)_操作
引用该包,调用这个包里面的init函数,其他的不调用