Go での時間処理を学ぶ
この記事では、Go 時間処理の問題に遭遇したときに Baidu を必要とする子供たちを助けることを願って、タイム ライブラリのいくつかの重要な関数とメソッドを紹介します。
タイムゾーンの問題への対処
プログラミングでは、8 時間の時差の問題によく遭遇します。これはタイムゾーンの違いが原因で発生するため、タイムゾーンの違いをより適切に解決するには、いくつかの時間定義標準を理解する必要があります。
GMT (グリニッジ標準時)、グリニッジ標準時。 GMT は地球の自転と公転に基づいて時間を計算し、毎日正午に太陽がイギリスのロンドン郊外にある王立グリニッジ天文台を通過することを定めています。 GMT は以前の世界時です。
UTC (協定世界時)、協定世界時。 UTC は GMT よりも正確で、原子時計に基づいて時間を計算します。秒までの精度が必要ない場合は、UTC=GMT を考慮できます。 UTC は協定世界時です。
グリニッジの本初子午線を起点として、東方向が正、西方向が負になります。世界は 24 の標準時間帯に分かれており、隣接する時間帯間の差は 1 時間です。
1 2 3 4 5 6 7 8 9 10 |
|
中国本土では、東部第 8 時間帯の標準時、つまり北京時間 CST、中国標準時が使用されます。
1 2 |
|
这是默认时区下的结果,<span style="font-size: 15px;">time.Now()</span>
的打印中会标注<span style="font-size: 15px;">+0800 CST</span>
。
假设我们是在美国洛杉矶时区下,那得到的结果是什么呢?
1 2 |
|
可以看到,此时的结果是<span style="font-size: 15px;">-0700 PDT</span>
时间,即 PDT(Pacific Daylight Time)太平洋夏季时间。由于时区差异,两次执行的时间结果相差了 15 小时。
注意,在使用 Docker 容器时,系统默认的时区就是 UTC 时间(0 时区),和我们实际需要的北京时间相差八个小时,这是导致八小时时间差问题的经典场景。
时区问题的应对策略,可以详细查看 src/time/zoneinfo_unix.go 中 initLocal() 函数的加载逻辑。例如,可以通过指定环境变量 TZ,修改/etc/localtime文件等方式来解决。
因为时区问题非常重要,所以放在了文章第一部分讲述。下面开始介绍 time 库的使用。
时间瞬间 time.Time
time 库,最核心的对象是 time.Time 结构体。它的定义如下,用以表示某个瞬间的时间。
1 2 3 4 5 6 7 |
|
计算机在时间处理上,主要涉及到两种时钟。
墙上时钟(wall time),又称为钟表时间,用于表示具体的日期与时间。
单调时钟(monotonic clocks),总是保证时间是向前的,不会出现墙上时钟的回拨问题,因此它很适合用于测量持续时间段。
wall 和 ext 字段就是用于记录墙上时钟和单调时钟,精度为纳秒。字段的对应位数上关联着用于确定时间的具体年、月、日、小时、分钟、秒等信息。
loc 字段记录时区位置,当 loc 为 nil 时,默认为 UTC 时间。
因为 time.Time 用于表示具有纳秒精度的时间瞬间,在程序中通常应该将它作为值存储和传递,而不是指针。
即在时间变量或者结构体字段中,我们应该使用 time.Time,而非 *time.Time。
获取 time.Time
我们可以通过 Now 函数获取当前本地时间
1 |
|
也可以通过 Date 函数,根据年、月、日等时间和时区参数获取指定时间
1 |
|
转换时间戳
计算机世界中,将 UTC 时间 1970 年1月1日 0 时 0 分 0 秒作为 Unix 时间 0。所谓的时间瞬间转换为 Unix 时间戳,即计算的是从 Unix 时间 0 到指定瞬间所经过的秒数、微秒数等。
1 2 3 4 |
|
获取基本字段
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
持续时间 time.Duration
持续时间 time.Duration 用于表示两个时间瞬间 time.Time 之间所经过的时间。它通过 int64 表示纳秒计数,能表示的极限大约为 290 年。
1 2 3 4 |
|
在 Go 中,持续时间只是一个以纳秒为单位的数字而已。如果持续时间等于 1000000000,则它代表的含义是 1 秒或 1000 毫秒或 1000000 微秒或 1000000000 纳秒。
例如,相隔 1 小时的两个时间瞬间 time.Time 值,它们之间的持续时间 time.Duration 值为
1 |
|
Go 的 time 包中定义了这些持续时间常量值
1 2 3 4 5 6 7 8 |
|
同时,time.Duration 提供了能获取各时间粒度数值的方法
1 2 3 4 5 6 |
|
时间计算
在学习了时间瞬间和持续时间之后,我们来看如何做时间计算。
1 |
|
Add 函数用于增加/减少( d 的正值表示增加、负值表示减少) time.Time 的持续时间。我们可以对某瞬时时间,增加或减少指定纳秒级以上的时间。
1 |
|
Sub 函数可以得出两个时间瞬间之间的持续时间。
1 |
|
AddDate 函数基于年、月和日的维度增加/减少 time.Time 的值。
当然,基于当前时间瞬间 time.Now() 的计算是最普遍的需求。因此,time 包还提供了以下便捷的时间计算函数。
1 |
|
Since 函数是 time.Now().Sub(t) 的快捷方法。
1 |
|
Until 函数是 t.Sub(time.Now()) 的快捷方法。
使用示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
|
格式化时间
在其他语言中,一般会使用通用的时间模板来格式化时间。例如 Python,它使用 %Y 代表年、%m 代表月、%d 代表日等。
但是,Go 不一样,它使用固定的时间(需要注意,使用其他的时间是不可以的)作为布局模板,而这个固定时间是 Go 语言的诞生时间。
1 |
|
格式化时间涉及到两个转换函数
1 |
|
Parse 函数用于将时间字符串根据它所能对应的布局转换为 time.Time 对象。
1 |
|
Formate 函数用于将 time.Time 对象根据给定的布局转换为时间字符串。
示例
1 2 3 4 5 6 7 8 |
|
在 time 库中,Go 提供了一些预定义的布局模板常量,这些可以直接拿来使用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|
下面是我们可选的布局参数对照表
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
时区转换
在文章开头,我们介绍了时区问题。如果在代码中,需要获取同一个 time.Time 在不同时区下的结果,我们可以使用它的 In 方法。
1 |
|
它的使用非常简单,直接看示例代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
总结
整体而言,time 库提供的时间处理函数和方法,基本满足我们的使用需求。
以上がGo での時間処理を学ぶの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

