Go语言学习(四)函数

一、golang函数

函数包括函数的名称、参数列表和返回值类型。这些构成了函数的签名

1.1go语言中函数特性

  1. go语言中有三种函数:普通函数匿名函数(没有名的函数)、方法(定义在struct上的函数)
  2. go语言中不允许函数重载,即不允许函数同名
  3. go语言中的函数不能嵌套函数,但可以嵌套匿名函数
  4. 函数是一个,可以将函数赋值给变量,使这个变量也成为函数
  5. 函数可以作为参数传递给另一个函数(因为函数是一个值)
  6. 函数的返回值可以是一个函数
  7. 函数调用的时候,如果有参数传递给函数,则先拷贝参数的副本,再将副本传递给函数
  8. 函数参数可以没有名称

1.2go语言中函数的定义和调用

1.2.1定义语法

func function_name( [ parameter list ] ) [return_types]{

      函数体

}

示例

package main

import (
	"fmt"
)
/*
函数
*/
func sum(a int,b int)(ret int){
	//参数 a,b;返回值 ret
	ret =a+b
	return ret
}
func comp(a int,b int)(maxNum int){
	if a>b{
		maxNum=a
	}else{
		maxNum=b
	}
	return maxNum
}

func main() {
	r:=sum(1,2)
	fmt.Printf("r:%v\n", r)
	r1:=comp(3,4)
	fmt.Printf("r1:%v\n", r1)

}

 1.3golang中的返回值的情况

  • 没有返回值
  • 有一个返回值
  • 有多个返回值
package main

import (
	"fmt"
)
/*
函数---返回值
*/

//没有返回值
func f1(){
	fmt.Println("没有返回值")
}
//有一个返回值  返回值可以给名称,也可以不给名称
func sum1(a int,b int)(ret int){
	ret=a+b
	return ret
}
func sum2(a int,b int)(int){
	ret:=a+b
	return ret
}
func sum3(a int,b int)(int){
	return a+b
}
//多个返回值
func f3()(name string,age int){
	name="tom"
	age=20
	return name,age
	//return   return=return name,age
}
//return可以覆盖命名返回值,返回值名称没有被使用
func f4()(name string,age int){
	n:="tom"
	a:=20
	return n,a
}


func main() {
	f1()
	name,age:=f3()
	fmt.Printf("%v %v", name,age)
	name1,age1:=f3()
	fmt.Printf("%v %v", name1,age1)




}

1.4参数的情况

  • go语言是通过传值的方式传参的,意味着传递给函数的是拷贝后的副本,所以函数内部访问、修改的也是这个副本。对于一般的数据类型,例如int、string来说,在函数中的改变不影响变量本身,但是对于slice、指针等引用数据类型,在函数中的改变也会改变该变量本身
  • go语言可以使用变长参数,使用args...type的方式,这是会将...代表的参数全部保存到一个名为ages的slice中,注意这些参数的数据类型都是type

示例

package main

import (
	"fmt"
)
/*
函数---参数
*/


func sum(a int,b int) int{
	return a+b
}
//参数的传递是传递值,
//也就是说在函数中改变的是参数的副本,不会改变变量本身
func f1(a int){
	a=200
}
//对于参数是指针、引用、切片等,都是指针类型,
//在函数中改变后,变量本身也改变
func f2(a []int){
	a[0]=100
}

//变长参数  必须是一个数据类型,使用...表示
func f3(args...int){
	for _, v := range args {
		fmt.Printf("%v\n", v)
	}
}
func f4(name string,ok bool,args...int){
	fmt.Printf("name:%v\n", name)
	fmt.Printf("ok:%v\n", ok)
	for _, v := range args {
		fmt.Printf("args:%v\n", v)
	}
}

func main() {
	r:=sum(1,2)
	fmt.Printf("%v\n", r)
	a:=100
	f1(a)
	fmt.Printf("%v\n", a) //100 说明不会改变
	var b=[]int{0,1,2,3}
	f2(b)
	fmt.Printf("%v\n", b) //[100 1 2 3] 说明改变了
	f3(1,2,3,4)
	f3(7,8,9)
	f4("zxx",true,1,2,3,4)
}

1.5函数类型和函数变量

可以使用type关键字来定义一个函数类型

type fun func(int,int) int

上面语句定义了一个fun函数类型,接受两个int类型的范数,并且返回一个int类型的返回值 

package main

import (
	"fmt"
)
/*
定义一个fun函数类型,把sum和max赋值给他
*/

//定义一个函数类型
type fun func(int,int) int
func sum(a int,b int)(ret int){
	//参数 a,b;返回值 ret
	ret =a+b
	return ret
}
func comp(a int,b int)(maxNum int){
	if a>b{
		maxNum=a
	}else{
		maxNum=b
	}
	return maxNum
}


func main() {
	var f fun   //f是一个fun类型的函数变量
	f=sum
	s:=f(1,2)
	fmt.Printf("%v\n", s) //3
	f=comp
	m:=f(4,5)
	fmt.Printf("%v\n", m) //5

}

1.6golang高阶函数

go语言中的函数,可以作为函数的参数,也可以作为另一个函数的返回值返回

package main

import (
	"fmt"
)
/*
golang高阶函数
*/

