Golang基础函数

avatar 2020年5月2日18:52:17 评论 1,909 次浏览

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

avatar
  • 未经博主允许,禁止转载本博客任何内容,如需转载请留言,谢谢合作!!!
  • 转载注明:Golang基础函数 | 吴老二

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: