在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,也可以重定义基本数据类型。

您可以选择一种方式赞助本站
支付宝扫一扫赞助
微信钱包扫描赞助
赏