1、Go语言递归函数阶乘斐波那契数列2、Go语言类型转换3、Go语言接口4、Go错误处理5、Go并发Go并发通道(channel)通道缓冲区Go遍历通道与关闭通道1、Go语言递归函数 递归,就是在运行的过程中调用自己。 语法格式如下:funcrecursion(){recursion()函数调用自身}funcmain(){recursion()} Go语言支持递归。但我们在使用递归时,开发者需要设置退出条件,否则递归将陷入无限循环中。 递归函数对于解决数学上的问题是非常有用的,就像计算阶乘,生成斐波那契数列等。1。1、阶乘 以下实例通过Go语言的递归函数实例阶乘:packagemainimportfmtfuncFactorial(nuint64)(resultuint64){if(n0){resultnFactorial(n1)returnresult}return1}funcmain(){variint15fmt。Printf(d的阶乘是d,i,Factorial(uint64(i)))} 以上实例执行输出结果为:15的阶乘是13076743680001。2、斐波那契数列 以下实例通过Go语言的递归函数实现斐波那契数列:packagemainimportfmtfuncfibonacci(nint)int{ifn2{returnn}returnfibonacci(n2)fibonacci(n1)}funcmain(){variintfori0;i10;i{fmt。Printf(d,fibonacci(i))}} 以上实例执行输出结果为:01123581321342、Go语言类型转换 类型转换用于将一种数据类型的变量转换为另外一种类型的变量。Go语言类型转换基本格式如下:typename(expression) typename为类型,expression为表达式。 以下实例中将整型转化为浮点型,并计算结果,将结果赋值给浮点型变量:packagemainimportfmtfuncmain(){varsumint17varcountint5varmeanfloat32meanfloat32(sum)float32(count)fmt。Printf(mean的值为:f,mean)} 以上实例执行输出结果为:mean的值为:3。400000 go不支持隐式转换类型,比如:packagemainimportfmtfuncmain(){varaint643varbint32bafmt。Printf(b为:d,b)} 此时会报错cannotusea(typeint64)astypeint32inassignmentcannotuseb(typeint32)astypestringinargumenttofmt。Printf 但是如果改成bint32(a)就不会报错了:packagemainimportfmtfuncmain(){varaint643varbint32bint32(a)fmt。Printf(b为:d,b)}3、Go语言接口 Go语言提供了另外一种数据类型即接口,它把所有的具有共性的方法定义在一起,任何其他类型只要实现了这些方法就是实现了这个接口。定义接口typeinterfacenameinterface{methodname1〔returntype〕methodname2〔returntype〕methodname3〔returntype〕。。。methodnamen〔returntype〕}定义结构体typestructnamestruct{variables}实现接口方法func(structnamevariablestructname)methodname1()〔returntype〕{方法实现}。。。func(structnamevariablestructname)methodnamen()〔returntype〕{方法实现}packagemainimport(fmt)typePhoneinterface{call()}typeNokiaPhonestruct{}func(nokiaPhoneNokiaPhone)call(){fmt。Println(IamNokia,Icancallyou!)}typeIPhonestruct{}func(iPhoneIPhone)call(){fmt。Println(IamiPhone,Icancallyou!)}funcmain(){varphonePhonephonenew(NokiaPhone)phone。call()phonenew(IPhone)phone。call()} 在上面的例子中,我们定义了一个接口Phone,接口里面有一个方法call()。然后我们在main函数里面定义了一个Phone类型变量,并分别为之赋值为NokiaPhone和IPhone。然后调用call()方法,输出结果如下:IamNokia,Icancallyou!IamiPhone,Icancallyou!4、Go错误处理 Go语言通过内置的错误接口提供了非常简单的错误处理机制。 error类型是一个接口类型,这是它的定义:typeerrorinterface{Error()string} 我们可以在编码中通过实现error接口类型来生成错误信息。 函数通常在最后的返回值中返回错误信息。使用errors。New可返回一个错误信息:funcSqrt(ffloat64)(float64,error){iff0{return0,errors。New(math:squarerootofnegativenumber)}实现} 在下面的例子中,我们在调用Sqrt的时候传递的一个负数,然后就得到了nonnil的error对象,将此对象与nil比较,结果为true,所以fmt。Println(fmt包在处理error时会调用Error方法)被调用,以输出错误,请看下面调用的示例代码:result,err:Sqrt(1)iferr!nil{fmt。Println(err)}5、Go并发5。1、Go并发 Go语言支持并发,我们只需要通过go关键字来开启goroutine即可。 goroutine是轻量级线程,goroutine的调度是由Golang运行时进行管理的。 goroutine语法格式:go函数名(参数列表) 例如:gof(x,y,z) 开启一个新的goroutine:f(x,y,z) Go允许使用go语句开启一个新的运行期线程,即goroutine,以一个不同的、新创建的goroutine来执行一个函数。同一个程序中的所有goroutine共享同一个地址空间。packagemainimport(fmttime)funcsay(sstring){fori:0;i5;i{time。Sleep(100time。Millisecond)fmt。Println(s)}}funcmain(){gosay(world)say(hello)} 执行以上代码,你会看到输出的hello和world是没有固定先后顺序。因为它们是两个goroutine在执行:worldhellohelloworldworldhellohelloworldworldhello5。2、通道(channel) 通道(channel)是用来传递数据的一个数据结构。 通道可用于两个goroutine之间通过传递一个指定类型的值来同步运行和通讯。操作符用于指定通道的方向,发送或接收。如果未指定方向,则为双向通道。chv把v发送到通道chv:ch从ch接收数据,并把值赋给v 声明一个通道很简单,我们使用chan关键字即可,通道在使用前必须先创建:ch:make(chanint) 注意:默认情况下,通道是不带缓冲区的。发送端发送数据,同时必须有接收端相应的接收数据。 以下实例通过两个goroutine来计算数字之和,在goroutine完成计算后,它会计算两个结果的和:packagemainimportfmtfuncsum(s〔〕int,cchanint){sum:0for,v:ranges{sumv}csum把sum发送到通道c}funcmain(){s:〔〕int{7,2,8,9,4,0}c:make(chanint)gosum(s〔:len(s)2〕,c)gosum(s〔len(s)2:〕,c)x,y:c,c从通道c中接收fmt。Println(x,y,xy)} 输出结果为:517125。3、通道缓冲区 通道可以设置缓冲区,通过make的第二个参数指定缓冲区大小:ch:make(chanint,100) 带缓冲区的通道允许发送端的数据发送和接收端的数据获取处于异步状态,就是说发送端发送的数据可以放在缓冲区里面,可以等待接收端去获取数据,而不是立刻需要接收端去获取数据。 不过由于缓冲区的大小是有限的,所以还是必须有接收端来接收数据的,否则缓冲区一满,数据发送端就无法再发送数据了。 注意:如果通道不带缓冲,发送方会阻塞直到接收方从通道中接收了值。如果通道带缓冲,发送方则会阻塞直到发送的值被拷贝到缓冲区内;如果缓冲区已满,则意味着需要等待直到某个接收方获取到一个值。接收方在有值可以接收之前会一直阻塞。packagemainimportfmtfuncmain(){这里我们定义了一个可以存储整数类型的带缓冲通道缓冲区大小为2ch:make(chanint,2)因为ch是带缓冲的通道,我们可以同时发送两个数据而不用立刻需要去同步读取数据ch1ch2获取这两个数据fmt。Println(ch)fmt。Println(ch)} 执行输出结果为:125。4、Go遍历通道与关闭通道 Go通过range关键字来实现遍历读取到的数据,类似于与数组或切片。格式如下:v,ok:ch 如果通道接收不到数据后ok就为false,这时通道就可以使用close()函数来关闭。packagemainimport(fmt)funcfibonacci(nint,cchanint){x,y:0,1fori:0;in;i{cxx,yy,xy}close(c)}funcmain(){c:make(chanint,10)gofibonacci(cap(c),c)range函数遍历每个从通道接收到的数据,因为c在发送完10个数据之后就关闭了通道,所以这里我们range函数在接收到10个数据之后就结束了。如果上面的c通道不关闭,那么range函数就不会结束,从而在接收第11个数据的时候就阻塞了。fori:rangec{fmt。Println(i)}} 执行输出结果为:0112358132134