>

如果我们传入的是字符串则返回字符串的长度,

- 编辑:澳门博发娱乐官网 -

如果我们传入的是字符串则返回字符串的长度,

Go中等高校函授数本性简要介绍

对Go中的函数性子做一个总括。懂则看,不懂则算。

  1. Go中有3种函数:普通函数、无名氏函数、方法(定义在struct上的函数)。
  2. Go编写翻译时不在乎函数的概念地点,但提议init()定义在最前头,main函数定义在init()之后,然后再依靠函数名的字母顺序或许依照调用顺序放置各函数的地方。
  3. 函数的参数、重返值以及它们的品类,结合起来成为函数的签订左券(signature)。
  4. 函数调用的时候,假使有参数字传送递给函数,则先拷贝参数的别本,再将别本传递给函数。
    • 出于援引类型(slice、map、interface、channel)本身就是指针,所以那些类别的值拷贝给函数参数,函数内部的参数照旧指向它们的底层数据结构。
  5. 函数参数能够没盛名称,举例func myfunc
  6. Go中的函数能够用作一种type类型,比方type myfunc func int
    • 实则,在Go中,函数自己就是一体系型,它的signature便是所谓的type,比如func int。所以,当函数ab()赋值给一个变量ref_abref_ab := ab,不能够再将其余函数类型的函数cd()赋值给变量ref_ab
  7. Go中作用域是词法功能域,意味着函数的定义地方决定了它能瞥见的变量。
  8. Go中不允许函数重载,也便是说不容许函数同名。
  9. Go中的函数不可能嵌套函数,但足以嵌套佚名函数。
  10. Go实现了拔尖函数(first-class functions),Go中的函数是高阶函数(high-order functions)。那表示:
    • 函数是贰个值,能够将函数赋值给变量,使得那个变量也改成函数
    • 函数能够用作参数字传送递给另三个函数
    • 函数的重回值能够是三个函数
    • 这个特征使得函数变得最棒的灵巧,比方回调函数、闭包等等功用都注重于这几个特色。
  11. Go中的函数不援助泛型,但倘使必要泛型的气象,大多数时候都得以由此接口、type switch、reflection的点子来缓和。但使用这么些技术驱动代码变得更头眼昏花,品质更低。

1.函数声称:

golang基础之函数

目录

Go 语言函数

函数是中央的代码块,用于施行二个职分。

Go 语言最少有个 main() 函数。

您能够通过函数来划分不一样效能,逻辑上各种函数施行的是钦定的职分。

函数注明告诉了编译器函数的称谓,重返类型,和参数。

Go 语言标准库提供了多种可利用的放手的函数。比如,len() 函数可以承受差别门类参数并再次回到该类型的长度。假设大家传入的是字符串则赶回字符串的尺寸,借使传入的是数组,则赶回数组中含有的函数个数。

参数和再次来到值

函数能够有0或多个参数,0或三个重回值,参数和重回值都亟需钦点数据类型,再次回到值通过return关键字来钦命。

return能够有参数,也足以没有参数,那个重返值能够有名称,也能够没有名称。Go中的函数能够有八个再次回到值。

  • .当重返值有几个时,那几个重回值必需利用括号包围,逗号分隔
  • .return关键字中钦赐了参数时,再次回到值能够毫不名称。假诺return省略参数,则再次回到值部分必得带名称
  • .当再次来到值出名称时,必须利用括号包围,逗号分隔,纵然独有四个重临值
  • .但纵然再次来到值命名了,return中也能够强制内定别的再次来到值的名目,也正是说return的开始时期级越来越高
  • .命名的重返值是预先评释好的,在函数内部可以间接使用,不必要重新宣示。命名重回值的名目无法和函数参数名称同样,不然报错提示变量重复定义
  • .return中能够有表明式,但不能够冒出赋值表达式,那和别的语言可能天差地远。举个例子return a+b是不错的,但return c=a+b是漏洞百出的

例如:

// 单个返回值func func_a() int{    return a}// 只要命名了返回值,必须括号包围func func_b{    // 变量a int已存在,无需再次声明    a = 10    return    // 等价于:return a}// 多个返回值,且在return中指定返回的内容func func_c() {    return a,b}// 多个返回值func func_d() {    return    // 等价于:return a,b}// return覆盖命名返回值func func_e() {    return x,y}

Go中平时会利用在那之中三个再次回到值作为函数是或不是实行成功、是还是不是有错误消息的决断标准。举例return value,existsreturn value,okreturn value,err等。

当函数的再次来到值过多时,举个例子有4个以上的重返值,应该将这个再次来到值搜罗到容器中,然后以回到容器的艺术去重返。比方,同种类的再次来到值能够放进slice中,差异品类的重返值能够放进map中。

但函数有多个再次回到值时,假设内部有些或某多少个重返值不想使用,能够通过下划线_本条blank identifier来舍弃那一个重临值。举个例子下边的func_a函数四个再次回到值,调用该函数时,扬弃了第四个再次回到值b,只保留了第三个重返值a赋值给了变量a

func func_a() {    return}func main() {    a,_ := func_a()}

