golang error和nil深入分析

go处理错误的方式非常原始和有效,go是通过function返回error类型而非主流语言抛出异常。在golang里永远不要忽略错误,否则可能导致程序的意外崩溃。
通常用如下方式检测错误:
if value, err := pack1.Func1(param1); err != nil {
    fmt.Printf(“Error %s in pack1.Func1 with parameter %v”, err.Error(), param1)
    return    // or: return err
}
// Process(value)

从上可以看出如果err不为nil表明存在错误。那么error和nil是啥?
error是golang的预定义接口:
type error interface {
 Error() string
}

那么如何定义error?
package main
 
import (
 "fmt"
 "errors"
)
 
type myError struct{}
 
func (this *myError) Error() string { return "" }
 
func main()  {
 //方法一:采用errors包的New方法 返回一个err的类型
 var err1 error = errors.New("this is an error")
 fmt.Println(err1.Error())
 
 //方法二:采用fmt.Errof 将string信息转化为error信息 并返回
 err2 := fmt.Errorf("%s", "the error test for fmt.Errorf")
 fmt.Println(err2.Error())
 
 //方法三:自定义error,下面细说
}

我们已经知道golang的error是一个interface,go中interface是作为两个成员实现:一个类型和一个值。该值被称为接口的动态值, 它是一个任意的具体值,而该接口的类型则为该值的类型。对于 int 值3, 一个接口值示意性地包含(int, 3)。
只有在内部值和类型都未设置时(nil, nil),一个接口的值才为 nil。特别是,一个 nil 接口将总是拥有一个 nil 类型。若我们在一个接口值中存储一个 int 类型的指针,则内部类型将为 int,无论该指针的值是什么,这样的接口值会是非 nil 的,即使在该指针的内部值为 nil,形如(*int, nil)。
下面举个简单的例子:
package main
 
import (
 "math"
 "fmt"
 "reflect"
)
 
// 定义接口 Abser
type Abser interface {
 Abs() float64
}
 
// 定义结构体 Vertex
type Vertex struct {
 X, Y float64
}
 
// 实现方法 Abs
func (v *Vertex) Abs() float64 {
 return math.Sqrt(v.X*v.X + v.Y*v.Y)
}
 
func main() {
 v := Vertex{3, 4}
 // 成功,能够持有 *Vertex 类型的值
 var a Abser = &v
 
 fmt.Println(reflect.TypeOf(v)) //main.Vertex
 fmt.Println(reflect.TypeOf(a)) //*main.Vertex
 
 // 出错,不能持有 Vertex 类型的值
 // 因为在 *Vertex 上定义了方法 Abs,而未在 Vertex 上定义
 //var b Abser = v
}

那么go在自定义error的时候就要注意了:
package main
 
import (
 "errors"
 "fmt"
 "reflect"
)
 
type myError struct{}
 
func (this *myError) Error() string { return "" }
 
func bad() bool {
 return true
}
 
//自定义错误返回函数
func test() error {
 var p *myError = nil
 if bad() {
  return p
 }
 return nil
}
 
//只是返回错误非空
func test1() error {
 var val error = errors.New("val")
 return val
 
}
 
func main() {
 var e error = test()
 if e == nil {
  fmt.Println("e is nil")
 } else {
  fmt.Println(reflect.TypeOf(e))
  fmt.Println(reflect.ValueOf(e))
  fmt.Println("e is not nil")
 }
 
 var e1 error = test1()
 if e1 == nil {
  fmt.Println("e1 is nil")
 } else {
  fmt.Println("e1 is not nil")
  fmt.Println(e1.Error())
 }
 
 /*输出如下:
 *main.myError
 <nil>
 e is not nil
 e1 is not nil
 val
  */
}

再来说说nil:
golang的nil在概念上和其它语言的null、None、nil、NULL一样,都指代零值或空值。nil是预先说明的标识符,也即通常意义上的关键字。在golang中,nil只能赋值给指针、channel、func、interface、map或slice类型的变量。如果未遵循这个规则,则会引发panic。

时间: 2024-09-24 14:54:10

golang error和nil深入分析的相关文章

