0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Go言語におけるエラー型の生成方法 | erros.Newとfmt.Errorf

Posted at

Go言語のコードを書いている時に意図的にエラー型を生成したい時がある

例えば、os.Openやos.Createの関数などはerrorを返す関数になっています。このようなerrorが自然に発生する場合にはerrorを意図的に生成する必要がありません。

しかし、コードを書いていると、errorを意図的に生成したいタイミングがあります。

エラーが自然に発生しないパターンの例

  • string型の引数が空文字の場合、errorを返したい時

▼サンプルコード

func exampleFunc(str string) error{
	if str == "" {
		panic("empty string") //本当はerrorを返したい!
	}
	return nil
}
  • switch文のdefaultでpanicではなく、errorを返したい時

▼サンプルコード

func exampleFunc(flag int) error{
	switch(flag) {
	case 1:
		fmt.Println("case 1")
	case 2:
		fmt.Println("case 2")
	case 3:
		fmt.Println("case 3")
	default:
		panic("invalid flag") //本当はエラーを返したい!
	}
	return nil
}

そもそもerror型とは何か?

error型とはそもそもどんな型なのかをまずは整理します。

  • error型はビルトインのインターフェース型の一つ。

▼定義

type error interface {
    Error() string
}
  • よく使われている「error」はerrorsパッケージにて実装されたerrorString構造体
type errorString struct {
    s string
}

func (e *errorString) Error() string {
    return e.s
}
  • インターフェースであるため、このインターフェースを実装する構造体を定義すれば、独自定義のエラーを実装することも可能。

▼サンプルコード

// 構造体を定義
type MyError struct {
	message string
	code string
}

// Errorメソッドを実装。(Error型で決められたインターフェースを実装、満たす)
func (m MyError)Error() string {
	return m.code + " : " + m.message
}

// 実際に独自定義したMyErrorを呼び出してみる
func exampleFunc(str string) error{

	var err MyError

	if str == "" {
		err.code = "500"
		err.message = "internal server error"
		fmt.Println("check Error():", err.Error())
		return err
	}

	fmt.Println("str:", str)

	return nil
}

エラー型を意図的に生成する方法

エラー変数を意図的に生成する主な方法は下記2つあるようです。それぞれメリットについてもまとめてみました。

方法1:errors.New()関数を利用する

  • errors.New()は引数にエラーメッセージとなる文字列を受け取り、エラー型を返す
  • エラーメッセージをカスタマイズしたい場合は、事前にエラーメッセージとなる文字列を作っておく必要がある
package main

import (
	"errors"
	"fmt"
	"log"
)

func exampleFunc(str string) error{
	if str == "" {
		err := errors.New("エラーです")
		return err
	}
	return nil
}

func main(){
	emptyStr := ""
	err := exampleFunc(emptyStr)
	if err != nil {
		log.Fatal(err) //出力例:2022/xx/xx xx:xx:xx エラーです
	}
	fmt.Println("success")
}

▼メリット

  • 既にエラー出力したい文字列が用意されている時には便利
  • シンプルなエラーを生成したい時に便利

方法2:fmt.Errorf()関数を利用する

  • fmt.Errorf()はfmt.Sprintf()のようにフォーマットを指定したエラーメッセージを持つerror型を生成する。
package main

import (
	"fmt"
	"log"
)

func exampleFunc(str string) error{
	if str == "" {
		err := fmt.Errorf("%s", "エラーです")
		return err
	}
	return nil
}

func main(){
	emptyStr := ""
	err := exampleFunc(emptyStr)
	if err != nil {
		log.Fatal(err) //出力例:2022/xx/xx xx:xx:xx エラーです
	}
	fmt.Println("success")
}

▼メリット

  • やはりフォーマット指定でエラー文字列をカスタマイズできること。fmt.Sprintfと同じような感覚で利用できる。
  • 記述量は少なくできるかも。

結論:errors.New()とfmt.Errorf()はどちらがいい?

正直、あまり変わらない印象なので、どちらでもご自身がしっくりくる方でいいと思います!

記述量を少なくしたい場合は、fmt.Errorf()の方が少なくなりそうです。

参考文献

https://astaxie.gitbooks.io/build-web-application-with-golang/content/ja/11.1.html

https://qiita.com/haazime/items/88ae8426a3e61b824b1d

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?