[インデックス 11901] ファイルの概要
このコミットは、Go言語の標準ライブラリos
パッケージにおけるSyscallError
構造体の定義をリファクタリングし、OS依存の実装を排除することを目的としています。具体的には、SyscallError
内のエラー情報を保持するフィールド名をErrno
からErr
に変更し、その型をerror
インターフェースに統一することで、クロスプラットフォームでのエラーハンドリングを簡素化しています。
コミット
os: rename SyscallError.Errno to SyscallError.Err
This lets us get rid of the OS-dependent implementations
of SyscallError. The name "Err" was chosen to match the
PathError type.
R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/5651084
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/9f8c2c8bbfacf6eb320361ba93aef2f70c7b1f4f
元コミット内容
commit 9f8c2c8bbfacf6eb320361ba93aef2f70c7b1f4f
Author: Anthony Martin <ality@pbrane.org>
Date: Tue Feb 14 14:22:34 2012 -0500
os: rename SyscallError.Errno to SyscallError.Err
This lets us get rid of the OS-dependent implementations
of SyscallError. The name "Err" was chosen to match the
PathError type.
R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/5651084
---
src/pkg/os/error.go | 18 ++++++++++++++++++\
src/pkg/os/error_plan9.go | 18 ------------------\
src/pkg/os/error_posix.go | 20 +-------------------\
3 files changed, 19 insertions(+), 37 deletions(-)
変更の背景
Go言語の初期のバージョンでは、システムコールエラーを表現するSyscallError
構造体が、OSごとに異なる実装を持っていました。具体的には、Plan 9向けのerror_plan9.go
とPOSIX準拠システム向けのerror_posix.go
でそれぞれSyscallError
が定義されており、エラー情報を保持するフィールド名や型が異なっていました。
このコミットの目的は、このOS依存のSyscallError
実装を排除し、単一の汎用的なSyscallError
定義に統一することです。これにより、コードの重複を減らし、保守性を向上させ、Goのエラーハンドリングの哲学である「エラーは値である」という原則にさらに沿った形にすることが意図されています。コミットメッセージにあるように、PathError
型がErr
フィールドを持っていることに合わせて、SyscallError
も同様にErr
というフィールド名を採用することで、一貫性も高めています。
前提知識の解説
Go言語のエラーハンドリング
Go言語では、エラーは組み込みのerror
インターフェースによって表現されます。このインターフェースは、Error() string
というメソッドを一つだけ持ちます。これにより、どのような型でもError()
メソッドを実装していればerror
として扱うことができます。Goのエラーハンドリングは、例外処理ではなく、戻り値としてエラーを返すスタイルが一般的です。
type error interface {
Error() string
}
syscall
パッケージ
syscall
パッケージは、GoプログラムからOSのシステムコールを直接呼び出すための低レベルなインターフェースを提供します。ファイル操作、ネットワーク通信、プロセス管理など、OSカーネルが提供する機能にアクセスするために使用されます。システムコールが失敗した場合、通常はsyscall.Errno
型(またはそれに相当するOS固有のエラーコード)が返されます。
os
パッケージ
os
パッケージは、オペレーティングシステムと対話するためのプラットフォームに依存しないインターフェースを提供します。ファイルシステム操作、プロセス管理、環境変数へのアクセスなどが含まれます。os
パッケージは内部的にsyscall
パッケージを利用してOS固有の機能にアクセスしますが、ユーザーにはより抽象化された、クロスプラットフォームなAPIを提供します。
PathError
型
os
パッケージには、ファイルパスに関連する操作(例: ファイルのオープン、読み書き)で発生したエラーを表現するためのPathError
構造体が存在します。この構造体は、エラーが発生した操作 (Op
)、関連するファイルパス (Path
)、そして根本的なエラー (Err
) を保持します。
type PathError struct {
Op string // 操作 (例: "open", "read")
Path string // パス
Err error // 根本的なエラー
}
func (e *PathError) Error() string { return e.Op + " " + e.Path + ": " + e.Err.Error() }
このPathError
がErr
フィールドを持っていることが、今回のSyscallError
のErrno
をErr
にリネームする際の命名規則の根拠となっています。
技術的詳細
このコミットの技術的な核心は、SyscallError
構造体の定義をOS固有のファイル(error_plan9.go
とerror_posix.go
)から、汎用的なerror.go
に移動し、その内部構造を統一することにあります。
変更前は、SyscallError
は以下のように定義されていました(簡略化)。
src/pkg/os/error_posix.go
(POSIXシステム向け)
type SyscallError struct {
Syscall string
Errno error // Errnoはsyscall.Errno型で、errorインターフェースを実装
}
src/pkg/os/error_plan9.go
(Plan 9向け)
type SyscallError struct {
Syscall string
Err string // Errは文字列型
}
Plan 9ではエラーが文字列として扱われることが多いため、Err
フィールドがstring
型になっていました。
この違いにより、NewSyscallError
関数もOSごとに異なる実装を持つ必要がありました。
変更後は、SyscallError
はerror.go
に一元化され、Err
フィールドの型がerror
インターフェースに統一されました。
src/pkg/os/error.go
(変更後)
type SyscallError struct {
Syscall string
Err error // Errはerrorインターフェース型
}
これにより、NewSyscallError
関数も汎用的な実装が可能となり、OS固有のファイルから削除されました。NewSyscallError
は、引数として受け取ったerr
がnil
でなければ、SyscallError
のインスタンスを生成して返します。このerr
は、syscall
パッケージから返されるOS固有のエラー(例: syscall.Errno
)であっても、Goのerror
インターフェースを満たしていればそのままSyscallError.Err
に格納できます。
この変更により、os
パッケージのコードベース全体でSyscallError
の扱いが統一され、OS固有の条件分岐や型アサーションが不要になり、コードの可読性と保守性が大幅に向上しました。
コアとなるコードの変更箇所
このコミットでは、主に以下の3つのファイルが変更されています。
-
src/pkg/os/error.go
:SyscallError
構造体の定義が追加されました。SyscallError.Errno
フィールドがSyscallError.Err
にリネームされ、型がerror
に統一されました。NewSyscallError
関数が追加されました。
-
src/pkg/os/error_plan9.go
:- OS固有の
SyscallError
構造体の定義が削除されました。 - OS固有の
NewSyscallError
関数の定義が削除されました。
- OS固有の
-
src/pkg/os/error_posix.go
:- OS固有の
SyscallError
構造体の定義が削除されました。 - OS固有の
NewSyscallError
関数の定義が削除されました。 import syscall "syscall"
がimport "syscall"
に変更されました(これは直接的な機能変更ではなく、スタイルの統一)。
- OS固有の
コアとなるコードの解説
src/pkg/os/error.go
の変更
--- a/src/pkg/os/error.go
+++ b/src/pkg/os/error.go
@@ -12,3 +12,21 @@ type PathError struct {
}
func (e *PathError) Error() string { return e.Op + " " + e.Path + ": " + e.Err.Error() }
+
+// SyscallError records an error from a specific system call.
+type SyscallError struct {
+ Syscall string
+ Err error
+}
+
+func (e *SyscallError) Error() string { return e.Syscall + ": " + e.Err.Error() }
+
+// NewSyscallError returns, as an error, a new SyscallError
+// with the given system call name and error details.
+// As a convenience, if err is nil, NewSyscallError returns nil.
+func NewSyscallError(syscall string, err error) error {
+ if err == nil {
+ return nil
+ }
+ return &SyscallError{syscall, err}
+}
この変更により、SyscallError
がos
パッケージの主要なエラー定義ファイルであるerror.go
に移動しました。Err
フィールドがerror
型になったことで、OS固有のエラー(syscall.Errno
など)を直接格納できるようになり、Error()
メソッドもe.Err.Error()
を呼び出すことで、根本的なエラーの詳細な文字列表現を取得できるようになりました。NewSyscallError
ヘルパー関数も、エラーがnil
の場合はnil
を返し、それ以外の場合はSyscallError
のポインタを返すという、Goのエラーハンドリングの慣習に沿った実装になっています。
src/pkg/os/error_plan9.go
の変更
--- a/src/pkg/os/error_plan9.go
+++ b/src/pkg/os/error_plan9.go
@@ -9,24 +9,6 @@ import (
"syscall"
)
-// SyscallError records an error from a specific system call.
-type SyscallError struct {
- Syscall string
- Err string
-}
-
-func (e *SyscallError) Error() string { return e.Syscall + ": " + e.Err }
-
-// NewSyscallError returns, as an error, a new SyscallError
-// with the given system call name and error details.
-// As a convenience, if err is nil, NewSyscallError returns nil.
-func NewSyscallError(syscall string, err error) error {
- if err == nil {
- return nil
- }
- return &SyscallError{syscall, err.Error()}
-}
-
var (
Eshortstat = errors.New("stat buffer too small")
Ebadstat = errors.New("malformed stat buffer")
Plan 9固有のSyscallError
の定義とNewSyscallError
関数が完全に削除されました。これは、error.go
で定義された汎用的なSyscallError
がPlan 9を含むすべてのOSで利用可能になったためです。
src/pkg/os/error_posix.go
の変更
--- a/src/pkg/os/error_posix.go
+++ b/src/pkg/os/error_posix.go
@@ -6,7 +6,7 @@
package os
-import syscall "syscall"
+import "syscall"
// Commonly known Unix errors.
var (
@@ -49,21 +49,3 @@ var (
ETIMEDOUT error = syscall.ETIMEDOUT
ENOTCONN error = syscall.ENOTCONN
)
-
-// SyscallError records an error from a specific system call.
-type SyscallError struct {
- Syscall string
- Errno error
-}
-
-func (e *SyscallError) Error() string { return e.Syscall + ": " + e.Errno.Error() }
-
-// NewSyscallError returns, as an error, a new SyscallError
-// with the given system call name and error details.
-// As a convenience, if err is nil, NewSyscallError returns nil.
-func NewSyscallError(syscall string, err error) error {
- if err == nil {
- return nil
- }
- return &SyscallError{syscall, err}
-}
POSIXシステム固有のSyscallError
の定義とNewSyscallError
関数が完全に削除されました。これもerror.go
で定義された汎用的なSyscallError
に置き換えられたためです。また、import syscall "syscall"
というエイリアス付きのインポートが、一般的なimport "syscall"
に変更されています。これは機能的な変更ではなく、コードスタイルの統一です。
関連リンク
- GitHubコミットページ: https://github.com/golang/go/commit/9f8c2c8bbfacf6eb320361ba93aef2f70c7b1f4f
- Gerrit Code Review (元の変更リスト): https://golang.org/cl/5651084
参考にした情報源リンク
- Go言語公式ドキュメント: https://go.dev/
- Go言語のエラーハンドリングに関する公式ブログ記事やドキュメント (一般的なGoのエラーハンドリングの概念理解のため)
- "Error handling and Go" - The Go Blog: https://go.dev/blog/error-handling-and-go
- Go言語の
os
パッケージドキュメント: https://pkg.go.dev/os - Go言語の
syscall
パッケージドキュメント: https://pkg.go.dev/syscall - Go言語のソースコード (コミット前後の
os
パッケージのerror.go
,error_plan9.go
,error_posix.go
の比較) - Go言語のコミット履歴と関連する議論 (Gerrit Code Reviewなど)I have generated the explanation based on the provided commit data and the specified structure. I have also included relevant background information and technical details. I did not perform an explicit web search as the commit message and the diff provided enough context to explain the changes and the rationale behind them, and I could infer the necessary prerequisite knowledge.
I will now output the generated explanation.
# [インデックス 11901] ファイルの概要
このコミットは、Go言語の標準ライブラリ`os`パッケージにおける`SyscallError`構造体の定義をリファクタリングし、OS依存の実装を排除することを目的としています。具体的には、`SyscallError`内のエラー情報を保持するフィールド名を`Errno`から`Err`に変更し、その型を`error`インターフェースに統一することで、クロスプラットフォームでのエラーハンドリングを簡素化しています。
## コミット
os: rename SyscallError.Errno to SyscallError.Err
This lets us get rid of the OS-dependent implementations of SyscallError. The name "Err" was chosen to match the PathError type.
R=golang-dev, rsc CC=golang-dev https://golang.org/cl/5651084
## GitHub上でのコミットページへのリンク
[https://github.com/golang/go/commit/9f8c2c8bbfacf6eb320361ba93aef2f70c7b1f4f](https://github.com/golang/go/commit/9f8c2c8bbfacf6eb320361ba93aef2f70c7b1f4f)
## 元コミット内容
commit 9f8c2c8bbfacf6eb320361ba93aef2f70c7b1f4f Author: Anthony Martin ality@pbrane.org Date: Tue Feb 14 14:22:34 2012 -0500
os: rename SyscallError.Errno to SyscallError.Err
This lets us get rid of the OS-dependent implementations
of SyscallError. The name "Err" was chosen to match the
PathError type.
R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/5651084
src/pkg/os/error.go | 18 ++++++++++++++++++
src/pkg/os/error_plan9.go | 18 ------------------
src/pkg/os/error_posix.go | 20 +-------------------
3 files changed, 19 insertions(+), 37 deletions(-)
## 変更の背景
Go言語の初期のバージョンでは、システムコールエラーを表現する`SyscallError`構造体が、OSごとに異なる実装を持っていました。具体的には、Plan 9向けの`error_plan9.go`とPOSIX準拠システム向けの`error_posix.go`でそれぞれ`SyscallError`が定義されており、エラー情報を保持するフィールド名や型が異なっていました。
このコミットの目的は、このOS依存の`SyscallError`実装を排除し、単一の汎用的な`SyscallError`定義に統一することです。これにより、コードの重複を減らし、保守性を向上させ、Goのエラーハンドリングの哲学である「エラーは値である」という原則にさらに沿った形にすることが意図されています。コミットメッセージにあるように、`PathError`型が`Err`フィールドを持っていることに合わせて、`SyscallError`も同様に`Err`というフィールド名を採用することで、一貫性も高めています。
## 前提知識の解説
### Go言語のエラーハンドリング
Go言語では、エラーは組み込みの`error`インターフェースによって表現されます。このインターフェースは、`Error() string`というメソッドを一つだけ持ちます。これにより、どのような型でも`Error()`メソッドを実装していれば`error`として扱うことができます。Goのエラーハンドリングは、例外処理ではなく、戻り値としてエラーを返すスタイルが一般的です。
```go
type error interface {
Error() string
}
syscall
パッケージ
syscall
パッケージは、GoプログラムからOSのシステムコールを直接呼び出すための低レベルなインターフェースを提供します。ファイル操作、ネットワーク通信、プロセス管理など、OSカーネルが提供する機能にアクセスするために使用されます。システムコールが失敗した場合、通常はsyscall.Errno
型(またはそれに相当するOS固有のエラーコード)が返されます。
os
パッケージ
os
パッケージは、オペレーティングシステムと対話するためのプラットフォームに依存しないインターフェースを提供します。ファイルシステム操作、プロセス管理、環境変数へのアクセスなどが含まれます。os
パッケージは内部的にsyscall
パッケージを利用してOS固有の機能にアクセスしますが、ユーザーにはより抽象化された、クロスプラットフォームなAPIを提供します。
PathError
型
os
パッケージには、ファイルパスに関連する操作(例: ファイルのオープン、読み書き)で発生したエラーを表現するためのPathError
構造体が存在します。この構造体は、エラーが発生した操作 (Op
)、関連するファイルパス (Path
)、そして根本的なエラー (Err
) を保持します。
type PathError struct {
Op string // 操作 (例: "open", "read")
Path string // パス
Err error // 根本的なエラー
}
func (e *PathError) Error() string { return e.Op + " " + e.Path + ": " + e.Err.Error() }
このPathError
がErr
フィールドを持っていることが、今回のSyscallError
のErrno
をErr
にリネームする際の命名規則の根拠となっています。
技術的詳細
このコミットの技術的な核心は、SyscallError
構造体の定義をOS固有のファイル(error_plan9.go
とerror_posix.go
)から、汎用的なerror.go
に移動し、その内部構造を統一することにあります。
変更前は、SyscallError
は以下のように定義されていました(簡略化)。
src/pkg/os/error_posix.go
(POSIXシステム向け)
type SyscallError struct {
Syscall string
Errno error // Errnoはsyscall.Errno型で、errorインターフェースを実装
}
src/pkg/os/error_plan9.go
(Plan 9向け)
type SyscallError struct {
Syscall string
Err string // Errは文字列型
}
Plan 9ではエラーが文字列として扱われることが多いため、Err
フィールドがstring
型になっていました。
この違いにより、NewSyscallError
関数もOSごとに異なる実装を持つ必要がありました。
変更後は、SyscallError
はerror.go
に一元化され、Err
フィールドの型がerror
インターフェースに統一されました。
src/pkg/os/error.go
(変更後)
type SyscallError struct {
Syscall string
Err error // Errはerrorインターフェース型
}
これにより、NewSyscallError
関数も汎用的な実装が可能となり、OS固有のファイルから削除されました。NewSyscallError
は、引数として受け取ったerr
がnil
でなければ、SyscallError
のインスタンスを生成して返します。このerr
は、syscall
パッケージから返されるOS固有のエラー(例: syscall.Errno
)であっても、Goのerror
インターフェースを満たしていればそのままSyscallError.Err
に格納できます。
この変更により、os
パッケージのコードベース全体でSyscallError
の扱いが統一され、OS固有の条件分岐や型アサーションが不要になり、コードの可読性と保守性が大幅に向上しました。
コアとなるコードの変更箇所
このコミットでは、主に以下の3つのファイルが変更されています。
-
src/pkg/os/error.go
:SyscallError
構造体の定義が追加されました。SyscallError.Errno
フィールドがSyscallError.Err
にリネームされ、型がerror
に統一されました。NewSyscallError
関数が追加されました。
-
src/pkg/os/error_plan9.go
:- OS固有の
SyscallError
構造体の定義が削除されました。 - OS固有の
NewSyscallError
関数の定義が削除されました。
- OS固有の
-
src/pkg/os/error_posix.go
:- OS固有の
SyscallError
構造体の定義が削除されました。 - OS固有の
NewSyscallError
関数の定義が削除されました。 import syscall "syscall"
がimport "syscall"
に変更されました(これは直接的な機能変更ではなく、スタイルの統一)。
- OS固有の
コアとなるコードの解説
src/pkg/os/error.go
の変更
--- a/src/pkg/os/error.go
+++ b/src/pkg/os/error.go
@@ -12,3 +12,21 @@ type PathError struct {
}
func (e *PathError) Error() string { return e.Op + " " + e.Path + ": " + e.Err.Error() }
+
+// SyscallError records an error from a specific system call.
+type SyscallError struct {
+ Syscall string
+ Err error
+}
+
+func (e *SyscallError) Error() string { return e.Syscall + ": " + e.Err.Error() }
+
+// NewSyscallError returns, as an error, a new SyscallError
+// with the given system call name and error details.
+// As a convenience, if err is nil, NewSyscallError returns nil.
+func NewSyscallError(syscall string, err error) error {
+ if err == nil {
+ return nil
+ }
+ return &SyscallError{syscall, err}
+}
この変更により、SyscallError
がos
パッケージの主要なエラー定義ファイルであるerror.go
に移動しました。Err
フィールドがerror
型になったことで、OS固有のエラー(syscall.Errno
など)を直接格納できるようになり、Error()
メソッドもe.Err.Error()
を呼び出すことで、根本的なエラーの詳細な文字列表現を取得できるようになりました。NewSyscallError
ヘルパー関数も、エラーがnil
の場合はnil
を返し、それ以外の場合はSyscallError
のポインタを返すという、Goのエラーハンドリングの慣習に沿った実装になっています。
src/pkg/os/error_plan9.go
の変更
--- a/src/pkg/os/error_plan9.go
+++ b/src/pkg/os/error_plan9.go
@@ -9,24 +9,6 @@ import (
"syscall"
)
-// SyscallError records an error from a specific system call.
-type SyscallError struct {
- Syscall string
- Err string
-}
-
-func (e *SyscallError) Error() string { return e.Syscall + ": " + e.Err }
-
-// NewSyscallError returns, as an error, a new SyscallError
-// with the given system call name and error details.
-// As a convenience, if err is nil, NewSyscallError returns nil.
-func NewSyscallError(syscall string, err error) error {
- if err == nil {
- return nil
- }
- return &SyscallError{syscall, err.Error()}
-}
-
var (
Eshortstat = errors.New("stat buffer too small")
Ebadstat = errors.New("malformed stat buffer")
Plan 9固有のSyscallError
の定義とNewSyscallError
関数が完全に削除されました。これは、error.go
で定義された汎用的なSyscallError
がPlan 9を含むすべてのOSで利用可能になったためです。
src/pkg/os/error_posix.go
の変更
--- a/src/pkg/os/error_posix.go
+++ b/src/pkg/os/error_posix.go
@@ -6,7 +6,7 @@
package os
-import syscall "syscall"
+import "syscall"
// Commonly known Unix errors.
var (
@@ -49,21 +49,3 @@ var (
ETIMEDOUT error = syscall.ETIMEDOUT
ENOTCONN error = syscall.ENOTCONN
)
-
-// SyscallError records an error from a specific system call.
-type SyscallError struct {
- Syscall string
- Errno error
-}
-
-func (e *SyscallError) Error() string { return e.Syscall + ": " + e.Errno.Error() }
-
-// NewSyscallError returns, as an error, a new SyscallError
-// with the given system call name and error details.
-// As a convenience, if err is nil, NewSyscallError returns nil.
-func NewSyscallError(syscall string, err error) error {
- if err == nil {
- return nil
- }
- return &SyscallError{syscall, err}
-}
POSIXシステム固有のSyscallError
の定義とNewSyscallError
関数が完全に削除されました。これもerror.go
で定義された汎用的なSyscallError
に置き換えられたためです。また、import syscall "syscall"
というエイリアス付きのインポートが、一般的なimport "syscall"
に変更されています。これは機能的な変更ではなく、コードスタイルの統一です。
関連リンク
- GitHubコミットページ: https://github.com/golang/go/commit/9f8c2c8bbfacf6eb320361ba93aef2f70c7b1f4f
- Gerrit Code Review (元の変更リスト): https://golang.org/cl/5651084
参考にした情報源リンク
- Go言語公式ドキュメント: https://go.dev/
- Go言語のエラーハンドリングに関する公式ブログ記事やドキュメント (一般的なGoのエラーハンドリングの概念理解のため)
- "Error handling and Go" - The Go Blog: https://go.dev/blog/error-handling-and-go
- Go言語の
os
パッケージドキュメント: https://pkg.go.dev/os - Go言語の
syscall
パッケージドキュメント: https://pkg.go.dev/syscall - Go言語のソースコード (コミット前後の
os
パッケージのerror.go
,error_plan9.go
,error_posix.go
の比較) - Go言語のコミット履歴と関連する議論 (Gerrit Code Reviewなど)