memcpy深度解�:`resistance` vs `resistance` 关键区别

核心内容摘要

Fluke福禄克9170 9171 9172 9173干井炉计量炉
2026 年 GEO 行业风向标:五大优质优化服务商全维度解析

QOwnNotes(事务笔记管理)

error接口:erorr是一种内建的接口类型.内建意味着不需要import.任何包都可以直接使用,使用起来就像int string一样自然.源码位置:src/builtin/builtin.go// The error built-in interface type is the conventional interface for // representing an error condition, with the nil value representing no error. type error interface { Error() string }从源码可知.error接口只声明了一个Error()方法.任何实现了该方法的结构体都可以作为error来使用.error的实例代表一种异常状态.Error()方法用于描述该异常状态.值为nil的error代表没有异常.标准库erroor包中的errorString就是实现error接口的一个例子.源码位置:src/errors/errors.gotype errorString struct { s string } func (e *errorString) Error() string { return e.s }errorString是errors包的私有类型.对外不可见.只能通过相应的公开接口才可以创建errorString实例.

创建error:标准库创建方法:

.errors.New():源码位置:src/errors/errors.go// New returns an error that formats as the given text. // Each call to New returns a distinct error value even if the text is identical. func New(text string) error { return errorString{text} }errors.New()实现比较简单.只是单纯的构建了一个errorString实例便返回了.

.fmt.Errorf():源码位置:src/fmt/errors.gofunc Errorf(format string, a ...any) error { p : newPrinter() p.wrapErrs true p.doPrintf(format, a) s : string(p.buf) var err error switch len(p.wrappedErrs) { case 0: err errors.New(s) case 1: w : wrapError{msg: s} w.err, _ a[p.wrappedErrs[0]].(error) err w default: if p.reordered { slices.Sort(p.wrappedErrs) } var errs []error for i, argNum : range p.wrappedErrs { if i 0 p.wrappedErrs[i-1] argNum { continue } if e, ok : a[argNum].(error); ok { errs append(errs, e) } } err wrapErrors{s, errs} } p.free() return err }fmt.Errorf会接受两个参数然后对string进行格式化.

性能对比:fmt.Errorf()适用于格式化输出错误字符串的场景.如果不需要格式化字符串.则建议直接使用errors.New().示例如下:package Concurrent import ( errors fmt testing ) // 场景1无格式化参数的简单错误errors.New 原生场景 vs fmt.Errorf 无参数 func BenchmarkErrorsNew_Simple(b *testing.B) { // 重置计时器排除初始化耗时 b.ResetTimer() // 循环执行 b.N 次b.N 由基准测试框架自动调整 for i : 0; i b.N; i { _ errors.New(simple error) } } func BenchmarkFmtErrorf_Simple(b *testing.B) { b.ResetTimer() for i : 0; i b.N; i { // fmt.Errorf 无格式化参数等价于 errors.New _ fmt.Errorf(simple error) } } // 场景2带格式化参数的错误fmt.Errorf 核心场景errors.New 无法直接实现 func BenchmarkFmtErrorf_Format(b *testing.B) { // 测试参数字符串数字模拟真实业务格式化场景 msg : user uid : 1001 b.ResetTimer() for i : 0; i b.N; i { _ fmt.Errorf(user %s not found, uid: %d, msg, uid) } } // 场景3带错误包装的场景%w 动词fmt.Errorf 特有 func BenchmarkFmtErrorf_Wrap(b *testing.B) { baseErr : errors.New(base error) b.ResetTimer() for i : 0; i b.N; i { _ fmt.Errorf(wrap error: %w, baseErr) } }

自定义error:任何实现error接口的类型都可以称为error.比如标准库os中的PathError就是一个典型的例子.源码位置:src/io/fs.gotype PathError struct { Op string Path string Err error } func (e *PathError) Error() string { return e.Op e.Path : e.Err.Error() }

异常处理:针对error而言.异常处理包括如何检查错误 如何传递错误.

