🍳

Goのエラーの書き方(王道とcatch相当ver)

2023/03/28に公開約2,600字

引数が"a"の場合エラーを出す例

package main

import (
	"errors"
	"fmt"
)

func main() {

	// エラーハンドリングS
	err1 := errTest("b")
	if err1 != nil {
		fmt.Printf("%s\n", err1)
		return
	}
	fmt.Printf("%s\n", err1) //%!s(<nil>)

	// エラーハンドリング
	err2 := errTest("a")
	if err2 != nil {
		fmt.Printf("%s\n", err2) //some error
		return
	}
}

func errTest(arg string) error { //エラーを作る関数
	if arg == "a" {
		return errors.New("some error")
	}
	return nil
}

引数が"a"の場合エラーを出す、それ以外の場合は引数を返す。

func main() {

	// エラーハンドリング
	val3, err3 := errTest2("b")
	if err3 != nil {
		fmt.Printf("%s\n", err3)
		return
	}
	fmt.Printf("%s\n", val3)

	// エラーハンドリング
	val4, err4 := errTest2("a")
	if err4 != nil {
		fmt.Printf("%s\n", err4)
		return
	}
	fmt.Printf("%s\n", val4)

}

func errTest2(arg string) (string, error) {
	if arg == "a" {
		return "", errors.New("some error")
	}
	return arg, nil
}

try-catch構文のcatchがGo言語にもある-> recover()関数

package main

import "fmt"

func main() {
	result, err := myFunction()
	if err != nil {
		fmt.Println("Error:", err)
		return
	}
	fmt.Println("Result:", result)
}

func myFunction() (result int, err error) {
	defer func() { //無名関数
		if r := recover(); r != nil { //panic(強制的に処理中断)が実行された場合recover()でキャッチする(try-catch構文のcatch)
			err = fmt.Errorf("panic occurred: %v", r)
		}
	}()
	strA := someFunction() //panicが発生するとrecover()で拾われる
	return strA, nil
}

func someFunction() int {
	defer fmt.Println("Deferred statement in someFunction")

	// This line will panic because the index is out of range
	arr := []int{1, 2, 3}
	return arr[5]
}

try-catch構文のcatch相当の実装

package main

import "fmt"

type Queue struct { //構造体の独自型
	stack1 []int
	stack2 []int
}

func (q *Queue) Enqueue(val int) {
	q.stack1 = append(q.stack1, val) //末尾に追加
}

func (q *Queue) Dequeue() int {
	/** 先回りしてエラーハンドリング
	if len(q.stack1) == 0 && len(q.stack2) == 0 {
		panic("Queue is empty")
	}
	*/

	if len(q.stack2) == 0 {
		for len(q.stack1) > 0 {
			val := q.stack1[len(q.stack1)-1]         //末尾要素の代入
			q.stack1 = q.stack1[0 : len(q.stack1)-1] //list末尾を消す上書き
			q.stack2 = append(q.stack2, val)         //listの末尾要素を移すように追加
		}
	}

	val := q.stack2[len(q.stack2)-1]         //末尾要素の代入
	q.stack2 = q.stack2[0 : len(q.stack2)-1] //list末尾を消す上書き
	return val
}

func main() {
	//try-catch構文ライクでエラーハンドリング
	defer func() { //無名関数
		if err := recover(); err != nil { //panic(強制的に処理中断)が実行された場合recover()でキャッチする(try-catch構文のcatch)
			fmt.Println("Recovered from:", err)
		}
	}()

	q := Queue{}
	q.Enqueue(1)
	q.Enqueue(2)
	q.Enqueue(3)
	fmt.Println(q.Dequeue()) // 1
	fmt.Println(q.Dequeue()) // 2
	fmt.Println(q.Dequeue()) // 3
	fmt.Println(q.Dequeue()) // panic
	q.Enqueue(3)
	fmt.Println(q.Dequeue()) // 3
}

Discussion

ログインするとコメントできます