//go语言函数作为参数
func sayhello(name string){
	fmt.Println(name)
}
func f1(name string, f func(string)){
	f(name)
	fmt.Printf("%v", name)
}

//函数作为返回值
func add(a int,b int)int{
	return a+b
}
func sub(a int,b int)int{
	return a-b
}
//返回值是一个函数
func call(operator string) func(int,int) int{
	switch operator {
	case "+":
		return add
	case "-":
		return sub
	default:
		return nil
	}
}


func main() {
	f1("tom",sayhello) //直接给函数名称就可以了
	ff:=call("+")
	r:=ff(1,2)
	fmt.Printf("%v", r)
}

1.7golang匿名函数 

        go语言函数不能嵌套,但是在函数内部可以定义匿名函数,实现一下简单功能调用

所谓匿名函数就是没有名称的函数

语法格式:

func (参数列表)(返回值)

package main

import (
	"fmt"
)
/*
golang高阶函数
*/

func f1(){
	name:="zxx"
	age:="20"
	//匿名函数,在函数内部做一些运算
	f1:=func()string{
		return name+age
	}
	msg:=f1()
	fmt.Printf("%v", msg)
}

func main() {

	//匿名函数  用法一  没有函数名称
	max:=func(a int,b int) int{
		if a>b{
			return a
		}else{
			return b
		}
	}

	r:=max(1,2)
	fmt.Printf("%v\n", r)  //2

	 //用法二:自己调用自己
	 r1:=func(a int,b int) int{
		if a>b{
			return a
		}else{
			return b
		}
	 }(1,2)
	 fmt.Printf("%v\n", r1)

	 f1()

}

 1.8golang闭包

闭包可以理解为定义在一个函数内部的函数。在本质上,闭包是将函数内部和函数外部连接起来的桥梁。或者说是函数和引用环境的组合体  闭包=函数+引用环境

package main

import (
	"fmt"
)
/*
golang闭包
*/

func add()func(y int)int{
	//返回值是 func(y int)int 即形参是int,返回值是int的函数
	var x int
	return func(y int) int{
		x+=y
		return x
	}
}

func main() {
	f:=add() //调用add返回了一个函数,这个函数就是func(y int) int
	r:=f(10) //形参10,即y=10
	fmt.Printf("r:%v\n", r) //10
	r=f(20)
	fmt.Printf("r:%v\n", r) //30 之前的10被保存下来了,保存到x中
	r=f(30)
	fmt.Printf("r:%v\n", r) //60 30+30=60 只要这个函数一直存在,那么就会一直保存一个x
	fmt.Println("--------------------")
	f1:=add() //重新调用了一次 x中之前存在值就被清空了
	fmt.Println(f1(40))  //40
	fmt.Println(f1(50))  //90
}

进阶

package main

import (
	"fmt"
)
/*
golang闭包
*/
func cal(base int)(add func (a int)int,sub func (a int)int){
	add=func(i int)int{
		base+=i
		return base
	}
	sub=func(i int)int{
		base-=i 
		return base
	}
	return add,sub
}


func main() {
	add,sub:=cal(10)
	fmt.Printf("%v %v\n", add(1),sub(2)) //11 9
	fmt.Printf("%v %v\n", add(3),sub(1)) //12 11
}

1.9递归

package main

import (
	"fmt"
)
/*
golang递归
*/
func f1(){
	var s int = 1
	//阶乘的for实现
	for i := 1; i <=5; i++ {
		s*=i
	}
	fmt.Printf("%v\n", s)
}
//使用递归实现
func f2(a int) int{
	//返回条件
	if a==1{
		return 1
	}else{
		return a*f2(a-1)
	}
}

//斐波那契数列的实现
func f3(a int) int{
	if a==1||a==2{
		return 1
	}else{
		return f3(a-1)+f3(a-2)
	}
}
func main() {
	f1() //120
	r:=f2(5)
	fmt.Printf("%v\n", r) //120
	r1:=f3(10)
	fmt.Printf("%v\n", r1) //55
}

二、特殊语句

2.1defer语句

defer语句会将其后面跟随的语句进行延迟处理。在defer归属的函数即将返回时,将延迟处理的语句按defer定义的逆序进行执行。也就是说,先被defer的语句最后被执行,最后被defer的语句,最先被执行

2.1.1defer特性

2.1.2defer用途

package main

import (
	"fmt"
)
/*
defer
*/

func main() {
	fmt.Println("start")
	defer fmt.Println("step1")
	defer fmt.Println("step2")
	defer fmt.Println("step3")
	fmt.Println("end")
}
/*
start
end
step3
step2
step1

可以看到defer语句在return之前才会被执行,并且按照defer的先后逆序执行
*/

2.2init函数

先于main函数执行,实现包级别的一些初始化操作

2.2.1init函数的主要特点

示例函数

package main

import (
	"fmt"
)
/*
init
*/

//init初始化顺序:变量->init->main
var i int = initVar()
func init(){
	fmt.Println("init")
}

func initVar()int{
	fmt.Println("initVar")
	return 100
}
func main() {
	fmt.Println("main")
}
/*
initVar
init
main
可以看出init先于main执行
*/

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值