github.com/code-reading/golang@v0.0.0-20220303082512-ba5bc0e589a3/coding/errors/as.go (about)

     1  package main
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"io/fs"
     7  	"os"
     8  )
     9  
    10  // errors.As 可以非常方便抽取结构化中错误值部分
    11  
    12  /*
    13  比如,有一个业务错误信息,  path: xxxx, Os: drawin, error:path not exist
    14  这个错误信息很难进行字段提取
    15  可以通过自定义错误方法, 提出这个错误信息
    16  
    17  // 自定义错误类型
    18  
    19  type PathError struct {
    20  	path string
    21  	Os string
    22  	err error
    23  }
    24  // 实现错误接口
    25  func (e PathError)Error()string {
    26  	return fmt.Sprintf("xxx, xx ,x ", e.path, e.os, e.err)
    27  }
    28  
    29  业务函数
    30  func A() error {
    31  	return PathError{path:xxx, os:xxx, err:errors.New("xxxx")}
    32  }
    33  if e = A() ; e !=nil {
    34  	var pe *PathError
    35  	注意: 这里明确知道返回的e 的类型就是 PathError, 且pe 传递为地址传递 ,否则会panic
    36  	当然 如果要进一步提取PathError, 比如脱敏等, 可以在PathError 在实现一个As(error, interface{})方法
    37  	if errors.As(e, &pe) {
    38  		// dosomething with pe
    39  		fmt.Println("path:", pe.path)
    40  	}
    41  }
    42  */
    43  
    44  func main() {
    45  	if _, err := os.Open("non-existing"); err != nil {
    46  		// os.Open 返回的错误类型 是  *fs.PathError
    47  		var pathError *fs.PathError
    48  		if errors.As(err, &pathError) {
    49  			fmt.Println("Failed at path:", pathError.Path)
    50  		} else {
    51  			fmt.Println(err)
    52  		}
    53  	}
    54  
    55  	// Output:
    56  	// Failed at path: non-existing
    57  }