Go语言(二)

            指针

            Go也有指针

·         

p := 2
pInt := &p //定义一个指针变量,赋值为变量p的地址,编译器可以自动识别
fmt.Printf("p=%d\tpInt=%p\n",p,pInt)
*pInt = 123445
fmt.Printf("p=%d\tpInt=%p\n",p,pInt)

输出
p=2     pInt=0x12060140
p=123445        pInt=0x12060140

   

    函数在前面说过了,这里说一下函数的调用

    不定参数

   

不定参数是指函数传入的参数个数为不定数量
首先需要将函数定义成接受不定参数类型
func myFunc(args ...int){
    for _,arg:= range args{
         fmt.Println(arg)
    }
}

或者为
func myFunc(args []int){
       ...........
}

如果想不限定传递参数的类型,可以指定interface{}
如Go语言标准库中的fmt.Printf()函数
func Printf(format string,args ...interface{}){
     //....
}

  

 

    函数返回多个值

    Go语言也提供了像Python一样返回多个值语法,一般来说Go中很多package都返回两个值,一个是正常期望返回的值,一个是错误error.

    

比如File.Read()函数可以同时返回读取的字节数和错误信息
func (file *File)Read(b []byte)(n int,err Error)

 

     匿名函数

     匿名函数指的是不需要定义函数名的一种函数实现方式

     

f := func (a,b int,z float64) bool{
    return a*b < int(z)
}
可以赋给一个变量或者直接执行

   

    闭包

    闭包是可以包含自由(未绑定到特定对象)变量的代码块,这些变量不在这个代码块内或者任何全局上下文中定义,而是在定义代码块的环境中定义。要执行的代码块(由于自由变量包含在代码块中,所以这些自由变量以及他们引用的对象,没有被释放)为自由变量提供绑定的计算环境(作用域)。

    

package main

import "fmt"

func main(){
   var j int = 5
   a := func()(func()){
         var i int = 10
         return func(){
              fmt.Println("i, j: %d\n",i ,j)
         }
   }()

   a()
   j*=2
   a()
}

输出
i, j: 10,5
i, j: 10,10

 

 

    错误处理

    Go中引入了一个错误处理的标准模式,error接口

    

type error interface{
    Error() string
}

 

    在Go中大多函数,如果要返回错误,大致上都可以定义为如下模式,将error作为多种返回值中的最后一个,当然这个并非是强制要求(怎么看都有点javascript的感觉,哈哈)。

     

func myFunc(param string)(str string,err error){
    //...
}

调用时的代码
n, err := myFunc("")
if err := nil {
   //...
}else{
  //...
}

那如何应用到实际中呢?

在Go中,接口的实现,根本不需要明确类型和接口之间的关系

type myError struct{
     msg string
}

要想让编译器知道myError可以当做一个error来处理,这个时候就要去实现Error()方法了

func (e *myError)Error()string{
     return e.msg
}

例子
func myFunc(name string)(string,error){
    if len(name)<10 {
         return name+" is right",nil
    }else{
         return name+" is not right",&myError("incorrect!")
    }
}

 

 

   defer

   defer的出现简直就是C/C++程序员的福音,在程序中,特别是在调用一个资源的时候,比如数据库连接,但是程序出现异常的地方可能有很多,每一个可能的地方都有一个return的位置,该关闭的可能就没有来得及关闭,使用defer就可以很轻松解决这个问题,而且增加代码的可读性和优雅性。

    

    

func CopyFile(dst,src string)(w int64, err error){
    srcFile, err := os.Open(src)
    if err != nil{
        return
    }
    defer srcFile.CLose()
    }

    dstFile,err := os.Create(dst)
    if err != nil {
       return
    }

    defer dstFile.Close()

    return io.COpy(dstFile,srcFile)

}
即使其中Copy()函数抛出异常,Go仍然会保证dstFile和srcFile被正常关闭。
一个函数里面可以有多个defer,他们按照栈的方式执行,先进后出

 

    panic()和recover()

    Go语言引入了两个内置函数panic()和recover()以报告和处理运行时错误和程序中的错误场景。

    func panic(interface())

    func recover(interface())

    当在一个函数执行过程中调用panic()函数时,正常的函数执行流程将立即终止,但函数终止之前使用defer关键字延迟执行的语句将正常展开执行,之后该函数将返回到调用函数,并导致逐层向上执行panic流程,直至所属的goroutine中所有正在执行的函数终止,错误信息将被上报,包括panic()函数传入的参数。

    recover()函数用于终止错误处理流程。一般情况下,recover()应该在一个使用defer关键字的函数中执行有效的截取错处理流程。如果没有在发生异常的goroutine中明确调用恢复过程(使用recover()关键字),会导致该goroutine所属的进程打印异常信息后直接退出。

   

 defer func(){
           if r := recover(); r !=nil {
                     log.Printf("Runtime error caught: %v", r)
           }
     }()

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值