golang学习笔记系列之函数

golang学习笔记系列之函数,第1张

函数 golang函数简介

函数是go语言中的一级公民,我们把所有的功能单元都定义在函数中,可以重复使用。函数包含函数的名称,参数列表和返回值类型,这些构成了函数的签名。

golang中函数的特性
  • go语言中有3种函数:普通函数,匿名函数,方法(定义在struct上的函数)。
  • go语言中不允许函数重载(overload),也就是说不允许函数同名。
  • go语言中的函数不能嵌套函数,但可以嵌套匿名函数。
  • 函数是一个值,可以将函数赋值给变量,使得这个变量也成为函数。
  • 函数可以作为参数传递给另一个函数。
  • 函数的返回值可以是一个函数。
  • 函数调用的时候,如果有参数传递给函数,则先拷贝参数的副本,再将副本传递给函数。(值传递)
  • 函数参数可以没有名称。
golang中函数的定义和调用

函数在使用之前必须先定义,可以调用函数来完成某个任务。函数可以重复使用,从而达到代码重用。

语法

func function_name([parameter list])(return_types){
    //函数体
}
  • func:声明函数
  • function_name:函数名
  • [parameter list]:参数列表,参数就像一个占位符,当函数被调用时,你可以将值传递给函数,这个值被称为实际参数。参数列表指定的是参数类型,顺序及参数个数。参数是可选的,也就是说函数也可以不包含参数。
  • return_types:函数返回值的类型。
  • 函数体:函数的逻辑代码部分
//定义一个两数之和
func sum(a int,b int)(res int){
    res=a+b
    return res
}
golang函数的返回值

函数可以有0个或多个返回值,返回值需要指定数据类型,返回值通过return关键字来指定。

return可以有参数,也可以没有参数,这些返回值可以有名称,也可以没有名称。go中的函数可以有多个返回值。

  • return关键字中指定了参数时,返回值可以不用名称。如果return省略参数,则返回值部分必须带名称。
  • 当返回值有名称时,必须使用括号包围,逗号分隔,即使只有一个返回值。
  • 但即使返回值命名了,return中也可以强制指定其他返回值名称,也就是说return的优先级更高。
  • 命名的返回值是预先声明好的,在函数内部可以直接使用,无需再次声明。命名返回值的名称不能和函数参数名称相同,否则报错提示变量重复声明。
  • return中可以有表达式,但不能出现赋值表达式,这其他语言可能有所不同。例如可以:return a+b,但是不能:return a=b+c
package main

import "fmt"

//没有返回值
func foo1() {
	print("没有参数,也没有返回值!\n")
}

//有参数,没有返回值
func foo2(name string) {
	print("有一个参数:")
	fmt.Printf("name: %v\n", name)
}

//有参数,有返回值 且给返回值命名了
func foo3(name string, age int) (name2 string, age2 int) {
	name2 = name
	age2 = age
	return name2, age2
	// return    如果return不指定返回值,则默认返回上面定义的返回值
}

// 有参数,有返回值,但没有给返回值命名 这个时候就必须需要return来指定返回值
func foo4(name string, age int) (string, int) {
	return name, age

}

func main() {

	foo1()
	foo2("Tom")
	name2, age2 := foo3("Tom", 18)
	fmt.Printf("name2: %v\n", name2)
	fmt.Printf("age2: %v\n", age2)
	name, _ := foo4("Tom", 18)  //丢弃age
	fmt.Printf("name: %v\n", name)

}

运行结果

没有参数,也没有返回值!
有一个参数:name: Tom
name2: Tom
age2: 18
name: Tom

tips:

  • go中经常会使用其中一个返回值作为函数是否执行成功,是否有错误信息的判断条件。例如return value,exists;return value,ok(map中就是这样使用的);return value,err等
  • 当函数的返回值过多时,例如有4个以上的返回值,应该将这些返回值收集到容器中,然后以返回容器的方式去返回。
  • 当函数有多个返回值时,如果其中某个或几个返回值不想使用,可以通过下划线_来丢弃这些返回值。
golang函数的参数

go语言函数可以有0个或多个参数,参数需要指定数据类型。

声明函数时的参数列表叫做形参,调用时传递的参数叫做实参。

