Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Goのエラーハンドリング

Daisuke Mino
August 14, 2018
180

 Goのエラーハンドリング

Daisuke Mino

August 14, 2018
Tweet

Transcript

  1. 255 type error interface {¬ 256 ▸ Error() string¬ 257

    }¬ Τϥʔ͸୯ͳΔJOUFSGBDF CVJMUJOCVJMUJOHP--
  2. 8 // New returns an error that formats as the

    given text.¬ 9 func New(text string) error {¬ 10 ▸ return &errorString{text}¬ 11 }¬ 12 ¬ 13 // errorString is a trivial implementation of error.¬ 14 type errorString struct {¬ 15 ▸ s string¬ 16 }¬ 17 ¬ 18 func (e *errorString) Error() string {¬ 19 ▸ return e.s¬ 20 }¬ errors.Error() FSSPSTFSSPSTHP--
  3. 200 // Sprintf formats according to a format specifier and

    returns the resulting string.¬ 201 func Sprintf(format string, a ...interface{}) string {¬ 202 ▸ p := newPrinter()¬ 203 ▸ p.doPrintf(format, a)¬ 204 ▸ s := string(p.buf)¬ 205 ▸ p.free()¬ 206 ▸ return s¬ 207 }¬ 208 ¬ 209 // Errorf formats according to a format specifier and returns the string¬ 210 // as a value that satisfies error.¬ 211 func Errorf(format string, a ...interface{}) error {¬ 212 ▸ return errors.New(Sprintf(format, a...))¬ 213 }¬ fmt.Errorf() GNUQSJOUHP--
  4. 7 type HTTPError struct {¬ 8 ▸ statusCode int¬ 9

    ▸ message string¬ 10 }¬ 11 ¬ 12 func NewHTTPError(code int, message string) *HTTPError {¬ 13 ▸ return &HTTPError{code, message}¬ 14 }¬ 15 ¬ 16 func (e *HTTPError) Error() string {¬ 17 ▸ return fmt.Sprintf("http error: %d %s", e.statusCode, e.mess age)¬ 18 }¬ ܕΛఆٛ͢Δ
  5. 35 var (¬ 36 ▸ ErrBodyNotAllowed = errors.New("http: request method

    or response status code does not allow body")¬ 37 ▸ ErrHijacked = errors.New("http: connection has been hijacke d")¬ 38 ▸ ErrContentLength = errors.New("http: wrote more than the declare d Content-Length")¬ 39 )¬ ஋Λఆ͓ٛͯ͘͠ύλʔϯ OFUIUUQTFSWFSHP--
  6. 1 func main() {¬ 2 ▸ res := &http.Response{}¬ 3

    ▸ err := res.Write(bytes.NewBufferString("foo"))¬ 4 ▸ if err != nil {¬ 5 ▸ ▸ switch err {¬ 6 ▸ ▸ case http.ErrBodyNotAllowed:¬ 7 ▸ ▸ ▸ // do something¬ 8 ▸ ▸ case http.ErrHijacked:¬ 9 ▸ ▸ ▸ // do something¬ 10 ▸ ▸ case http.ErrContentLength:¬ 11 ▸ ▸ ▸ // do something¬ 12 ▸ ▸ }¬ 13 ▸ }¬ 14 }¬ ஋ͷൺֱͰղऍ
  7. 84 type EscapeError string¬ 85 ¬ 86 func (e EscapeError)

    Error() string {¬ 87 ▸ return "invalid URL escape " + strconv.Quote(string(e))¬ 88 }¬ 89 ¬ 90 type InvalidHostError string¬ 91 ¬ 92 func (e InvalidHostError) Error() string {¬ 93 ▸ return "invalid character " + strconv.Quote(string(e)) + " in host name"¬ 94 }¬ ܕΛఆ͓ٛͯ͘͠ύλʔϯ OFUVSMVSMHP--
  8. 1 func main() {¬ 2 ▸ res := &http.Response{}¬ 3

    ▸ err := res.Write(bytes.NewBufferString("foo"))¬ 4 ▸ if err != nil {¬ 5 ▸ ▸ switch err.(type) {¬ 6 ▸ ▸ case *url.EscapeError:¬ 7 ▸ ▸ ▸ // do something¬ 8 ▸ ▸ case *url.InvalidHostError:¬ 9 ▸ ▸ ▸ // do something¬ 10 ▸ ▸ }¬ 11 ▸ }¬ 12 }¬ ΤϥʔܕͰղऍ
  9. 11 func isExist(err error) bool {¬ 12 ▸ err =

    underlyingError(err)¬ 13 ▸ return err == syscall.EEXIST || err == syscall.ENOTEMPTY || err == ErrExist¬ 14 }¬ 15 ¬ 16 func isNotExist(err error) bool {¬ 17 ▸ err = underlyingError(err)¬ 18 ▸ return err == syscall.ENOENT || err == ErrNotExist¬ 19 }¬ 20 ¬ 21 func isPermission(err error) bool {¬ 22 ▸ err = underlyingError(err)¬ 23 ▸ return err == syscall.EACCES || err == syscall.EPERM || err == ErrPermission¬ 24 }¬ Ћ(PΆ͍FSSPSղऍͷίʔυ PTFSSPS@VOJYHP--
  10. 1 func Do(req *http.Request) (io.ReadCloser, error) {¬ 2 ▸ cli

    := &http.Client{}¬ 3 ▸ res, err := cli.Do(req)¬ 4 ▸ if err != nil {¬ 5 ▸ ▸ return nil, err¬ 6 ▸ }¬ 7 ▸ if res.StatusCode >= 300 {¬ 8 ▸ ▸ buf, err := ioutil.ReadAll(res.Body)¬ 9 ▸ ▸ if err != nil {¬ 10 ▸ ▸ ▸ return nil, err¬ 11 ▸ ▸ }¬ 12 ▸ ▸ return nil, errs.NewHTTPError(res.StatusCode, string(buf))¬ 13 ▸ }¬ 14 ▸ return res.Body, nil¬ 15 }¬ (PͰΑ͋͘Δޫܠ
  11. 1 func Get(url string) (io.ReadCloser, error) {¬ 2 ▸ req,

    err := http.NewRequest(http.MethodGet, url, nil)¬ 3 ▸ if err != nil {¬ 4 ▸ ▸ return nil, err¬ 5 ▸ }¬ 6 ▸ return Do(req)¬ 7 }¬ (PͰΑ͋͘Δޫܠ
  12. 1 func Scrape(url string) ([]string, error) {¬ 2 ▸ body,

    err := http.Get(url)¬ 3 ▸ if err != nil {¬ 4 ▸ ▸ return nil, err¬ 5 ▸ }¬ 6 ▸ hrefs, err := parse(body)¬ 7 ▸ if err != nil {¬ 8 ▸ ▸ return nil, err¬ 9 ▸ }¬ 10 ▸ urls, err := filter(url, hrefs)¬ 11 ▸ if err != nil {¬ 12 ▸ ▸ return nil, err¬ 13 ▸ }¬ 14 ▸ return urls, nil¬ 15 }¬ (PͰΑ͋͘Δޫܠ
  13. 1 func Do(req *http.Request) (io.ReadCloser, error) {¬ 2 ▸ cli

    := &http.Client{}¬ 3 ▸ res, err := cli.Do(req)¬ 4 ▸ if err != nil {¬ 5 ▸ ▸ return nil, errors.Wrap(err, "can not send HTTP request")¬ 6 ▸ }¬ 7 ▸ if res.StatusCode >= 300 {¬ 8 ▸ ▸ buf, err := ioutil.ReadAll(res.Body)¬ 9 ▸ ▸ if err != nil {¬ 10 ▸ ▸ ▸ return nil, errors.Wrap(err, "can not read response body")¬ 11 ▸ ▸ }¬ 12 ▸ ▸ return nil, errs.NewHTTPError(res.StatusCode, string(buf))¬ 13 ▸ }¬ 14 ▸ return res.Body, nil¬ 15 }¬ ΤϥʔʹίϯςΩετΛ͚ͭΔ
  14. 1 func Get(url string) (io.ReadCloser, error) {¬ 2 ▸ req,

    err := http.NewRequest(http.MethodGet, url, nil)¬ 3 ▸ if err != nil {¬ 4 ▸ ▸ return nil, errors.Wrap(err, "can not create request")¬ 5 ▸ }¬ 6 ▸ return Do(req)¬ 7 }¬ ΤϥʔʹίϯςΩετΛ͚ͭΔ
  15. 1 func Scrape(url string) ([]string, error) {¬ 2 ▸ body,

    err := http.Get(url)¬ 3 ▸ if err != nil {¬ 4 ▸ ▸ return nil, errors.Wrapf(err, "can not fetch '%s'", url)¬ 5 ▸ }¬ 6 ▸ hrefs, err := parse(body)¬ 7 ▸ if err != nil {¬ 8 ▸ ▸ return nil, errors.Wrapf(err, "can not parse '%s'", url)¬ 9 ▸ }¬ 10 ▸ urls, err := filter(url, hrefs)¬ 11 ▸ if err != nil {¬ 12 ▸ ▸ return nil, errors.Wrapf(err, "can not filter ‘%v'", hrefs)¬ 13 ▸ }¬ 14 ▸ return urls, nil¬ 15 }¬ ΤϥʔʹίϯςΩετΛ͚ͭΔ