.检查error:最常见的检查error的方式是与nil值进行比较:func main() { var err error T(

if err ! nil { } }有时也会与一些预定义的error进行比较:package oserror import errors var ( ErrInvalid errors.New(invalid argument) ErrPermission errors.New(permission denied) ErrExist errors.New(file already exists) ErrNotExist errors.New(file does not exist) ErrClosed errors.New(file already closed) )实现了error接口的类型均可以作为error来处理.也可以使用类型断言来检查error.func AssertError(err error) { if e,ok : err.(*os.PathError); ok { fmt.Printf(path error: %s, e.Path) } }

.传递error:在一个函数中收到一个error.往往需要附加一些上下文信息再把error继续往上抛.最常见的添加附加上下文信息的方法是用fmt.Errorf().func ReturnErrorTest() { err : errors.New(test error) if err ! nil { fmt.Errorf(我定义的异常进行了包装%s, err) } }这种方式抛出的error有一个糟糕的问题.就是原error信息和附加的信息被糅合到了一起.示例如下:import ( fmt os ) func WriteFile(fileName string) error { if fileName 测试.txt { return fmt.Errorf(write file error:%v, os.ErrPermission) } return nil } func ExampleWriteFile() { err : WriteFile(测试.txt) if err os.ErrPermission { fmt.Printf(write file error:%v, os.ErrPermission) } }在这个例子中.无法明确到底是不是这个异常.为了解决这个问题.可以自定义error类型.就像os.PathError.上下文与信息分开放.type PathError struct { Op string //上下文 Path string //上下文 Err error //原error }

wrapError:Go

13针对error的优化.最核心的内容就是引入了wrapError这一新的error类型.其他特性都是围绕此类型展开的.源码位置:src/fmt/errors.go:type wrapError struct { msg string err error } func (e *wrapError) Error() string { return e.msg } func (e *wrapError) Unwrap() error { return e.err }wrapError中的msg保存上下文信息和err.Error(). err用来存储原error.与之前的errorString相比.还额外实现了Unwrap接口.用于返回原始的error.

fmt.Errorf():fmt.Errorf()新增了格式动词%w(wrap)用于生成wrapError实例.并且兼容原有动词格式.源码如下:func Errorf(format string, a ...any) error { p : newPrinter() p.wrapErrs true p.doPrintf(format, a) s : string(p.buf) var err error switch len(p.wrappedErrs) { case 0: err errors.New(s) case 1: w : wrapError{msg: s} w.err, _ a[p.wrappedErrs[0]].(error) err w default: if p.reordered { slices.Sort(p.wrappedErrs) } var errs []error for i, argNum : range p.wrappedErrs { if i 0 p.wrappedErrs[i-1] argNum { continue } if e, ok : a[argNum].(error); ok { errs append(errs, e) } } err wrapErrors{s, errs} } p.free() return err }fmt.Errorf()将根据动词格式来动态决定生成wrapError还是errorString.func main() { err : errors.New(this is an error) //使用%v baseError : fmt.Errorf(this is a %v, err) if _, ok : baseError.(interface{ Unwrap() error }); !ok { fmt.Println(baseError is errorString) } }使用%w格式动词生成的error类型自动变成wrapError(实现了Unwrap接口).func main() { err : errors.New(this is an error) //使用%w baseError : fmt.Errorf(this is a %w, err) if _, ok : baseError.(interface{ Unwrap() error }); ok { fmt.Println(baseError is wrapError) } }当error在函数间传递时.error之间好像被组织成一个链式结构.

errors.Unwrap():源码位置:src/errors/wrap.gofunc Unwrap(err error) error { u, ok : err.(interface { Unwrap() error }) if !ok { return nil } return u.Unwrap() }如果参数err没有实现Unwrap()函数.则说明是基础error.直接返回nil.否则调用原error实现的Unwrap函数并返回. 可以通过循环调用errors.Unwrap()方法来逐层检查.示例如下:func ExampleUnwrapLoop() { err1 : fmt.Errorf(write file error:%w, os.ErrPermission) err2 : fmt.Errorf(write file error:%w, err

err : err2 for { if err os.ErrPermission { fmt.Printf(Permission denied\n) break } if err errors.Unwrap(err); err nil { break } } }

errors.Is():errors.Is()用于检查特定的error链中是否包含指定的error值.源码位置:src/errors/wrap.gofunc Is(err, target error) bool { if err nil || target nil { return err target } isComparable : reflectlite.TypeOf(target).Comparable() return is(err, target, isComparable) }func is(err, target error, targetComparable bool) bool { for { if targetComparable err target { return true } if x, ok : err.(interface{ Is(error) bool }); ok x.Is(target) { return true } switch x : err.(type) { case interface{ Unwrap() error }: err x.Unwrap() if err nil { return false } case interface{ Unwrap() []error }: for _, err : range x.Unwrap() { if is(err, target, targetComparable) { return true } } return false default: return false } } }

errors.As()方法:在Go

13中.errors.As()用于从一个error链中查找是否有指定类型出现.如有.则把error转换成该类型.源码位置:src/errors/wrap.gofunc As(err error, target any) bool { if err nil { return false } if target nil { panic(errors: target cannot be nil) } val : reflectlite.ValueOf(target) typ : val.Type() if typ.Kind() ! reflectlite.Ptr || val.IsNil() { panic(errors: target must be a non-nil pointer) } targetType : typ.Elem() if targetType.Kind() ! reflectlite.Interface !targetType.Implements(errorType) { panic(errors: *target must be interface or implement error) } return as(err, target, val, targetType) }func as(err error, target any, targetVal reflectlite.Value, targetType reflectlite.Type) bool { for { if reflectlite.TypeOf(err).AssignableTo(targetType) { targetVal.Elem().Set(reflectlite.ValueOf(err)) return true } if x, ok : err.(interface{ As(any) bool }); ok x.As(target) { return true } switch x : err.(type) { case interface{ Unwrap() error }: err x.Unwrap() if err nil { return false } case interface{ Unwrap() []error }: for _, err : range x.Unwrap() { if err nil { continue } if as(err, target, targetVal, targetType) { return true } } return false default: return false } } }山高路远.如果大家喜欢我的分享的话.可以关注我的微信公众号念何架构之路

jhs2.0.9.apk安装包-jhs2.0.9.apk安装包应用

百度百家号客服电话人工服务

123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123