go语言是通过传值的方式传参的,意味着传递给函数的是拷贝后的副本,所以函数内部访问,修改的也是这个副本。(但是map,slice,interface,channel这些数据类型本身就是指针类型,所以就算是拷贝传值也是拷贝的指针,拷贝后的参数任然指向底层数据结构,所以修改它们可能会影响外部数据结构的值。)

go语言可以使用变长参数,有时候不能确定参数的个数时,可以使用变长参数,可以在函数定义语句的参数部分使用args…type的方式。这时会将…代表的参数全部保存到一个名为args的slice中,并且这些参数的数据类型都是type。

package main

import "fmt"

func test(a int) {
	a = 200
	fmt.Printf("里面的a: %v\n", a)
}

//两数之和
func sum(a int, b int) (c int) {
	c = a + b
	return
}

//...接收无数个参数
func foo(name string, age int, args ...string) {
	fmt.Printf("name: %v\n", name)
	fmt.Printf("age: %v\n", age)
	for _, v := range args {
		fmt.Printf("v: %v\n", v)
	}
}
func main() {

	a := 100
	test(a)
	fmt.Printf("外面的a=%v\n", a)

	res := sum(1, 2)
	fmt.Printf("res: %v\n", res)
	foo("Tom", 18, "Hello", "My", "name", "is", "Tom")

}

运行结果

里面的a: 200
外面的a=100
res: 3
name: Tom
age: 18
v: Hello
v: My
v: name
v: is
v: Tom
golang函数类型与函数变量

可以使用type关键字来定义一个函数类型,语法如下:

type fun func(par_type1,par_type2...) res_type1...
  • fun:自己定义的函数类型名
  • par_type1,par_type2…:表示各个参数的类型
  • res_type1…:表示各个返回值的类型
package main

import "fmt"

func sum(a int, b int) (c int) {
	c = a + b
	return
}

func main() {

	//自己声明函数的类型,然后再将函数赋值给一个变量
	type my_func func(int, int) int
	var my_sum my_func
	my_sum = sum
	res := my_sum(1, 2)
	fmt.Printf("res: %v\n", res)

	//直接通过短变量的形式将一个函数赋值给一个变量
	c := sum
	res2 := c(1, 2)
	fmt.Printf("res2: %v\n", res2)

}

运行结果

res: 3
res2: 3
高阶函数

go语言的函数,可以作为函数的参数,传递给另外一个函数,同时也可以作为函数的返回值返回。

函数作为参数和返回值
package main

import "fmt"

func sum(a int, b int) (c int) {
	c = a + b
	return
}

func sub(a int, b int) (c int) {
	c = a - b
	return
}

func test(a int, b int, f func(int, int) int) {
	res := f(a, b)
	fmt.Printf("%v+%v=res: %v\n", a, b, res)
}

func cal(flag string) func(int, int) int {
	switch flag {
	case "+":
		return sum
	case "-":
		return sub
	default:
		return sum
	}

}

func main() {

	//函数作为参数传给函数
	test(10, 20, sum)

	//函数作为返回值
	f_sum := cal("+")
	res := f_sum(1, 2)
	fmt.Printf("res: %v\n", res)

	f_sub := cal("-")
	res2 := f_sub(1, 2)
	fmt.Printf("res2: %v\n", res2)
}

运行结果

10+20=res: 30
res: 3
res2: -1
匿名函数

go语言函数不能嵌套,但是在函数内部可以定义匿名函数,实现一些简单的功能。所谓匿名函数,就是没有名称的函数。

语法

func ([参数列表])([返回值列表]){
    //函数体
}
package main

import "fmt"

func main() {

	//将匿名函数赋值给一个变量
	say_hello := func(name string, age int) {
		fmt.Printf("My name is  %v,And i',m %v old.\n", name, age)
	}
	say_hello("Tom", 18)

	//直接调用匿名函数
	func(words string) {
		fmt.Printf("words: %v\n", words)
	}("Hi,我是一个匿名函数!")

}

运行结果

My name is  Tom,And i',m 18 old.
words: Hi,我是一个匿名函数!
闭包

闭包就是延伸了函数作用于的函数,使得函数可以访问到函数体外的非全局变量。

package main

import "fmt"

