[インデックス 11246] ファイルの概要
このコミットは、Go言語のsyscall
パッケージにおいて、Timespec
およびTimeval
構造体にUnix()
メソッドを追加するものです。これにより、これらの時間表現構造体からUnixエポック秒とナノ秒(またはマイクロ秒)を直接取得できるようになります。
コミット
commit 7d418aeed2f93014d2717da36dd08376e3fe2bf9
Author: Brad Fitzpatrick <bradfitz@golang.org>
Date: Wed Jan 18 19:05:44 2012 -0800
syscall: add Unix method to TimeSpec, TimeVal
Fixes #2534
R=golang-dev, dave, alex.brainman
CC=golang-dev
https://golang.org/cl/5554057
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/7d418aeed2f93014d2717da36dd08376e3fe2bf9
元コミット内容
syscall
パッケージのTimespec
およびTimeval
構造体にUnix()
メソッドを追加しました。これにより、これらの構造体からUnixエポック秒とナノ秒(またはマイクロ秒)を取得できるようになります。
変更の背景
この変更は、Go言語のIssue #2534を修正するために行われました。Issue #2534は、syscall.Timespec
とsyscall.Timeval
がtime.Time
型に変換できないという問題提起でした。具体的には、time.Unix()
関数がint64
型の秒とナノ秒を引数として取るため、Timespec
やTimeval
のフィールドを直接渡すことができませんでした。このコミットは、これらの構造体にUnix()
メソッドを追加することで、time.Unix()
関数への変換を容易にし、よりGoらしい(idiomaticな)方法で時間情報を扱うことを可能にしました。
前提知識の解説
Unix時間 (Unix Epoch Time)
Unix時間(またはPOSIX時間)は、協定世界時 (UTC) の1970年1月1日00時00分00秒(Unixエポック)からの経過秒数で時間を表現する方法です。うるう秒は考慮されません。多くのシステムで内部的に時間を扱う際の標準的な形式として利用されています。
syscall
パッケージ
Go言語のsyscall
パッケージは、オペレーティングシステム(OS)の低レベルなシステムコールへのインターフェースを提供します。ファイル操作、プロセス管理、ネットワーク通信など、OSが提供する基本的な機能に直接アクセスするために使用されます。このパッケージはOSに依存する部分が多く、OSごとに異なる実装を持つことがあります。
Timespec
構造体
Timespec
構造体は、Unix系OSで高精度な時間情報を表現するために使用されます。通常、秒 (tv_sec
) とナノ秒 (tv_nsec
) の2つのフィールドを持ちます。
Sec
: 秒を表すint64
型。Nsec
: ナノ秒を表すint64
型。
Timeval
構造体
Timeval
構造体もTimespec
と同様に時間情報を表現しますが、こちらは秒 (tv_sec
) とマイクロ秒 (tv_usec
) の2つのフィールドを持ちます。
Sec
: 秒を表すint64
型。Usec
: マイクロ秒を表すint64
型。
これらの構造体は、ファイルシステムのタイムスタンプ(作成時刻、最終アクセス時刻、最終更新時刻など)や、select()
、poll()
などのシステムコールにおけるタイムアウト値の指定など、様々な場面で利用されます。
Go言語のメソッド
Go言語では、構造体に対してメソッドを定義することができます。これは、特定の構造体のデータに対して操作を行う関数を、その構造体に関連付けるための仕組みです。func (t Type) MethodName(...)
の形式で定義され、t
はレシーバと呼ばれます。
技術的詳細
このコミットの主要な目的は、syscall
パッケージ内のTimespec
とTimeval
構造体から、標準的なUnix時間形式(秒とナノ秒)を簡単に取得できるようにすることです。
Unix()
メソッドの追加
Timespec
とTimeval
にUnix()
メソッドが追加されました。このメソッドは、Go標準ライブラリのtime.Time
型が持つUnix()
およびUnixNano()
メソッドと同様のセマンティクスを提供します。
-
Timespec
のUnix()
メソッド:func (ts *Timespec) Unix() (sec int64, nsec int64)
このメソッドは、Timespec
構造体のSec
フィールドをそのまま秒として、Nsec
フィールドをそのままナノ秒として返します。これはTimespec
が元々秒とナノ秒で構成されているため、単純なフィールドのキャストで済みます。 -
Timeval
のUnix()
メソッド:func (tv *Timeval) Unix() (sec int64, nsec int64)
このメソッドは、Timeval
構造体のSec
フィールドを秒として返します。ナノ秒については、Usec
フィールド(マイクロ秒)を1000倍してナノ秒に変換します(1マイクロ秒 = 1000ナノ秒)。
WindowsにおけるTimespec
の定義
興味深い点として、src/pkg/syscall/syscall_windows.go
において、Windows環境ではTimespec
構造体が「発明された構造体」として定義されています。これは、Windows APIが直接Timespec
のような構造体を提供しないため、Goのsyscall
パッケージがUnix系OSとの一貫性を保つために内部的に定義していることを示しています。この定義は、Sec
とNsec
のフィールドを持つことで、Unix系OSのTimespec
と互換性のあるインターフェースを提供します。
// Timespec is an invented structure on Windows, but here for
// consistency with the syscall package for other operating systems.
type Timespec struct {
Sec int64
Nsec int64
}
この定義により、Windows上でもTimespec
型を扱うことができ、今回追加されたUnix()
メソッドも同様に利用可能になります。
コアとなるコードの変更箇所
src/pkg/syscall/syscall.go
--- a/src/pkg/syscall/syscall.go
+++ b/src/pkg/syscall/syscall.go
@@ -29,3 +29,11 @@ func StringBytePtr(s string) *byte { return &StringByteSlice(s)[0] }\n // Single-word zero for use when we need a valid pointer to 0 bytes.\n // See mksyscall.pl.\n var _zero uintptr\n+\n+func (ts *Timespec) Unix() (sec int64, nsec int64) {\n+\treturn int64(ts.Sec), int64(ts.Nsec)\n+}\n+\n+func (tv *Timeval) Unix() (sec int64, nsec int64) {\n+\treturn int64(tv.Sec), int64(tv.Usec) * 1000\n+}\ndiff --git a/src/pkg/syscall/syscall_windows.go b/src/pkg/syscall/syscall_windows.go
src/pkg/syscall/syscall_windows.go
--- a/src/pkg/syscall/syscall_windows.go
+++ b/src/pkg/syscall/syscall_windows.go
@@ -624,6 +624,13 @@ func (w WaitStatus) Signaled() bool { return false }\n \n func (w WaitStatus) TrapCause() int { return -1 }\n \n+// Timespec is an invented structure on Windows, but here for\n+// consistency with the syscall package for other operating systems.\n+type Timespec struct {\n+\tSec int64\n+\tNsec int64\n+}\n+\n // TODO(brainman): fix all needed for net\n \n func Accept(fd Handle) (nfd Handle, sa Sockaddr, err error) { return 0, nil, EWINDOWS }\n```
## コアとなるコードの解説
### `src/pkg/syscall/syscall.go` の変更
このファイルでは、`Timespec`と`Timeval`のポインタレシーバを持つ`Unix()`メソッドが追加されています。
```go
func (ts *Timespec) Unix() (sec int64, nsec int64) {
return int64(ts.Sec), int64(ts.Nsec)
}
ts *Timespec
:Timespec
構造体へのポインタをレシーバとして受け取ります。これにより、メソッド内でTimespec
のフィールドにアクセスできます。return int64(ts.Sec), int64(ts.Nsec)
:Timespec
のSec
とNsec
フィールドは既に適切な型(int64
)であるため、そのまま返されます。
func (tv *Timeval) Unix() (sec int64, nsec int64) {
return int64(tv.Sec), int64(tv.Usec) * 1000
}
tv *Timeval
:Timeval
構造体へのポインタをレシーバとして受け取ります。return int64(tv.Sec), int64(tv.Usec) * 1000
:Timeval
のSec
フィールドはそのまま秒として返されます。Usec
フィールドはマイクロ秒単位であるため、ナノ秒に変換するために1000
を乗算しています。
これらのメソッドの追加により、例えばsyscall.Stat_t
構造体に含まれるAtim
(アクセス時刻)、Mtim
(変更時刻)、Ctim
(作成時刻)などのTimespec
型のフィールドから、直接Unix時間形式の秒とナノ秒を取得できるようになります。
src/pkg/syscall/syscall_windows.go
の変更
このファイルでは、Windows環境におけるTimespec
構造体の定義が追加されています。
// Timespec is an invented structure on Windows, but here for
// consistency with the syscall package for other operating systems.
type Timespec struct {
Sec int64
Nsec int64
}
- コメントにあるように、Windowsにはネイティブな
Timespec
構造体は存在しません。しかし、Goのsyscall
パッケージがクロスプラットフォームで一貫したインターフェースを提供するために、この構造体がWindows向けに「発明」されました。 Sec
とNsec
フィールドを持つことで、Unix系OSのTimespec
と互換性のあるデータ構造を提供し、syscall.go
で定義されたUnix()
メソッドがWindows上でも機能するようにしています。
この変更は、Go言語が異なるOSのシステムコールを抽象化し、開発者に一貫したAPIを提供するという設計思想を反映しています。
関連リンク
- Go言語の
syscall
パッケージのドキュメント: https://pkg.go.dev/syscall - Go言語の
time
パッケージのドキュメント: https://pkg.go.dev/time - Unix時間に関するWikipediaの記事: https://ja.wikipedia.org/wiki/Unix%E6%99%82%E9%96%93
参考にした情報源リンク
- Go Issue #2534:
syscall.Timespec
andsyscall.Timeval
should haveUnix()
method (or be convertible totime.Time
) - https://github.com/golang/go/issues/2534 - Go CL 5554057:
syscall: add Unix method to TimeSpec, TimeVal
- https://golang.org/cl/5554057 time.Time
のUnix()
メソッドに関するGoのドキュメント: https://pkg.go.dev/time#Time.Unixtime.Time
のUnixNano()
メソッドに関するGoのドキュメント: https://pkg.go.dev/time#Time.UnixNano