为什么我设置EMPushNotificationOptions返回error 是nil,设置也不...

问题描述 **为什么我设置EMPushNotificationOptions返回error 是nil,设置也不对?** 解决方案 EMPushNotificationOptions设置需要在您获取deviceToken成功后才能设置.请先确定deviceToken获取没问题.

Golang context 包入门

概述 Golang 的 context Package 提供了一种简洁又强大方式来管理 goroutine 的生命周期,同时提供了一种 Requst-Scope K-V Store.但是对于新手来说,Context 的概念不算非常的直观,这篇文章来带领大家了解一下 Context 包的基本作用和使用方法. 1. 包的引入 在 go1.7 及以上版本 context 包被正式列入官方库中,所以我们只需要import "context"就可以了,而在 go1.6 及以下版本,我们要 imp

用Golang(Go语言)快速构建WEB应用实例教程

1.Abstract 在学习web开发的过程中会遇到很多困难,因此写了一篇类似综述类的文章.作为路线图从web开发要素的index出发来介绍golang开发的学习流程以及Example代码. 在描述中多是使用代码来描述使用方法不会做过多的说明.最后可以方便的copy代码来实现自己的需求. 本文适应对象:     对web开发有一定经验的人     能够灵活使用ajax的人(至少懂得前后分离)     golang web 开发有一定了解,至少略读过一些golang web开发的书籍 看完本文之后

Golang的os标准库中常用函数的整理介绍_Golang

os.Rename()这个函数的原型是func Rename(oldname, newname string) error,输入的是旧文件名,新文件名,然后返回一个error其实这个函数的真正实现用的syscall.Rename()然后通过MoveFile(from *uint16, to *uint16) (err error) = MoveFileW来重新命名 复制代码 代码如下:  import (  "fmt"  "os" ) func main() {  

环信主动退出群组,error,提示说 没有找到

问题描述 [[EaseMob sharedInstance].chatManager asyncLeaveGroup:groupidString completion:^(EMGroup *group, EMGroupLeaveReason reason, EMError *error) {             if (!error) {         } onQueue:nil];groupidString是正确的groupid,我在环信后台用groupidString搜索过了,能找到群

退出登录 error 显示 解除device token失败

问题描述 退出登录 error 显示 解除device token失败 [.chatManager asyncLogoffWithUnbindDeviceToken:YES completion:^(NSDictionary *info, EMError *error) { } onQueue:nil]; 解决方案 除deviceToken失败了.多出现在网不好的情况.如果忽略这个,在unbind里传NO.

集成环信3.0,调用登陆时 emerror 返回对象是nil

问题描述 集成环信3.0,调用登陆时 emerror 返回对象是nil集成环信3.0,调用登陆时 emerror 返回对象是nil集成环信3.0,调用登陆时 emerror 返回对象是nil集成环信3.0,调用登陆时 emerror 返回对象是nil集成环信3.0,调用登陆时 emerror 返回对象是nil集成环信3.0,调用登陆时 emerror 返回对象是nil集成环信3.0,调用登陆时 emerror 返回对象是nil集成环信3.0,调用登陆时 emerror 返回对象是nil集成环信3

Go语言编程中判断文件是否存在是创建目录的方法_Golang

判断文件是否存在os.IsExists()函数和os.IsNotExists(),他们的函数的原形是func IsExist(err error) bool func IsNotExist(err error) bool 都是传入一个err返回bool 这里注意了 err已经定义好了 复制代码 代码如下:   /*  var (      ErrInvalid    = errors.New("invalid argument")      ErrPermission = errors

利用Go语言初步搭建一个web应用的教程_Golang

1.Abstract 在学习web开发的过程中会遇到很多困难,因此写了一篇类似综述类的文章.作为路线图从web开发要素的index出发来介绍golang开发的学习流程以及Example代码. 在描述中多是使用代码来描述使用方法不会做过多的说明.最后可以方便的copy代码来实现自己的需求. 本文适应对象:     对web开发有一定经验的人     能够灵活使用ajax的人(至少懂得前后分离)     golang web 开发有一定了解,至少略读过一些golang web开发的书籍 看完本文之后