在go中函数是一个基本的代码块,用于执行一个任务。可以根据不同的功能,来划分不同的功能,逻辑上每个函数执行的都是指定任务,至少有一个函数就是main(),函数申明了编辑器函数的名称,返回类型,和参数。不过go也有很多内置函数,例如:len()函数可以返回类型的长度。如果传入的是字符串则返回字符串的长度。传入的是数组,就返回数组的元素个数。
函数的定义
函数语法:
func function_name( [parameter list] ) [return_types] { 函数体 }
解析:
* func 函数有func开始申明 * function_name 函数名称,函数吗和参数列表一起构成了函数的签名。 * parameter list 参数列表,参数就像一个占位符,当函数被调用时,你可以将值传递给参数,这个值被称为实际参数,参数列表指定的参数类型、顺序、及参数个数。参数时可选的,也就是函数可以包含参数。 * return_types 返回类型,函数返回一列值,return_types是该值的数据类型,有些功能不需要返回值,这种情况下return_types不是必须的, * 函数体 函数定义的集合
下面看个例子,比较两个值的大小:
package main //函数对比两个数的大小 //个人博客 http://www.wulaoer.org import "fmt" func main() { var a int = 100 //申明两个变量的值 var b int = 200 //申明两个变量的值 var set int //申明数据类型 set = max(a,b) //调用对比数值大小函数,并发结果返回给变量 fmt.Print("对比后最大的值是:",set) } func max(num1,num2 int) int { //定义对比函数的名称和对比变量的数据类型 var ret int //定义数据类型 if ( num2 > num2 ) { //判断两个变量的大小 ret = num2 //把最大的变量赋值给变量 } else { ret = num1 // } return ret }
打印结果:
对比后最大的值是:100
使用字符举个例子,说说那个语言是世界上最好的语言:
package main import "fmt" //个人博客 http://www.wulaoer.org func main() { var a string = "Python" var b string = "Golang" var set string set = str(a,b) //换一下位置可能就不一样了哦 fmt.Print(set) } func str(num1,num2 string) string { var ret string ret = num1 + "是世界上最好的语言," + num2 + "不是" return ret }
打印结果:
Python是世界上最好的语言,Golang不是
函数返回多个值
//个人博客 http://www.wulaoer.org func main() { a, b := swap("baidu","google") fmt.Println(a, b) } func swap(num1, num2 string) (string, string1 string) { //这里需要注意当函数中有几个参数时,后面需要跟进几个数据类型 return num2, num1 }
打印结果:
google baidu
下面看一个函数返回多类型的例子:
package main //个人博客 http://www.wulaoer.org import "fmt" func swap(x, y string,z int) (string, string,int) { //这里应该会注意到后面参数的数据类型随着前面的参数而变化 return y, x,z } func main() { a, b, c := swap("google", "baidu", 51200) fmt.Println(a, b,c) }
打印结果:
baidu google 51200
函数参数
函数参数分为形参和实参,形参简单的说就是一个变量,实参可以理解为数值。
形参:只有在函数被调用时才会分配内存,调用结束后,立刻释放内存,所以形参变量只有在函数内部有效,不能在函数外部使用。
实参:可以是常量、变量、表达式、函数等,无论实参是何种类型的数据,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参,所以应该提前用赋值、输入等办法使实参获得确定值。
形参和实参在数量、类型、顺序上必须严格一致,否则会发生“类型不匹配”的错误,当然,如果能够进行自动类型切换,或者进行了强制类型转换,那么实参类型也可以不同于形参类型。
函数在调用的过程中发生的数据传递是单向的,只能把实参的值传递给形参,而不能把形参的值反向地传递给实参;换句话说,一旦完成数据的传递,实参和形参酒再也没有瓜葛了,所以,在函数调用过程中,形参的值发生改变不会影响实参。
值传递
值传递就是在调用函数时将实际参数复制一份传递到函数中,这样函数中对参数进行修改,不会影响到实际参数。下面看几个例子:
package main //个人博客 http://www.wulaoer.org import "fmt" func split(x,y int) (num,num1 int) { var temp int temp = x x = y y = temp return x,y } func main() { var a = 10 var b = 20 fmt.Println("交换前a的值",a) fmt.Println("交换前b的值",b) fmt.Println(split(a,b)) //调用交换函数,根据位置两个变量的值交换 fmt.Println("交换后a的值",a) fmt.Println("交换后b的值",b) }
打印结果:
交换前a的值 10 交换前b的值 20 20 10 交换后a的值 10 交换后b的值 20
引用传递
引用传递就是把实际参数的内存地址传递到函数中,这样在对参数进行修改的过程中会影响到实际参数,但是参数的内存地址不变。
package main import "fmt" //个人博客 http://www.wulaoer.org func swap(x *int, y *int) (num1,num2 int) { var temp int fmt.Println("打印内存地址x",x) fmt.Println("打印内存地址y",y) temp = *x *x = *y *y = temp fmt.Println("打印内存地址x",x) fmt.Println("打印内存地址y",y) return *x,*y } func main() { var a = 10 var b = 20 fmt.Println("交换前a的值",a) fmt.Println("交换前b的值",b) fmt.Println(swap(&a,&b)) //调用交换函数 fmt.Println("交换后a的值",a) fmt.Println("交换后b的值",b) }
也可以这样写:
func main() { var a = 10 var b = 20 fmt.Println(a,b) a,b = b,a fmt.Println(a,b) }
打印结果:
交换前a的值 10 交换前b的值 20 打印内存地址x 0xc000094000 打印内存地址y 0xc000094008 打印内存地址x 0xc000094000 打印内存地址y 0xc000094008 20 10 交换后a的值 20 交换后b的值 10
一般都是使用值传递,不会影响到实际参数的调用。
函数用法
一个函数作为另一个函数的实参
函数是用来对参数的一种操作,并作为另一函数的实参,下面看个例子定义函数中初始化一个变量,该函数不仅仅为了使用内置函数math.sqrt(),实例为:
package main //个人博客 http://www.wulaoer.org import ( "fmt" "math" ) func main() { //申明函数变量 getSquareRoot := func(x float64) float64 { return math.Sqrt(x) //math.Sqrt(x)就是对x进行开方 } //调用函数 fmt.Println(getSquareRoot(2)) }
打印结果:
1.4142135623730951
函数作为参数,然后调用传入的函数
package main import "fmt" //个人博客 http://www.wulaoer.org // 声明一个函数类型 type cb func(int) int func main() { testCallBack(9, callBack) testCallBack(2, func(x int) int { fmt.Printf("我是回调,x:%d\n", x) return x }) } func testCallBack(x int, m cb) { //把函数错位参数传入函数,然后调用传入的函数 m(x) } func callBack(x int) int { fmt.Printf("我是回调,x:%d\n", x) return x }
打印结果:
我是回调,x:9 我是回调,x:2
math包的常用方法:
package main //个人博客 http://www.wulaoer.org import ( "fmt" "math" ) func main() { /* math包: */ i := -100 fmt.Println(math.Abs(float64(i))) //绝对值 fmt.Println(math.Ceil(5.0)) //向上取整 fmt.Println(math.Floor(5.8)) //向下取整 fmt.Println(math.Mod(11, 3)) //取余数,同11%3 fmt.Println(math.Modf(5.26)) //取整数,取小数 fmt.Println(math.Pow(3, 2)) //x的y次方 fmt.Println(math.Pow10(4)) // 10的n次方 fmt.Println(math.Sqrt(8)) //开平方 fmt.Println(math.Cbrt(8)) //开立方 fmt.Println(math.Pi) }
打印结果:
100 5 5 2 5 0.2599999999999998 9 10000 2.8284271247461903 2 3.141592653589793
闭包
go支持匿名函数,可作为闭包。匿名函数是一个“内联”语句表达式,匿名函数的优越性在于可以直接使用函数内的变量,不必申明。下面创建了一个函数getvars(),返回另一个函数。该函数的目的是在匿名函数中递增变量i的值。
package main import "fmt" //个人博客 http://www.wulaoer.org //创建函数,返回一个函数 func getvars() func() int { //申明一个变量 i := 0 //创建一个返回的函数 return func() int { //在创建的函数中对变量进行处理 i += 1 //返回变量 return i } } func main() { //申明一个函数给变量 newvar := getvars() //打印变量就是调用函数 fmt.Println(newvar()) fmt.Println(newvar()) fmt.Println(newvar()) //什么第二个函数给变量 newvar1 := getvars() fmt.Println(newvar1()) fmt.Println(newvar1()) fmt.Println(newvar1()) }
打印结果:
1 2 3 1 2 3
在闭包中传入函数作为参数,返回参数作为函数的变量
//add_mo是主函数,后面跟的是嵌套函数 //个人博客 http://www.wulaoer.org func add_mo(x1,x2 int) func(x3,x4 int) (int,int,int) { i := 0 //申明变量 return func(x3 int,x4 int) (int,int,int) { //x3,x4是传入的参数,后面括号的int是定义返回的数据类型。 i ++ //变量自增 return i,x1+x2,x3+x4 //返回函数值 } } func main() { add_func := add_mo(1,2) //定义的是外层函数的参数 fmt.Println(add_func(3,4)) //嵌套函数的参数 fmt.Println(add_func(0,1)) //嵌套的函数参数 fmt.Println(add_func(5,9)) //嵌套的函数参 }
打印结果:
1 3 7 2 3 1 3 3 14
方法
在go语言中有函数和方法,一个方法就是一个包含接受者的函数,接受者可以是命名类型或者结构类型的一个值或者一个指针,所有给定类型的方法属于该类型的方法集。语法格式如下:
func (variable_name variable_data_type) function_name() [return_type]{ /* 函数体*/ }
看下面的例子:
package main //个人博客 http://www.wulaoer.org import ( "fmt" ) /* 定义结构体 */ type Circle struct { radius float64 } func main() { var c1 Circle c1.radius = 10.00 fmt.Println("圆的面积 = ", c1.getArea()) } //该 method 属于 Circle 类型对象中的方法 func (c Circle) getArea() float64 { //c.radius 即为 Circle 类型对象中的属性 return 3.14 * c.radius * c.radius }
打印结果:
面积是: 314
函数和方法的区别
方法func后面的关键字是接收者不是函数名,接受者是自己定义的类型,可以是struct、interface,也可以重定义基本数据类型。
您可以选择一种方式赞助本站
支付宝扫一扫赞助
微信钱包扫描赞助
赏