- エラーが発生する可能性のある関数は戻り値にエラーインターフェース(error)を返す必要があり、呼び出しが成功した場合はエラーインターフェースはnilを返し、そうでない場合はエラーを返します。
- 関数呼び出し後にエラーをチェックし、エラーが発生した場合は必要なエラー処理を実行する必要があります。
Go 言語には、 Javaや .NET のような例外処理メカニズムがありません。遅延、パニック、リカバリのシミュレーションは使用できますが、公式はこれを推奨していません。Go 言語の設計者は、他の言語の例外メカニズムが機能すると考えています。上記のロジックは使い過ぎており、関数内で発生する例外に対して多大なリソースを支払う必要があり、同時に関数利用者がエラー処理を面倒に感じてエラーを無視してしまうと、プログラムは予期せぬ瞬間にクラッシュします。
Go 言語は、開発者がエラー処理を通常の開発で実装する必要があるリンクとみなして、エラーを引き起こす可能性のあるすべての関数を正しく処理することを望んでいます。エラーの複雑さにより、開発者はエラー処理を真に習得できます。
ネットパッケージ内の例
net.Dial() は Go 言語システム パッケージ net 内の関数であり、通常はソケット接続を作成するために使用されます。
net.Dial には、Conn と error という 2 つの戻り値があります。この関数はブロックされているため、Socket 操作の後、Conn 接続オブジェクトと error を返します。エラーが発生した場合、error はエラーの種類を通知し、Conn は戻り値を返します空。
Go 言語のエラー処理メカニズムによれば、Conn は重要な戻り値であるため、この関数に error と同様のエラー戻り値を追加します。次のコードを参照してください。
func Dial(network, address string) (Conn, error) {
var d Dialer
return d.Dial(network, address)
}
io パッケージの Writer インターフェイスにもエラーが返されます。コードは次のとおりです。
type Writer interface{
Write(p []byte) (n int, err error)
}
io パッケージには Closer インターフェイスもあります。エラーは 1 つだけ返されます。コードは次のとおりです。
type Closer interface {
Close() error
}
エラーインターフェースの定義形式
error は Go システムによって宣言されたインターフェイスの型であり、コードは次のとおりです。
type error interface {
Error() string
}
Error() 文字列形式に準拠するすべてのメソッドはエラー インターフェイスを実装できます。Error() メソッドはエラーの具体的な説明を返し、ユーザーはこの文字列を通じてどのようなエラーが発生したかを知ることができます。
エラーをカスタマイズする
エラーを返す前に、どのようなエラーが発生する可能性があるかを定義する必要があります。Go 言語では、errors パッケージを使用してエラーを定義します。形式は次のとおりです。
var err = errors.New("this is an error")
エラー文字列は比較的固定されているため、通常はパッケージ スコープ内で宣言され、errors.New を使用するときに直接返されるように最小限に抑える必要があります。
1) エラーパッケージ
Go 言語のエラーにおける New の定義は非常に簡単で、コードは次のとおりです。
// エラーオブジェクトを作成する
func New(text string) error {
return &errorString{text}
}
// エラー文字列
type errorString struct {
s string
}
// 何が起こったかを返す
func (e *errorString) Error() string {
return e.s
}
コードの説明は次のとおりです。
- 2 行目で、errorString 構造体をインスタンス化し、エラー説明のメンバーに値を割り当てます。
- 7 行目では、errorString 構造体を宣言しています。この構造体には、エラーの内容を記述するメンバーが含まれています。
- 12 行目は、エラー インターフェイスの Error() メソッドを実装しており、メンバー内のエラーの説明を返します。
2) コード内で間違った定義を使用している
次のコードは、除数が 0 の場合に事前定義された 0 による除算エラーを返す除算関数を定義します。
package main
import (
"errors"
"fmt"
)
// 除数が0のエラーを定義します
var errDivisionByZero = errors.New("division by zero")
func div(dividend、divisor int) (int、error) {
//除数が0の場合は、そのまま返します
if divisor == 0 {
return 0、errDivisionByZero
}
//通常の計算で、空のエラーを返します
return dividend / divisor、nil
}
func main() {
fmt.Println(div(1、0))
}
コード出力は次のとおりです。
0 division by zero
コードの説明:
- 9 行目、事前定義された 0 による除算エラー。
- 11 行目で、除算関数が宣言され、被除数と除数が入力され、商と誤差が返されます。
- 14行目、割り算の計算で、約数が0の場合、計算結果が無限大になってしまうので、これを避けるために約数を判定し、商が0、約数が0であるというエラーオブジェクトを返しています。
- 19行目は通常の除算計算を行っており、エラーが発生しなければエラーオブジェクトはnilを返します。

errors.New で定義されたエラー文字列のエラー タイプは豊富なエラー情報を提供できないため、エラー情報を返す必要がある場合は、カスタム構造体を使用してエラー インターフェイスを実装する必要があります。
次のコードは、解析エラー (ParseError) を実装します。このエラーには、ファイル名と行番号という 2 つの内容が含まれています。解析エラーの構造には、エラー インターフェイスの Error() メソッドも実装されています。エラーの説明を返すとき、ファイル名と行番号が返されます。
package main
import(
"fmt"
)
// 解析エラーを宣言する
type ParseError struct {
Filename string // ファイル名
Line int // 行番号
}
// errorインターフェイスを実装して、エラーの説明を返す
func(e *ParseError) Error() string {
return fmt.Sprintf("%s:%d", e.Filename, e.Line)
}
// いくつかの解析エラーを作成する
func newParseError(filename string, line int) error {
return &ParseError{filename, line}
}
func main() {
var e error
// ファイル名と行数を含むエラーインスタンスを作成する
e = newParseError("main.go", 1)
//エラーの説明をerrorインターフェイスで確認する
fmt.Println(e.Error())
//エラーインターフェイスの具体的なタイプに基づいて、詳細なエラー情報を取得する
スイッチdetail := e.(タイプ) {
case *ParseError: //これはjson解析エラーです。
fmt.Printf("Filename: %s Line: %d\n", detail.Filename, detail.Line)
default: // 他の種類のエラー
fmt.Println("other error")
}
}
コード出力は次のとおりです。
main.go:1
Filename: main.go Line: 1
コードの説明は次のとおりです。
- 8 行目は解析エラーの構造体を宣言しており、解析エラーにはファイル名と行番号の 2 つのメンバーが含まれています。
- 14 行目はエラー インターフェイスを実装し、メンバーのファイル名と行番号を文字列として返します。
- 19 行目では、指定されたファイル名と行番号に基づいてエラー インスタンスが作成されます。
- 25 行目で、エラー インターフェイスの種類が宣言されています。
- 27 行目でインスタンスが作成され、内部エラー インターフェイスのタイプは *ParserError で、ファイル名 main.go と行番号 1 が付けられます。
- 30 行目で Error() メソッドが呼び出され、15 行目でエラーの詳細が返されます。
- 33 行目では、エラー アサーションを通じてエラーの詳細な種類が取得されます。
- 34行目でエラーの種類を解析すると、エラーの種類が*ParserErrorであることが分かり、この時点で詳細なエラー情報が取得できます。
- 36 行目では、処理できるエラーの種類ではない場合、他の処理のために他のエラーを出力します。
エラー オブジェクトは、エラー インターフェイスの Error() メソッドを実装する必要があります。このようにして、すべてのエラーを文字列で記述することができます。エラーの詳細を知りたい場合は、型アサーションを使用してエラー オブジェクトを次のように変換できます。特定のエラーの種類、エラーの詳細を取得します。