//求平均值的闭包
func make_avger() func(int) float64 {

	s := make([]int, 0) 
    //对于下面的匿名函数来说,切片s就相当于函数体外的非全局变量
    //并且调用make_avager方法后,在全局中是访问不到切片s的
  

	return func(num int) float64 {
		s = append(s, num)
		sum := 0
		for _, v := range s {
			sum += v
		}
		return float64(sum / len(s))
	}

}
func main() {

	avg := make_avger()
	for i := 0; i < 10; i++ {
		fmt.Printf("%.2f\n", avg(i))

	}
}

运行结果

0.00
0.00
1.00
1.00
2.00
2.00
3.00
3.00
4.00
4.00
递归

函数内部调用函数自己的函数称为递归函数(同闭包一样,递归不是go语言特有的,而是go语言具备实现递归的条件)。

package main

//使用递归实现斐波那契数列
func fib(n int) int {
	if n == 1 || n == 2 {
		return 1
	} else {
		return fib(n-1) + fib(n-2)
	}
}

func main() {
	res := fib(10)
	print(res)
}

运行结果

102334155

同步更新于个人博客系统:golang学习笔记系列之函数

欢迎分享,转载请注明来源:内存溢出

原文地址:https://outofmemory.cn/langs/3002966.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-09-27
下一篇2022-09-27

随机推荐

  • 画个圈圈诅咒你是什么意思

    画个圈圈诅咒你,是一句网络用语,是‌‌‌‌‌‌‌‌‌‌‌‌喜羊羊系列动画中《古古怪界大作战》中的一颗蛋蛋,潇洒哥的口头禅。场景一般是,在潇洒哥得不到满足的时候,就会跑到角落画圈圈,说出这句经典台词。在

    2022-12-06
    100
  • j家步是什么意思

    j家步,指日本杰尼斯事务所旗下的男艺人们走路的姿态步伐。 j家步具体特征是:走路带风,摇曳生姿,风骚不露骨,优雅要带杀气。 j家步来源:Johnnys事务所所属艺人惯有的步伐,所以简称J家步,鼻祖是大

    2022-12-06
    000
  • 女菩萨什么意思网络用语

    女菩萨,指‌‌‌‌‌‌‌在社交媒体上传自己的色图美图的女性。因为满足了广大男性网友(你敢假定性别?)的欣赏欲和幻想而得到的称赞。有时也用作对路人女性的戏谑。那些晒性感身材、晒私房照、晒美腿、晒泳照等等

    2022-12-06
    000
  • be美学什么意思

    BE,在对游戏和文章讨论时应用(多用于网络),全写是Bad End 坏结局,与此相对的有 GE = Good End 好结局 SE=Sad End 悲伤的结局 和 HE = Happy End 开心、

    2022-12-06
    000
  • 断背

    断背,用来暗指两个男人之间的同性之爱。2007年8月由教育部公布的171新词之一,出自李安的同性爱题材电影《断背山》。电影《断背山》讲的是两个小伙子之间一段长达20年的感情纠葛。断背隐喻同性恋,现在网

    2022-12-06
    000
  • 火车站人工服务时间

    不一定,具体得看当地火车站的运营时间。对于一些大型火车站通常会设有24小时售票窗口,但也会有很多小火车站人工售票窗口营业时间是根据当地火车的运营时间来进行安排的,所以最好提前购票。火车站人工窗口是24

    2022-12-06
    000
  • 古代太医地位高吗

     古代太医的地位身份特殊,因为当时没有人不生病的,因此不能用地位高不高来形容。中国帝制几千年,太医院制度更是伴随帝制由来已久。虽然各个朝代名称有所不同,但是实际工作性质却是一样的。他们都是给人治病,所

    2022-12-06
    000
  • 本草纲目是谁写的

    《本草纲目》的作者是明代著名医学家李时珍。李时珍出生在一个医学世家,他的祖父和父亲都是一名医生,但是在当时那个时代,医生并不是一个非常受人尊重的职业,而且生活十分艰苦,因此他的父亲不想他做一名医生,而

    2022-12-06
    000
  • 打雷为什么会把电器打坏

    雷电具有静电功率损害和高压损害,大气产生强运动后,高压会通过电子设备的电源线,进行刹那间的强放电,最终造成电器设备内的电子元件内部击穿或者是熔融,最终造成了电器设备的永久性损坏。打雷是夏天很常见的一种

    2022-12-06
    000

发表评论

登录后才能评论

评论列表(0条)

    保存