func function_name (parameter list) (return_types) {

1、缘何必要函数?

多少同样的代码恐怕出现再三,要是不开展打包,那么多次写入到程序中,会导致程序冗余,何况可读性收缩

  • 函数定义
  • 函数再次来到四个值
  • 函数参数
    • Go 语言函数值传递
    • Go语言函数引用传递
  • 函数用法
    • 函数作为值
    • 无名氏函数
    • 闭包
    • 方法
  • 兵慌马乱参数的函数
  • init函数
  • 内建函数
  • 函数调用机制
  • 总结

函数定义

Go 语言函数定义格式如下:

func function_name( [parameter list] ) [return_types] {
   函数体
}

函数定义:

  1. func:函数是以func为关键字
  2. function_name:函数名称,函数名和参数列表一同组成了函数签名
  3. parameter list:参数列表,扶助传递到函数内部的参数,能够是二个参数,也能够是多少个参数(可变参数,用 name ...type来标志),这几个值被称为实际参数。参数列表钦赐的是参数类型、顺序、及参数个数。参数是可选的,也正是说函数也得以不分包参数
  4. return_types:重临类型,函数再次来到一列值。return_types 是该列值的数据类型。某个效果无需再次回到值,这种气象下 return_types 不是必需的。
  5. 函数体:函数定义的代码集结。

按值传参

Go中是因而传值的不二等秘书诀传参的,意味着传递给函数的是拷贝后的副本,所以函数内部访谈、修改的也是其一别本。

例如:

a,b := 10,20minfunc min int{}

下边调用min()时,是将a和b的值拷贝一份,然后将拷贝的别本赋值给变量x,y的,所以min()函数内部,访问、修改的平昔是a、b的别本,和原有的多寡对象a、b没有任何关系。

假使想要修改外界数据,需求传递指针。

举例说,下边三个函数,func_value()是传值函数,func_ptr()是传指针函数,它们都修改同贰个变量的值。

package mainimport "fmt"func main() {    a := 10    func_value    fmt.Println    // 输出的值仍然是10        b := &a    func_ptr    fmt.Println   // 输出修改后的值:11}func func_value int{    x = x + 1    return x}func func_ptr int{    *x = *x + 1    return *x}

map、slice、interface、channel那一个数据类型本人正是指针类型的,所以就到底拷贝传值也是拷贝的指针,拷贝后的参数照旧指向底层数据结构,所以修改它们可能会耳闻则诵外界数据结构的值。

其余注意,赋值操作b = a+1那类别型的赋值也是拷贝赋值。换句话说,今后最底层已经有三个数据对象,八个是a,三个是b。但a = a+1那系列型的赋值即使本质上是拷贝赋值,但因为a的指针指向特色,使得结果上看是原地修改数据对象而非生成新数据对象。

  函数体

2、何以是函数

为做到有些特定功用的主次指令集合称为函数

函数定义

为做到某一效果的前后相继指令的联谊,称为函数。

函数一般分为两类:系统函数、自定义函数。

Go语言函数定义格式如下:

func function_name ([parameter list]) [return_types] {    //函数体}

函数定义分析:

  • func:函数由 func 起始注明
  • function_name:函数名称,函数名和参数列表一同组成了函数签名。
  • parameter list:参数列表,参数就如叁个占位符,当函数被调用时,你能够将值传递给参数,这些值被称为实际参数。参数列表内定的是参数类型、顺序、及参数个数。参数是可选的,也便是说函数也足以不含有参数。
  • return_types:再次回到类型,函数再次回到一列值。return_types 是该列值的数据类型。有个别功用没有需求再次来到值,这种意况下 return_types 不是必得的。
  • 函数体:函数定义的代码集合。

澳门博发娱乐官网 1

示例:

以下实例为 max() 函数的代码,该函数字传送入四个整型参数 num1 和 num2,并再次回到那多少个参数的最大值:

/* 函数返回两个数的最大值 */func max(num1, num2 int) int {   /* 声明局部变量 */   var result int   if (num1 > num2) {      result = num1   } else {      result = num2   }   return result }

函数参数类型声明证实:倘诺函数形参类型同样则声澳优(Ausnutria Hyproca)(Karicare)次就可以,如上边的max函数a, b都以int类型,不然,须要分开申明,如下

澳门博发娱乐官网 2

实例

写二个plus的函数,传递七个数值,用于计算多个数的和,并回到结果

 1 package main
 2 
 3 import (
 4     "fmt"
 5 )
 6 
 7 var (
 8     //声明全局变量num1,num2
 9     num1 float32 = 123.456
10     num2 float32 = 456.789
11 )
12 
13 //自己定义的求和函数,返回两个传递进来num1 num2的和
14 func plus(num1, num2 float32) float32 {
15     result := num1 + num2
16     return result
17 }
18 
19 //主函数
20 func main(){
21     //调用自定义求和函数的返回结果并赋值给sum变量
22     sum := plus(num1, num2)
23     fmt.Printf("%.3f + %.3f = %.3f ",num1, num2, sum)
24 }

地点代码重返的结果为:

123.456 + 456.789 = 580.245 

 

变长参数"..."

突发性参数过多,大概想要让函数管理任性多少个的参数,能够在函数定义语句的参数部分应用ARGS...TYPE的法子。那时会将...表示的参数全体封存到多个名叫ALANDGS的slice中,注意这几个参数的数据类型都是TYPE。

...在Go中称为variadic,在使用...的时候,可以将它看做是叁个slice,下面包车型大巴多少个例证能够表达它的用法。

例如:func myfunc(a,b int,args...int) int {}。除了前四个参数a和b外,其余的参数全都保存到名为args的slice中,且这一个参数全部都是int类型。所以,在函数内部就曾经有了贰个args = []int{....}的数据结构。

例如,下边包车型大巴例子中,min()函数要从具备参数中搜索最小的值。为了尝试效果,特地将前七个参数a和b独立到slice的外场。min()函数内部同期会输出保存到args中的参数值。

package mainimport "fmt"func main() {    a,b,c,d,e,f := 10,20,30,40,50,60    fmt.Println(min(a,b,c,d,e,f))}func min(a,b int,args...int) int{    // 输出args中保存的参数    // 等价于 args := []int{30,40,50,60}    for index,value := range args {        fmt.Printf("%s%d%s %dn","args[",index,"]:",value)    }    // 取出a、b中较小者    min_value := a    if a>b {        min_value = b    }    // 取出所有参数中最小值    for _,value := range args{        if min_value > value {            min_value = value        }    }    return min_value}

但地点代码中调用函数时传递参数的不二等秘书籍分明相比笨重。倘诺要传送的参数过多,可以先将那几个参数保存到三个slice中,再传递slice给min()函数。传递slice给函数的时候,使用SLICE...的主意就能够。

func main() {    s1 := []int{30,40,50,60,70}    fmt.Println(min(10,20,s1...))}

上边的赋值情势已经能表达能选拔slice来精通...的一言一行。其余,上面包车型客车例子也能很好的表达:

// 声明f1()func f1(s...string){    // 调用f2    f2    f3}// 声明f2func f2(s...string){}func f3(s []string){}

假诺各参数的等级次序差异,又想定义成变长参数,该怎么样?第一种方法,可以使用struct,第两种办法得以应用接口。接口暂且不说,倘使选拔struct,大约如下:

type args struct {    arg1 string    arg2 int    arg3 type3}

下一场能够将args传递给函数:f(a,b int,args{}),要是args结构中要求最早化,则f(a,b int,args{arg1:"hello",arg2:22})

}

3、函数分类

内建函数

自定义函数

函数再次回到八个值

Go函数能够重回多少个值,比如:

package mainimport "fmt"func swap(x, y string) (string, string) {   return y, x}func main() {   a, b := swap("Mahesh", "Kumar")   fmt.Println}

函数再次来到多少个值

Go 函数可以重回五个值,比如:

栗子~

 

 1 package main
 2 
 3 import (
 4     "fmt"
 5 )
 6 
 7 //自定义的交换x,y两个变量返回位置的函数
 8 func swap(x, y string) (string, string) {
 9     return y,x
10 }
11 
12 func main(){
13     //调用函数并输出结果
14     fmt.Println(swap("demon","18"))
15 }

 

上边代码重回的结果为:

18 demon

放手函数

在builtin包中有部分放到函数,那个内置函数额外的导入包就能够应用。

有以下内置函数:

$ go doc builtin | grep funcfunc close(c chan<- Type)func delete(m map[Type]Type1, key Type)func panic(v interface{})func print(args ...Type)func println(args ...Type)func recover() interface{}    func complex(r, i FloatType) ComplexType    func imag(c ComplexType) FloatType    func real(c ComplexType) FloatType    func append(slice []Type, elems ...Type) []Type    func make(t Type, size ...IntegerType) Type    func new *Type    func cap int    func copy(dst, src []Type) int    func len int
  • close用于关闭channel
  • delete用来删除map中的成分
  • copy用于拷贝slice
  • append用以追加slice
  • cap用来获取slice的体量
  • len用以获取
    • slice的长度
    • map的要素个数
    • array的因素个数
    • 指向array的指针时,获取array的长度
    • string的字节数
    • channel的channel buffer中的未读队列长度
  • printprintln:底层的出口函数,用来调解用。在骨子里程序中,应该采用fmt中的print类函数
  • compleximagreal:操作复数
  • panicrecover:管理错误
  • newmake:分配内部存款和储蓄器并开首化
    • new适用于为值类(value type)的数据类型(如array,int等)和struct类型的靶子分配内部存款和储蓄器并早先化,并重返它们的指针给变量。如v := new
    • make适用于为停放的援用类的品种(如slice、map、channel等)分配内部存款和储蓄器并开始化底层数据结构,并回到它们的指针给变量,同一时间也许会做一些极度的操作

瞩目,地址和指针是见仁见智的。地址就是数码对象在内部存款和储蓄器中的地址,指针则是私吞多少个机械字长(叁11位机器是4字节,六13人机器是8字节)的多少,这几个数目中存放的是它所指向数据对象的地点。

a -> AAAAb -> Pointer -> BBBB

new构造数据对象赋值给变量的都以指向数据对象的指针。

  • func:函数由 func 初叶证明
  • function_name:函数名称,函数名和参数列表一同构成了函数具名。
  • parameter list:参数列表,参数就像多少个占位符,当函数被调用时,你可以将值传递给参数,那一个值被叫作实际参数。参数列表钦赐的是参数类型、顺序、及参数个数。参数是可选的,也正是说函数也能够不带有参数。
  • return_types:再次回到类型,函数重临一列值。return_types 是该列值的数据类型。有个别成效无需再次来到值,这种场地下 return_types 不是必得的。
  • 函数体:函数定义的代码集合

4、函数的宗旨用法

着力语法

  func 函数名(形参列表) (再次回到值列表) {

    //实践语句

  return 重临值列表

  形参列表

    表示函数的输入

  试行语句

    表示函数推行的某成效代码

  再次来到值列表

    函数能够有重临值也得以未有重临值,可以回到多个,也足以三个也不回来

  使用注意

    golang中的函数能够回来多少个值,假若须求重回多少个值,需求在自定义函数时,证明的重临值列表必须是多个,不然报错

  案例演示

package mainimport (“fmt”)func main(){key := 12var a int = 9if key >= 10 {k,b := test   //调用函数fmt.Printlnfmt.Printf}}func test (float32, int){    //声明函数var t int  = 3b  := float32c  := a + treturn b,c}运行结果:12 12float32

函数参数

函数假如采纳参数,该变量可称为函数的形参。

形参就如定义在函数体内的部分变量。

调用函数,能够因此三种格局来传递参数:

传递类型 描述
值传递 值传递是指在调用函数时将实际参数复制一份传递到函数中,
这样在函数中如果对参数进行修改,将不会影响到实际参数。
引用传递 引用传递是指在调用函数时将实际参数的地址传递到函数中,
那么在函数中对参数所进行的修改,将影响到实际参数。

暗许情状下,Go 语言使用的是值传递,即在调用进度中不会潜濡默化到骨子里参数。

Go 语言函数引用传递值

引用传递是指在调用函数时将实际参数的地点传递到函数中,那么在函数中对参数所开展的更换,将震慑到实际参数。

援引传递指针参数字传送递到函数内,以下是换到函数 swap() 使用了引用传递:

 1 package main
 2 
 3 import (
 4     "fmt"
 5 )
 6 
 7 //使用了指针,这个时候,我们在函数内部修改传递进来的形参会修改外部的实际参数,因为引用的是同一个空间
 8 func swap(x *int, y *int) string{
 9     *x += 50      //*x是为了保持x地址上的值
10     *y += 50      //*y是为了保持y地址上的值
11     fmt.Printf("swap函数内部的x值为: %dn",*x)
12     fmt.Printf("swap函数内部的x值为: %d",*y)
13     return ""
14 }
15 
16 func main(){
17     var x int = 10
18     var y int = 20
19     fmt.Println("未进入函数中的x值:", x)
20     fmt.Println("未进入函数中的y值:", y)
21     fmt.Println("---------------------")
22     //调用函数并输出结果,&指向x,y变量的指针地址
23     fmt.Println(swap(&x, &y))
24     fmt.Println("*********************")
25     fmt.Println("全局变量x的值为:", x)
26     fmt.Println("全局变量y的值为:", y)
27 
28 }

下面代码重回的结果为:

 

未进入函数中的x值: 10
未进入函数中的y值: 20
---------------------
swap函数内部的x值为: 60
swap函数内部的x值为: 70
*********************
全局变量x的值为: 60
全局变量y的值为: 70

 

不应用引用传递值得效果,函数内部的修改并不会潜濡默化外界的变量值

 1 package main
 2 
 3 import (
 4     "fmt"
 5 )
 6 
 7 //未使用引用传递值得函数,内部对值得修改并不会影响外部
 8 func swap(x int, y int) string{
 9     x += 50
10     y += 50
11      fmt.Printf("swap函数内部的x值为: %dn", x)
12     fmt.Printf("swap函数内部的x值为: %d", y)
13     return ""
14 }
15 
16 func main(){
17     var x int = 10
18     var y int = 20
19     fmt.Println("未进入函数中的x值:", x)
20     fmt.Println("未进入函数中的y值:", y)
21     fmt.Println("---------------------")
22     //调用函数并输出结果
23     fmt.Println(swap(x, y))
24     fmt.Println("*********************")
25     fmt.Println("全局变量x的值为:", x)
26     fmt.Println("全局变量y的值为:", y)
27 
28 }

地点代码重临的结果为:

未进入函数中的x值: 10
未进入函数中的y值: 20
---------------------
swap函数内部的x值为: 60
swap函数内部的x值为: 70
*********************
全局变量x的值为: 10
全局变量y的值为: 20

 

递归函数

函数内部调用函数本身的函数称为递归函数。

采纳递归函数最重大的三点:

  1. 不可能不先定义函数的退出规范,退出规范基本上都施用退出点来定义,退出点平时也称为递归的基本点,是递归函数的结尾一次递归点,大概说没有东西可递归时正是退出点。
  2. 递归函数很只怕会时有产生第一次全国代表大会堆的goroutine(其余编程语言则是出现一大堆的线程、进度),也不小概会现出栈空间内部存款和储蓄器溢出标题。在别的编制程序语言大概不得不设置最大递归深度或改写递归函数来缓慢解决这一个主题材料,在Go中能够动用channel+goroutine设计的"lazy evaluation"来消除。
  3. 递归函数平日可以运用level级数的艺术举办改写,使其不再是递归函数,那样就不会有第2点的难题。

例如说,递归最广大的躬体力行,求二个加以整数的阶乘。因为阶乘的公式为n**...*3*2*1,它在参数为1的时候退出函数,也正是说它的递归基点是1,所以对是不是为宗旨进行推断,然后再写递归表明式。

package mainimport "fmt"func main() {    fmt.Println}func a int{    // 判断退出点    if n == 1 {        return 1    }    // 递归表达式    return n * a}

它的调用进程大概是那般的:

澳门博发娱乐官网 3

再比如斐波那契数列,它的总计公式为f+ff=1。它在参数为1和2的时候退出函数,所以它的退出点为1和2。

package mainimport "fmt"func main() {    fmt.Println}func f int{    // 退出点判断    if n == 1 || n == 2 {        return 1    }    // 递归表达式    return f+f}

何以递归三个索引?它的递归基点是文件,只假使文本就回去,只假诺目录就步入。所以,伪代码如下:

func recur FILE{    // 退出点判断    if (dir is a file){        return dir    }    // 当前目录的文件列表    file_slice := filelist()        // 遍历所有文件    for _,file := range file_slice {        return recur    }}

上面包车型地铁更进一竿的印证:(跟上边是一模二样的,都以函数的证明)

5、函数参数的传递方式

  基本介绍

    函数参数传递分为值传递和引用传递

  分类

    值传递

      基本数据类型、数组和结构体等都以值类型,值类型采取的是值传递

    援用传递

      指针、slice切块、map、管道chan、接口等都以援用类型,引用类型应用的是援用传递

  使用验证

    其实不管是值传递照旧引用传递,传递给函数的都以变量的别本,不一致的是值传递是值的正片,引用传递的是地方的正片,一般的话,地址的拷贝功效比较高,因数据量小,而值拷贝拷贝的成效取决于数量的分寸,数据越大,效用越低

Go 语言函数值传递

传送是指在调用函数时将实际参数复制一份传递到函数中,那样在函数中一经对参数举办退换,将不会潜濡默化到实在参数。

私下认可情状下,Go 语言使用的是值传递,即在调用进程中不会潜移暗化到实在参数。

以下定义了 swap() 函数:

/* 定义相互交换值的函数 */func swap int {   var temp int   temp = x /* 保存 x 的值 */   x = y    /* 将 y 值赋给 x */   y = temp /* 将 temp 值赋给 y*/   return temp;}

接下去,让大家利用值传递来调用 swap() 函数:

package mainimport "fmt"func main() {   /* 定义局部变量 */   var a int = 100   var b int = 200   fmt.Printf("交换前 a 的值为 : %dn", a )   fmt.Printf("交换前 b 的值为 : %dn", b )   /* 通过调用函数来交换值 */   swap   fmt.Printf("交换后 a 的值 : %dn", a )   fmt.Printf("交换后 b 的值 : %dn", b )}/* 定义相互交换值的函数 */func swap int {   var temp int   temp = x /* 保存 x 的值 */   x = y    /* 将 y 值赋给 x */   y = temp /* 将 temp 值赋给 y*/   return temp;}

以下代码施行结果为:

交换前 a 的值为 : 100交换前 b 的值为 : 200交换后 a 的值 : 100交换后 b 的值 : 200

Go 语言函数作为值(无名函数的利用)

 1 package main
 2 
 3 import (
 4     "fmt"
 5 )
 6 
 7 func main(){
 8     //匿名函数,传递一个x值进去并取x得平方
 9     f := func (x int) string {
10         return fmt.Sprintf("%d * %d = %d",x,x, x * x)
11     }
12     //调用匿名函数
13     fmt.Println(f(10))
14 }

下面代码重返的结果为:

10 * 10 = 100

 

闭包的贯彻

 

Go 语言帮忙无名氏函数,可用作闭包。佚名函数是多个"内联"语句或表明式。无名函数的优越性在于能够平昔动用函数内的变量,不必注明。

 

以下实例中,我们创设了函数 getSequence() ,再次来到别的三个函数。该函数的指标是在闭包中递增 i 变量,代码如下:

 1 package main
 2 
 3 import (
 4     "fmt"
 5 )
 6 
 7 func getSequence() func() int {
 8     i:=0
 9     return func() int {
10         i+=1
11         return i
12     }
13 }
14 
15 func main(){
16     //作为一个初始化函数,函数中的i初始化的值为0
17     nextNumber := getSequence()
18 
19     //每次调用都递增加1
20     fmt.Println(nextNumber())
21     fmt.Println(nextNumber())
22     fmt.Println(nextNumber())
23 }

地点代码再次回到的结果为:

1
2
3

佚名函数

无名氏函数是不曾名称的函数。一般佚名函数嵌套在函数内部,或许赋值给四个变量,大概当作三个表明式。

概念的办法:

// 声明匿名函数func{    ...CODE...}// 声明匿名函数并直接执行func{    ...CODE...}(parameters)

下边包车型地铁身先士卒中,先定义了无名氏函数,将其赋值给了八个变量,然后在急需的地方再去调用奉行它。

package mainimport "fmt"func main() {    // 匿名函数赋值给变量    a := func() {        fmt.Println("hello world")    }    // 调用匿名函数    a()    fmt.Printf("%Tn", a) // a的type类型:func()    fmt.Println        // 函数的地址}

一经给无名函数的概念语句前边加上(),表示注脚这么些佚名函数的同一时间并实行:

func main() {    msg := "Hello World"    func {        fmt.Println    }}

其中func意味着无名函数的参数,func{}msg代表传递msg变量给无名氏函数,并推行。

func funcName(形参1 type[, 形参2 type...]) [([[回来变量1] type[, [回到变量2] type...]])] {
    [return [重回变量1[, 重返变量2...]]]
  }
  a. 假如形参类型都同样,能够如此写: 形参1, 形参2 type, 同一时候再次来到变量也同等
  b. 固然唯有多个重回值也许无重回值, 可以去掉对应的()
  c. 假若回到有重临值,该函数中最外层要有return语句
  d. 重返语句(), 重临变量名能够省略
  e. []表示可总结
  f. 不帮衬暗中认可参数

6、变量成效域

  基本介绍

    函数内部宣称也许定义的变量叫做局地变量,功能域只限于函数内部

    函数外界证明的可能定义的变量叫做全局变量,功用域在全方位包都有效,全局变量借使在方方面面程序使得的前提是首字母必须大写

  注意事项

    借使变量被定义在三个代码块中,举个例子if或然for循环中,那么那些变量的功效域就在该代码块中

    变量的赋值不能够再全局功能域实行,不然会报错。全局功效域只可以声圣元(Synutra)些变量大概函数,不能够拓宽赋值操作

  案例演示

package mainimport ("fmt""strings")var name intname = 123  //错误的做法 name1 := 123  //错误的做法func main(){fmt.Print}案例演示package mainimport “fmt”name := “zhangsan”func test(){fmt.Print  //zhangsan}func test1(){name := “wangwu”fmt.Print  //wangwu}func maintest1()}运行结果shangsanwangwu

Go语言函数引用传递

引用传递是指在调用函数时将实际参数的地址传递到函数中,那么在函数中对参数所举行的修改,将影响到实在参数。

援引传递指针参数传递到函数内,以下是换成函数 swap() 使用了援用传递:

/* 定义交换值函数*/func swap(x *int, y *int) {   var temp int   temp = *x    /* 保持 x 地址上的值 */   *x = *y      /* 将 y 值赋给 x */   *y = temp    /* 将 temp 值赋给 y */}

以下大家通过使用引用传递来调用 swap() 函数:

package mainimport "fmt"func main() {   /* 定义局部变量 */   var a int = 100   var b int= 200   fmt.Printf("交换前,a 的值 : %dn", a )   fmt.Printf("交换前,b 的值 : %dn", b )   /* 调用 swap() 函数   * &a 指向 a 指针,a 变量的地址   * &b 指向 b 指针,b 变量的地址   */   swap(&a, &b)   fmt.Printf("交换后,a 的值 : %dn", a )   fmt.Printf("交换后,b 的值 : %dn", b )}func swap(x *int, y *int) {   var temp int   temp = *x    /* 保存 x 地址上的值 */   *x = *y      /* 将 y 值赋给 x */   *y = temp    /* 将 temp 值赋给 y */}

以上代码实行结果为:

交换前,a 的值 : 100交换前,b 的值 : 200交换后,a 的值 : 200交换后,b 的值 : 100

 

func type

能够将func作为一种type,以往能够直接行使这些type来定义函数。

package mainimport "fmt"type add func intfunc main() {    var a add = func int{        return a+b    }    s := a    fmt.Println}
  1. 函数的风味:

7、函数使用的注意事项和细节商量

  函数的形参列表能够是八个,重回值列表也可以是多个,重回值列表,各个值用逗号隔离

  形参列表和再次回到值列表的数据类型能够是值类型和援引类型

  函数命名标准遵循变量命名标准,无法以数字开始,大概隐含特殊字符,首字母大写,被别的包导入时,具备可访谈性。假如是小写只好被本包使用

  变量分为全局变量和一些变量,全局变量是宣称在main函数中,局地变量可以注脚在另外二个块结构中,譬喻if语句中,循环体中,自定义函数中等

  主干数据类型的和数组在传递时暗中同意都以值传递,即开展值的正片,在函数内部修改,不会影响原值

  假诺指望函数内部的变量修改函数外的变量,能够流传变量的地点&,函数内部已指针的秘诀操作变量,从功效看类似征引

  案例演示

package mainimport “fmt”func  test{*n = *n + 1fmt.Print}func  main(){num := 123testfmt.Print}

  go语言不援助古板的重载(也便是透过参数列表的两样来贯彻的重载),go语言是用另一种方法达成的重载,并非通过参数列表的例外来促成重载

  在Go中,函数也是二个数据类型,能够赋值给二个变量,则该变量就是函数类型的变量,通过该变量能够对函数调用

    举个例子表达  

package mainimport “fmt”func main(){a := yanshia()    //通过把函数赋值给一个变量,变量加个括号来调用函数fmt.Printf("%T %T",a,yanshi)}func yanshi{fmt.Print}

  函数既然是一种数据类型,由此Go中,函数能够当做参数字传送递给另四个函数

    比方表明

    

package mainimport “fmt”func main(){a := myfunc(yanshi,12)fmt.Printf("%T %T n",a,myfunc)fmt.Println}func  myfunc(funcvar  func int ,num int) {   //函数作为参数时,必须把函数的参数列表和函数的返回值类型的列表补全return funcvar}func yanshi{fmt.Print} 

  函数作为参数字传送递时,必得把函数的证明和重临值的品类列表写全

  为了简化数据类型的概念,Go扶助自定义数据类型

    基本语法

      type 自定义数据类型名 数据类型

    演示自定义数据类型

      第二个示范: type myint int //相当于给int数据类型取了小名,然则那四个是独立,是不相同的数据类型

      第4个示范: type mysum func int

    关于自定义类型后与原类型的难题

    使用注意

      关于子自定义函数类型效用,能够简化函数类型作为形参的概念,可是自定义函数类型的定义必得在利用那几个自定义函数类型的前头

    举个例子表明

      不行使自定义函数 

func  myfunc(funcvar  func int ,num int) int {   //没有使用自定义函数类型时,函数类型作为形参在参数列表时需要写很长return funcvar}

    使用自定义函数类型

    

type  myfunctype  func intfunc  myfunc(funcvar  myfunctype ,num int) int {  //自定义函数类型后,函数作为形参,在参数列表不用写很长return funcvar}

  Go语言协理对函数再次来到值命名

    优点:不用八个五个在return中对应的写再次回到的值

    举个例子表明

    

package mainimport “fmt”func main(){n := 12m := 4sum ,sub :=myfunc}func  myfunc(n int , m int)(sum int,sub int) {   //把返回的值定义好sum = n + m   //直接使用=等号赋值就行sub = n-mreturn      //返回时不用填任何返回数据,并且返回时不用担心对应关系,只需在接收时对应好就行}

  使用_下划线标记符忽略重回值

package mainimport “fmt”func main(){n := 12m := 4sum ,_:=myfunc   //忽略返回值sub}func  myfunc(n int , m int)(sum int,sub int) {   sum = n + m   sub = n-mreturn      } Go语言函数支持可变参数基本语法:func  sum(args... int) sum int {//代码}func sum(n1 int,args... int) sum int {//代码}

    使用注意

      args其实是壹个slice切成片,通过args[index]能够访问到各种值,假如三个函数形参列表有可变参数,和别的参数,那么可变参数要放在最终,不然报错

    案例演示

    

package mainimport “fmt”func main(){n := sum(3,1,2,3,4,5,6)fmt.Println}func sum(n int , args... int ) int {s := 0for i := 0 ; i < len ; i++ {if args[i] == n {break}s += args[i]}return s} 运行结果3

  要是在函数的形参列表中,多个恐怕几个形参的数据类型同样,那么能够轻便后面多少个,最终写二个就行 

func  sum(n , m , b ,c int) int {//代码}

函数用法

函数用法 描述
函数作为值 函数定义后可作为值来使用
闭包 闭包是匿名函数,可在动态编程中使用
方法 方法就是一个包含了接受者的函数

Go 语言函数方法

Go 语言中何况有函数和措施。二个艺术便是八个暗含了接受者的函数,接受者能够是命名类型或许组织体类型的二个值或然是一个指针。全数给定类型的主意属于该项目的主意集。语法格式如下:

func (variable_name variable_data_type) function_name() [return_type]{
   /* 函数体*/
}

栗子~ 

 1 package main
 2 
 3 import (
 4     "fmt"
 5 )
 6 
 7 //定义结构体,类似面向对象种的类的静态变量
 8 type Circle struct {
 9     redius float64
10 }
11 
12 //定义getArea函数,并返回3.14*100.00的结果
13 func (c Circle) getArea() float64{
14     return 3.14 * c.redius
15 }
16 
17 func  main()  {
18     //给结构体赋值
19     c1 := Circle{redius:100.00}
20 
21     /*给结构体赋值的另外一种写法
22     var c1 Circle
23     c1.redius = 100.00
24     */
25 
26     fmt.Printf("Area of Circle(c1) = %.2f ", c1.getArea())
27 
28 }

地点代码重回的结果为:

Area of Circle(c1) = 314.00 

 

1)函数便是变量

8、包的运用和行使原理

  包的采用原理

    包的本来面目实际上正是创制不相同的文本夹来贮存程序文件

  包的有关表明

  使用注意

    导入包时,路线必需从src下的某部目录开头算,比方,src文件夹下有七个utils文件,utils文件下有一个utils.go文件,那么,在main.go中程导弹入utils包下的utils.go的某部变量恐怕函数的路线是:import “utils”

函数作为值

Go 语言能够很灵巧的创制函数,并视作值使用。以下实例中我们在概念的函数中起初化贰个变量,该函数仅仅是为了接纳内置函数 math.sqrt() ,实例为:

package mainimport (   "fmt"   "math")func main(){   /* 声明函数变量 */   getSquareRoot := func(x float64) float64 {      return math.Sqrt   }   /* 使用函数 */   fmt.Println(getSquareRoot}

Go 语言递归函数

递归,正是在运作的经过中调用本人。

Go 语言辅助递归。但大家在应用递归时,开采者需求设置退出标准,不然递归将沦为特别循环中。

递归函数对于缓慢解决数学上的难点是老大实惠的,就像计算阶乘,生成斐波那契数列等。

栗子~

 1 package main
 2 
 3 import (
 4     "fmt"
 5 )
 6 
 7 func fibonacci(n int ) (resulut int){
 8     //递归必须要有退出条件,不然会成死循环
 9     if n < 2{
10         return n
11     }else{
12         return fibonacci(n - 2) + fibonacci(n - 1)
13     }
14 
15 }
16 
17 func main(){
18     //利用for循环求0到10的斐波那契数列的结果
19     for i := 0; i< 11; i++{
20         fmt.Printf("%d ",fibonacci(i))
21     }
22 }

上边代码重返的结果为:

0 1 1 2 3 5 8 13 21 34 55 

 1 package main
 2 
 3 import (
 4     "fmt"
 5 )
 6 
 7 func Factorial(n int ) (result int) {
 8     //递归必须要有退出条件,不然会成死循环
 9     if n == 0 {
10         result = 1
11     } else {
12         result = n * Factorial(n-1)
13     }
14     return result
15 }
16 
17 func main(){
18     //0-15的阶乘
19     fmt.Printf("15的阶乘为:%d ",Factorial(15))

上面代码再次回到的结果为:

15的阶乘为:1307674368000 

 

x:=1

9、动用包的注意事项

  1)在给二个文本打包时,该报对应二个文本夹。文件的包经常和文书所在的公文夹名是直接的,一般为题写

  2)当贰个文书要利用别的包的函数或然变量时,须要先引进对应的包

    引包情势1:import 包名

    引包格局2:import (

      “包名1”

      “包名2”

      )

  3)package指令在文件首先行,然后随就是import导包命令

  4)在import包时,路径从Computer景况变量$GOPATH下的src目录开首算,不用带src目录,编写翻译器会自动从src初始引进

  5)为了让别的包能够访谈到本包的函数可能变量,则该函数恐怕变量的首字母必需大写

  6)在访谈别的包的函数可能变量时,语法是:包名.函数名可能包.变量

  7)假如包名过长,Go语言帮助跟包名取别称,假如取了别称,那么原本的包名就不可能用

  8)在同一个包上边无法有双重的变量名,不然包重复定义

    表达:假若包取了小名,则必得运用别名来访谈包中的函数可能变量

  9)假若多个.go文件打了同一个包,而且那七个文件都有同三个名字的函数恐怕变量,那样都会报错,因为同三个包下只好有三个函数名只怕变量名,固然那么些八个函数名被定义在七个不等的可是打了同三个包的文件

  10)在一个go程序中,main包只可以有一个

  函数中return语句使用注意

    注意:对于函数的重回值,假如函数再次回到多少个值,但是你只供给有些值,那么无需的值能够使用下划线接受,举个例子: _ , a := getSum。

无名函数

在定义无名函数时就一向调用,这种方法无名氏函数只可以调用一回

func main() {    res := func(n1 int, n2 int) int {        return n1 + n2    }    fmt.Println}

将无名函数直接赋值给某些变量,通过变量名的主意开展调用

func main() {    a := func(n1 int, n2 int) int {        return n1 - n2    }        res := a}

y:=x

10、函数之递归调用

  基本介绍

    三个函数体内调用了自家,大家誉为递归调用

  案例演示

func  test {if   a > 2 {a--test}fmt.Println}func  main}运行结果:223

 实践流程

  澳门博发娱乐官网 4

   使用注意

    ①递归每推行多个函数时,就创办多少个新的受保证的独自的空中,也足以说是一个新的函数栈

    ②函数的片段变量是单独的,不会相互影响

    ③递归必得向退出递归的法规逼近,不然便是并世无两递归

    ④当贰个函数推行完结,也许碰到return,就能够回来,听从什么人调用,就将结果再次来到给什么人。执行完毕时,恐怕重返时,该函数栈会被灭绝

  书写递归的首要观念便是:找寻出路

闭包

骨干介绍:闭包正是三个函数和与其有关的援引情况构成的八个完全

Go 语言支持佚名函数,可用作闭包。无名函数是一个"内联"语句或表明式。无名氏函数的优越性在于能够直接使用函数内的变量,不必声明。

以下实例中,我们创制了函数 getSequence() ,再次来到其它三个函数。该函数的目标是在闭包中递增 i 变量,代码如下:

package mainimport "fmt"func getSequence int {   i:=0   return func() int {      i+=1     return i     }}func main(){   /* nextNumber 为一个函数,函数 i 为 0 */   nextNumber := getSequence()     /* 调用 nextNumber 函数,i 变量自增 1 并返回 */   fmt.Println(nextNumber   fmt.Println(nextNumber   fmt.Println(nextNumber      /* 创建新的函数 nextNumber1,并查看结果 */   nextNumber1 := getSequence()     fmt.Println(nextNumber1   fmt.Println(nextNumber1}

如上代码推行结果为:

12312

本文由胜博发-编程发布,转载请注明来源:如果我们传入的是字符串则返回字符串的长度,