Video Face Swap
完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック











Go では、gorilla/websocket パッケージを使用して WebSocket メッセージを送信できます。具体的な手順: WebSocket 接続を確立します。テキスト メッセージを送信します。 WriteMessage(websocket.TextMessage,[]byte("message")) を呼び出します。バイナリ メッセージを送信します。WriteMessage(websocket.BinaryMessage,[]byte{1,2,3}) を呼び出します。

Go では、関数のライフ サイクルには定義、ロード、リンク、初期化、呼び出し、戻り値が含まれます。変数のスコープは関数レベルとブロック レベルに分割されますが、ブロック内の変数はブロック内でのみ表示されます。 。

Go と Go 言語は、異なる特性を持つ別個の存在です。 Go (Golang とも呼ばれます) は、同時実行性、高速なコンパイル速度、メモリ管理、およびクロスプラットフォームの利点で知られています。 Go 言語の欠点としては、他の言語に比べてエコシステムが充実していないこと、構文が厳格であること、動的型付けが欠如していることが挙げられます。

Go では、正規表現を使用してタイムスタンプを照合できます。ISO8601 タイムスタンプの照合に使用されるような正規表現文字列をコンパイルします。 ^\d{4}-\d{2}-\d{2}T \d{ 2}:\d{2}:\d{2}(\.\d+)?(Z|[+-][0-9]{2}:[0-9]{2})$ 。 regexp.MatchString 関数を使用して、文字列が正規表現と一致するかどうかを確認します。

メモリ リークは、ファイル、ネットワーク接続、データベース接続などの使用されなくなったリソースを閉じることによって、Go プログラムのメモリを継続的に増加させる可能性があります。弱参照を使用してメモリ リークを防ぎ、強参照されなくなったオブジェクトをガベージ コレクションの対象にします。 go coroutine を使用すると、メモリ リークを避けるために、終了時にコルーチンのスタック メモリが自動的に解放されます。

IDE を使用して Go 関数のドキュメントを表示する: 関数名の上にカーソルを置きます。ホットキーを押します (GoLand: Ctrl+Q; VSCode: GoExtensionPack をインストールした後、F1 キーを押して「Go:ShowDocumentation」を選択します)。

Go の関数にマップを渡すと、デフォルトでコピーが作成され、コピーへの変更は元のマップには影響しません。元のマップを変更する必要がある場合は、ポインタを介してそれを渡すことができます。空のマップは技術的には nil ポインターであり、空ではないマップを期待する関数に空のマップを渡すとエラーが発生するため、空のマップは慎重に扱う必要があります。

Golang では、エラー ラッパーを使用して、元のエラーにコンテキスト情報を追加することで新しいエラーを作成できます。これを使用すると、さまざまなライブラリまたはコンポーネントによってスローされるエラーの種類を統一し、デバッグとエラー処理を簡素化できます。手順は次のとおりです。errors.Wrap 関数を使用して、元のエラーを新しいエラーにラップします。新しいエラーには、元のエラーのコンテキスト情報が含まれています。 fmt.Printf を使用してラップされたエラーを出力し、より多くのコンテキストとアクション性を提供します。異なる種類のエラーを処理する場合は、errors.Wrap 関数を使用してエラーの種類を統一します。
