Google erross의 Is와 As를 조사했습니다.
erross의 Is, As는?
errors.Is란?
package main
import (
"errors"
"fmt")
type myError struct {
s string
}
func (obj *myError) Error() string {
return ""
}
type myErrorImplementedIs struct {
s string
}
func (obj *myErrorImplementedIs) Is(err error) bool {
return true
}
func (obj *myErrorImplementedIs) Error() string {
return ""
}
func main() {
// 比較可能で同じオブジェクトを返す場合は真
{
err := &myError{s:"hoge"}
fmt.Println(errors.Is(err, err))
}
// 比較可能でもオブジェクトが違えば偽
{
err := &myError{s:"hoge"}
target := errors.New("hoge")
fmt.Println(errors.Is(err, target))
}
// オブジェクトが違っていてもerrにIsが実装されていればそれを返す
{
err := &myErrorImplementedIs{s:"hoge"}
target := errors.New("hoge")
fmt.Println(errors.Is(err, target))
}
// Unwrapが実装されていれば返り値が比較可能かIsで判定する
// errのwrapのどれかに同一のオブジェクトか真を返すIsがあれば通る
{
target := &myError{s:"hoge"}
err := fmt.Errorf("%w",target)
fmt.Println(errors.Is(err, target))
}
}
errors.Is의 내용
func Is(err, target error) bool {
if target == nil {
return err == target
}
isComparable := reflectlite.TypeOf(target).Comparable()
for {
if isComparable && err == target {
return true
}
if x, ok := err.(interface{ Is(error) bool }); ok && x.Is(target) {
return true
}
if err = Unwrap(err); err == nil {
return false
}
}
}
비교 가능한 판단
+ 다음 URL 상세 정보
+ https://golang.org/ref/spec#Comparison_operators
+ https://pod.hatenablog.com/entry/2016/07/30/204357
+ https://golang.org/ref/spec#Assignability
+ https://budougumi0617.github.io/2019/07/07/prevent-runtime-error-by-pointer/
isComparable := reflectlite.TypeOf(target).Comparable()
if isComparable && err == target {
return true
}
err Is 메소드 보유 시
if x, ok := err.(interface{ Is(error) bool }); ok && x.Is(target) {
return true
}
err Unwrap, nil을 반납하면 끝이에요.
if err = Unwrap(err); err == nil {
return false
}
func Unwrap(err error) error {
u, ok := err.(interface { Unwrap() error })
if !ok {
return nil
}
return u.Unwrap()
}
error.As란 무엇입니까?
package main
import (
"errors"
"fmt"
)
type myError struct {}
func (obj *myError) Error() string {
return "myError"
}
type myErrorAs struct {}
func (obj *myErrorAs) Error() string {
return "myErrorAs"
}
func (obj *myErrorAs) As(_ interface{}) bool {
return true
}
func main() {
// targetがinterfaceだと全てにmatchするので真
{
err := &myError{}
var target interface{}
fmt.Println(errors.As(err,&target))
}
// targetが同一の型なら代入可能なので真
{
err := &myError{}
var target *myError
fmt.Println(errors.As(err,&target))
}
// errがAsを実装されている場合はそこで判定
// この場合err.Asが常に真
{
err := &myErrorAs{}
var target *myError
fmt.Println(errors.As(err,&target))
}
}
errors.As의 내용
func As(err error, target interface{}) bool {
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")
}
for err != nil {
if reflectlite.TypeOf(err).AssignableTo(targetType) {
val.Elem().Set(reflectlite.ValueOf(err))
return true
}
if x, ok := err.(interface{ As(interface{}) bool }); ok && x.As(target) {
return true
}
err = Unwrap(err)
}
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")
}
대입 가능 여부를 판단하다
for err != nil {
if reflectlite.TypeOf(err).AssignableTo(targetType) {
val.Elem().Set(reflectlite.ValueOf(err))
return true
}
if x, ok := err.(interface{ As(interface{}) bool }); ok && x.As(target) {
return true
}
err = Unwrap(err)
}
총결산
同一
에 따라 As가 이 유형인지 아닌지代入可能
Reference
이 문제에 관하여(Google erross의 Is와 As를 조사했습니다.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://zenn.dev/hiroyukim/articles/d03e3860152c58텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)