Golang 函数
基本语法
func (函数所属类型对象)函数名 (形参列表) 返回值{
//body
return 返回值
}
(函数所属类型对象)只有指定的类型对象采用调用该方法
-
不带返回值
func say(str string){ fmt.Println(str) } say("world")
-
带单个返回值
func Hello(a int32, b int32) int32{ return a+b } hello := Hello(10, 20)
-
带多个返回值
func number(a int, b int) (int, int) { return a, b } a, b := number(10, 20) c,_ := number(10,30) // _ 表示忽略返回的值
-
回调函数
//作为参数 func test1(num1 int, num2 int) int { return num1 + num2 } //和Js中调用回调函数相同 func test2(method func(int, int) int, a int, b int) int { return method(a, b) } func main() { i := test2(test1, 10, 20) fmt.Println(i) }
-
闭包
无返回值
func test2(a int, b int) func() { return func() { fmt.Println(a+b) } } func main() { f := test2(10, 20) f() }
有返回值
func test2(a int, b int) func(string) { return func(s string) { fmt.Println(s) fmt.Println(a+b) } } func main() { //作为返回值 f := test2(10, 20) f("hello world") }
init函数
每一个源文件都可以包含一个init
函数,该函数会在 main
函数之前执行,被Go运行框架调用
注意事项
如果一个文件同时包含全局变量定义,init函数和main函数
则执行的流行全局变量定义 -> init
函数 -> main
函数
//age := test() 不能被用作全局变量
var age = test() //和Java一样优先初始化成员变量,所以先调用test(),然后init()
func init() {
fmt.Println("invoke init")
}
func test() int {
fmt.Printf("invoke method")
return 100
}
func main() {
fmt.Println(age)
}
优先执行,导入包的变量定义和init
方法
匿名函数
func main() {
a:=10
//和Js中的匿名函数一样, 可以省去func的括号
res := (func(a int, b int) int {
return a + b
})(a, 20)
fmt.Println(res)
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
(func() {
fmt.Println("hello world")
})()
}
闭包
func method() func(int) int {
a := 10
return func(num int) int {
return a + num
}
}
func main() {
f := method()
fmt.Println(f(1)) // 11
fmt.Println(f(2)) // 13
fmt.Println(f(3)) // 16 a相当于method实例f的成员变量
}
注意事项
-
函数的形参列表可以是多个,返回值列表也可以是多个。
-
形参列表和返回值列表的数据类型可以是值类型和引用类型。
-
函数的命名遵循标识符命名规范,首字母不能是是数字,首字母大写该函数可以被本包文件和其他包文件使用,类似于
public
,首字母小写,只能被本包文件使用,其他包文件不能使用,类似private
-
函数中的变量是局部的,函数外不生效
-
如果参数类型相同,可以省略参数类型
func Method(a,b float64) float64{ return a + b } func main() { num:=Method(10.2,10.2) fmt.Println(num) }
-
基本数据类型和数组默认都是值传递,即进行值拷贝。在函数内修改,不会影响到原来的值
-
如果希望函数内的变量能修改函数外的变量(指的是默认以值传递的方式的数据类型),可以传入变量的地址
&
,函数内以指针的方式操作变量。func test(a *int)*int{ *a = 30 //使用指针访问地址 return a } i := 20 test(&i) fmt.Println(i)//30
-
Go函数不支持重载
-
函数也是一种数据类型
func test(a int,b int)int{ return a+b } func main() { //和Js中相似, 函数是reference a := test fmt.Println(a(30 ,50))// 调用函数 fmt.Printf("a的类型为%T",a) fmt.Printf("test的类型为%T",test) }
-
支持对函数返回值命名
func method(a uint32, b uint32) (res uint32, tmp int) { res = a + b //自动返回res tmp = int(a+b) return } func main() { res, tmp := method(10, 10) //相当于Java System.err.print() print(res,tmp) }
-
使用
_
表示符,忽略返回值func main() { //忽略返回值中err num, _ := strconv.ParseInt("110", 2, 64) fmt.Println(num) }
-
支持可变参数
args
是slice
切片,通过args[index]
可以访问到各个值- 如果一个函数的形参列表中有可变参数,则可变参数需要放在列表的最后
//本质是切片,和Js中相似 func function(args... int){ fmt.Println("args = ",args) fmt.Println("len = ",len(args))//本质是一个数组 for i := 0; i < len(args); i++ { fmt.Printf("args[%d] = %d ",i,args[i]) } } func main() { function(1,2,3,4) }