国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

ホームページ バックエンド開(kāi)発 Golang OTP の謎を解く: トークンのオフライン生成の背後にあるロジック

OTP の謎を解く: トークンのオフライン生成の背後にあるロジック

Dec 12, 2024 pm 10:23 PM

こんにちは!別の夕方、家に帰る途中、私は郵便受けをチェックすることにしました。私が言っているのはメールの受信箱のことではなく、郵便配達(dá)員が物理的な手紙を入れる昔ながらの実際の箱のことです。そして驚いたことに、そこに何かが入った封筒を見(jiàn)つけました。それを開(kāi)いている間、私はそれが何十年も遅れたホグワーツからの手紙であることを望みながらしばらく過(guò)ごしました。しかし、それが銀行からの退屈な「大人向け」の手紙であることに気づき、私は地球に戻らなければなりませんでした。私は本文をざっと読んで、クールな子供たちのための私の「デジタル専用」銀行が地元市場(chǎng)の最大手によって買収されたことに気づきました。そして、新たな始まりのしるしとして、封筒にこれを追加しました:

Demystifying OTPs: the logic behind the offline generation of tokens

使用方法の説明書(shū)も添えてあります。

あなたも私と同じで、そのような技術(shù)革新に一度も出會(huì)ったことがない人のために、この手紙から學(xué)んだことを共有させてください。新しい所有者は會(huì)社のセキュリティ ポリシーを強(qiáng)制することにしました。つまり、すべてのユーザーがセキュリティ ポリシーを適用することを意味します。今後のアカウントでは MFA が有効になります (ちなみに、それは稱賛に値します)。そして、上記のデバイスは、銀行口座にログインする際の 2 番目の要素として使用される 6 桁の長(zhǎng)さのワンタイム トークンを生成します?;镜膜摔稀uthy、Google Authenticator、2FAS などのアプリと同じように動(dòng)作しますが、物理的な形狀が異なります。

それで、試してみたところ、ログインプロセスはスムーズに進(jìn)みました。デバイスに 6 桁のコードが表示され、それを銀行アプリに入力すると、ログインできました。萬(wàn)歳!しかし、あることが私に衝撃を與えました。これはどのように機(jī)能するのでしょうか?何らかの方法でインターネットに接続しているわけはありませんが、銀行のサーバーで受け入れられる正しいコードを生成することに成功しました。うーん...SIMカードかそれに似たものが入っているのでしょうか?まさか!

私の人生は決して同じではないことに気づき、上で述べたアプリ (Authy とその友達(dá)) について疑問(wèn)に思い始めました。私の內(nèi)なる研究心が目覚めたので、攜帯電話を機(jī)內(nèi)モードに切り替えたところ、驚いたことに、オフラインでもまったく問(wèn)題なく動(dòng)作することに気付きました。アプリのサーバーが受け入れるコードを生成し続けているのです。面白いですね!

あなたはどうかわかりませんが、私はワンタイムトークンの流れを常に當(dāng)然のことだと思っており、実際にそれについてきちんと考えたことはありませんでした(特に最近では、特別な理由がない限り、私の攜帯電話にインターネットが接続されていないことはめったにありません)私はアウトドアの冒険をしているのですが)、それが私の驚きの根本的な原因でした。それ以外の場(chǎng)合、生成プロセスは純粋にローカルであり、外部アクターから見(jiàn)て安全であるため、セキュリティの観點(diǎn)からこのように動(dòng)作することは完全に理にかなっています。しかし、それはどのように機(jī)能するのでしょうか?

そうですね、Google や ChatGPT などの最新テクノロジーを使用すると、簡(jiǎn)単に答えを見(jiàn)つけることができます。しかし、この技術(shù)的な問(wèn)題は私にとって面白そうだったので、まずは自分で解決してみることにしました。

要件

手元にあるものから始めましょう:

  • 6 桁のコードを生成するオフライン デバイス
  • これらのコードを受け入れ、検証し、正しい場(chǎng)合に緑色の信號(hào)を発するサーバー

サーバー検証部分は、サーバーがオフライン デバイスと比較するために同じコードを生成できる必要があることを示唆しています。うーん、それは役に立つかもしれません。

新しい「おもちゃ」をさらに観察すると、さらに多くの発見(jiàn)がもたらされました:

  • 一度オフにしてからオフにすると、通常は前と同じコードが表示されます
  • ただし、場(chǎng)合によっては変更されることもあります

私が思いついた唯一の論理的説明は、これらのコードには一定の壽命があるということです。 「1-2-3-...-N」形式でその時(shí)間を數(shù)えようとした話をしたいのですが、それは真実ではありません。大きなヒントは次のようなアプリから得ました。 Authy and Co、私はそこで 30 秒の TTL を見(jiàn)ました。良い発見(jiàn)です。これを既知の事実のリストに追加しましょう。

これまでの要件をまとめてみましょう:

  • 6 桁形式での (ランダムではなく) 予測(cè)可能なコード生成
  • 生成ロジックは再現(xiàn)可能である必要があり、プラットフォームに関係なく同じ結(jié)果を得ることができます
  • コードの有効期間は 30 秒です。これは、この時(shí)間枠內(nèi)で生成アルゴリズムが同じ?jìng)帳蛏嗓工毪长趣蛞馕钉筏蓼?/li>

大きな疑問(wèn)

わかりましたが、主な疑問(wèn)は未解決のままです。オフライン アプリはどのようにして他のアプリの値と一致する値を生成できるのでしょうか?彼らの共通點(diǎn)は何でしょうか?

もしあなたが『ロード?オブ?ザ?リング』の世界に興味があるなら、ビルボがゴラムとなぞなぞゲームをして、これを解かせたことを覚えているかもしれません:

これは萬(wàn)物が食いつくものです:
鳥(niǎo)、獣、木、花;
鉄をかじる、鋼を噛む;
硬い石を粉砕して食事にします。
王を殺し、町を廃墟にする、
そして高い山を打ち破る。

ネタバレ注意ですが、バギンズ氏は幸運(yùn)に恵まれ、偶然正しい答えを思いつきました - 「時(shí)間です!」。信じられないかもしれませんが、これはまさに私たちの謎に対する答えでもあります。時(shí)計(jì)が組み込まれている限り、2 つ (またはそれ以上) のアプリは同じ時(shí)刻にアクセスできます。後者は最近では問(wèn)題になりません。問(wèn)題のデバイスはそれに適合するのに十分な大きさです。周りを見(jiàn)回してみると、手元の時(shí)計(jì)、攜帯電話、テレビ、オーブン、壁にある時(shí)計(jì)の時(shí)間が同じである可能性が高くなります。私たちはここで何かに夢(mèng)中になっています。OTP (ワンタイム パスワード) コンピューティングの基礎(chǔ)を見(jiàn)つけたようです!

課題

時(shí)間に依存することには特有の課題があります:

  • タイムゾーン - どのタイムゾーンを使用しますか?
  • クロックは同期が崩れる傾向があり、分散システムではこれが大きな課題です

1 つずつ説明しましょう:

  • タイムゾーン: ここでの最も簡(jiǎn)単な解決策は、すべてのデバイスが同じゾーンに依存していることを確認(rèn)することであり、UTC が場(chǎng)所に依存しない適切な候補(bǔ)となる可能性があります
  • クロックの同期のずれについては、実際には、それを解決する必要さえなく、ずれが 1 ~ 2 秒以內(nèi)である限り、避けられないものとして受け入れます。30 秒の TTL を考慮すると許容できるかもしれません。デバイスのハードウェア製造者は、そのようなドリフトがいつ達(dá)成されるかを予測(cè)できる必要があるため、デバイスはそれを有効期限として使用し、銀行は単純に新しいものと交換するか、それらを接続する方法を用意します。ネットワークに接続して時(shí)計(jì)を調(diào)整します。少なくとも、それが私のここでの一連の思考です。

実裝

OK、これで解決したので、時(shí)間をベースとして使用してアルゴリズムの最初のバージョンを?qū)g裝してみましょう。 6 桁の結(jié)果に興味があるので、人間が判読できる日付ではなくタイムスタンプに依存するのが賢明な選択のように思えます。そこから始めましょう:

// gets current timestamp:
current := time.Now().Unix()
fmt.Println("Current timestamp: ", current)

Go ドキュメントによると、.Unix() は次の値を返します

1970 年 1 月 1 日 (UTC) からの経過(guò)秒數(shù)。

これは端末に出力されたものです:

Current timestamp:  1733691162

これは良いスタートですが、コードを再実行するとタイムスタンプ値が変わりますが、30 秒間は安定した狀態(tài)を保ちたいと考えています。さて、簡(jiǎn)単な話、それを 30 で割って、その値をベースとして使用しましょう:

// gets current timestamp
current := time.Now().Unix()
fmt.Println("Current timestamp: ", current)

// gets a number that is stable within 30 seconds
base := current / 30
fmt.Println("Base: ", base)

実行してみましょう:

Current timestamp:  1733691545
Base:  57789718

そしてまた:

Current timestamp:  1733691552
Base:  57789718

基本値は変わりません。少し待ってから、もう一度実行してみましょう:

Current timestamp:  1733691571
Base:  57789719

30 秒のウィンドウが経過(guò)したため、基本値が変更されました - うまくいきました!

「30 で割る」ロジックが意味をなさない場(chǎng)合は、簡(jiǎn)単な例で説明しましょう。

  • タイムスタンプが 1 を返すと想像してください
  • 厳密に型指定されたプログラミング言語(yǔ)を使用している場(chǎng)合と同様に、1 を 30 で割ると、結(jié)果は 0 になります。整數(shù)を整數(shù)で割ると別の整數(shù)が返され、浮動(dòng)小數(shù)點(diǎn)部分は関係ありません
  • これは、タイムスタンプが 0 から 29 の間である間、次の 30 秒間は 0 を取得することを意味します
  • タイムスタンプが値 30 に達(dá)すると、除算の結(jié)果は 1 になり、60 になるまで (2 になります)、以下同様です

これでもっと理解できると思います。

ただし、6 桁の結(jié)果が必要であるため、すべての要件がまだ満たされているわけではありません。現(xiàn)在のベースは 8 桁ですが、將來(lái)のある時(shí)點(diǎn)で 9 桁に達(dá)する可能性もあります。 。さて、もう 1 つの単純な數(shù)學(xué)トリックを使用しましょう?;鶖?shù)を 1 000 000 で割って余りを取得します。リマインダーは 0 から 999 999 までの任意の數(shù)値にすることができますが、それより大きくなることはありません。

// gets current timestamp:
current := time.Now().Unix()
fmt.Println("Current timestamp: ", current)

fmt.Sprintf(" d", code) 部分は、コード値が 6 桁未満の場(chǎng)合に備えて先頭にゼロを追加します。たとえば、1234 は 001234 に変換されます。
この投稿のコード全體はここにあります。

このコードを?qū)g行してみましょう:

Current timestamp:  1733691162

よし、6 桁のコードを取得できたぞ!でも、ここでは何かがおかしいと思いませんか?私がこのコードをあなたに渡し、あなたが私と同時(shí)にそれを?qū)g行すると、あなたも私と同じコードを取得することになります。これでは安全なワンタイム パスワードにはなりませんね。ここに新しい要件があります:

  • ユーザーごとに結(jié)果は異なるはずです

もちろん、ユーザー數(shù)が 100 萬(wàn)人を超える場(chǎng)合、これが 6 桁ごとに可能な最大の一意の値であるため、一部の衝突は避けられません。しかし、これらはまれであり、技術(shù)的に避けられない衝突であり、現(xiàn)在のようなアルゴリズム設(shè)計(jì)上の欠陥ではありません。

賢い數(shù)學(xué)的トリックが単獨(dú)でここで役立つとは思いません。ユーザーごとに個(gè)別の結(jié)果が必要な場(chǎng)合、それを?qū)g現(xiàn)するにはユーザー固有の狀態(tài)が必要です。エンジニアであると同時(shí)に多くのサービスのユーザーである私たちは、サービスが API へのアクセスを許可するためにユーザーごとに一意の秘密キーに依存していることを知っています。ユーザーを區(qū)別するために、このユースケースにも秘密キーを?qū)毪筏蓼筏绀Α?

秘密鍵

秘密キーを 1 000 000 から 999 999 999 までの整數(shù)として生成するための単純なロジック:

// gets current timestamp
current := time.Now().Unix()
fmt.Println("Current timestamp: ", current)

// gets a number that is stable within 30 seconds
base := current / 30
fmt.Println("Base: ", base)

秘密キー間の重複を防ぐ方法として pkDb マップを使用しており、重複が検出された場(chǎng)合は、一意の結(jié)果が得られるまで生成ロジックをもう一度実行します。

このコードを?qū)g行して秘密キーのサンプルを取得しましょう:

Current timestamp:  1733691545
Base:  57789718

コード生成ロジック內(nèi)でこの秘密キーを使用して、秘密キーごとに異なる結(jié)果が得られることを確認(rèn)してみましょう。私たちの秘密鍵は整數(shù)型であるため、私たちができる最も簡(jiǎn)単な方法は、それを基本値に追加し、殘りのアルゴリズムをそのまま維持することです。

Current timestamp:  1733691552
Base:  57789718

秘密鍵ごとに異なる結(jié)果が生成されることを確認(rèn)してみましょう:

Current timestamp:  1733691571
Base:  57789719

結(jié)果は私たちが望んでいた通りになりました:

// gets current timestamp:
current := time.Now().Unix()
fmt.Println("Current timestamp: ", current)

// gets a number that is stable within 30 seconds:
base := current / 30
fmt.Println("Base: ", base)

// makes sure it has only 6 digits:
code := base % 1_000_000

// adds leading zeros if necessary:
formattedCode := fmt.Sprintf("%06d", code)
fmt.Println("Code: ", formattedCode)

魅力的な働きをします!これは、秘密鍵が私のようなユーザーに送信される前に、コードを生成するデバイスに挿入される必要があることを意味します。銀行にとっては、それはまったく問(wèn)題ではありません。

もう終わりですか?ただし、使用した人工的なシナリオに満足している場(chǎng)合に限ります。アカウントを持っているサービス/Web サイトに対して MFA を有効にしたことがある場(chǎng)合は、Web リソースが、選択した第 2 要素アプリ (Authy、Google Authenticator、2FAS など) で QR コードをスキャンするように求めていることに気づいたかもしれません。 ) アプリにシークレット コードを入力し、その瞬間から 6 桁のコードの生成を開(kāi)始します。あるいは、コードを手動(dòng)で入力することもできます。

私がこれを取り上げたのは、業(yè)界で使用されている実際の秘密鍵の形式を覗くことが可能であることに言及するためです。これらは通常、次のような 16 ~ 32 文字の長(zhǎng)さの Base32 エンコードされた文字列です:

// gets current timestamp:
current := time.Now().Unix()
fmt.Println("Current timestamp: ", current)

ご覧のとおり、これは私たちが使用した整數(shù)秘密鍵とはまったく異なり、この形式に切り替える場(chǎng)合、アルゴリズムの現(xiàn)在の実裝は機(jī)能しません。ロジックを調(diào)整するにはどうすればよいでしょうか?

文字列としての秘密キー

簡(jiǎn)単なアプローチから始めましょう。次の行があるため、コードはコンパイルされません。

Current timestamp:  1733691162

これ以降、PK は文字列型になります。では、それを整數(shù)に変換してみませんか?もっとエレガントでパフォーマンスの高い方法はありますが、私が思いついた最も簡(jiǎn)単な方法は次のとおりです。

// gets current timestamp
current := time.Now().Unix()
fmt.Println("Current timestamp: ", current)

// gets a number that is stable within 30 seconds
base := current / 30
fmt.Println("Base: ", base)

これは String データ型の Java hashCode() 実裝から大きく影響を受けており、このシナリオには十分です。

調(diào)整されたロジックは次のとおりです:

Current timestamp:  1733691545
Base:  57789718

ターミナル出力は次のとおりです:

Current timestamp:  1733691552
Base:  57789718

なるほど、6 桁のコードがありました。うまくいきました。次の時(shí)間枠に到達(dá)するのを待って、再度実行してみましょう:

Current timestamp:  1733691571
Base:  57789719

うーん...それは機(jī)能しますが、コードは基本的に前の値の増分です。これは良くありません。この方法では OTP が予測(cè)可能であり、その値があり、それがどの時(shí)刻に屬するかを知ることは非常に困難です。秘密キーを知らなくても、同じ?jìng)帳紊嗓蚝?jiǎn)単に開(kāi)始できます。このハックの簡(jiǎn)単な疑似コードは次のとおりです:

// gets current timestamp:
current := time.Now().Unix()
fmt.Println("Current timestamp: ", current)

// gets a number that is stable within 30 seconds:
base := current / 30
fmt.Println("Base: ", base)

// makes sure it has only 6 digits:
code := base % 1_000_000

// adds leading zeros if necessary:
formattedCode := fmt.Sprintf("%06d", code)
fmt.Println("Code: ", formattedCode)

keepWithinSixDigits は、999 999 の次の値が 000 000 であることを確認(rèn)し、6 桁の制限の可能性內(nèi)に値を維持します。

ご覧のとおり、これは重大なセキュリティ上の欠陥です。なぜそれが起こるのでしょうか?基本的な計(jì)算ロジックを見(jiàn)ると、それが 2 つの要素に依存していることがわかります:

  • 現(xiàn)在のタイムスタンプを 30 で割った値
  • 秘密鍵のハッシュ

ハッシュは同じキーに対して同じ?jìng)帳蛏嗓工毪郡帷ⅳ饯蝹帳隙〝?shù)です?,F(xiàn)在の / 30 については、30 秒間は同じ?jìng)帳摔胜辘蓼工?、ウィンドウが経過(guò)すると、次の値は前の値の増分になります。すると、base % 1_000_000 は見(jiàn)たとおりに動(dòng)作します。以前の実裝 (秘密キーを整數(shù)として使用) にも同じ脆弱性がありましたが、テストが不足していたため、それに気づきませんでした。

電流 / 30 を何かに変換して、その値の変化をより目立つようにする必要があります。

分散 OTP 値

それを?qū)g現(xiàn)するには複數(shù)の方法があり、いくつかのクールな數(shù)學(xué)トリックが存在しますが、教育目的のため、使用するソリューションの読みやすさを優(yōu)先しましょう。現(xiàn)在の / 30 を別の変數(shù)ベースに抽出し、次のように組み込みます。それをハッシュ計(jì)算ロジックに組み込みます:

// gets current timestamp:
current := time.Now().Unix()
fmt.Println("Current timestamp: ", current)

このように、基數(shù)は 30 秒ごとに 1 ずつ変化しますが、hash() 関數(shù)ロジック內(nèi)で使用された後、実行される一連の乗算により diff の重みが増加します。

更新されたコード例は次のとおりです:

Current timestamp:  1733691162

実行してみましょう:

// gets current timestamp
current := time.Now().Unix()
fmt.Println("Current timestamp: ", current)

// gets a number that is stable within 30 seconds
base := current / 30
fmt.Println("Base: ", base)

ドーン!なぜここでマイナス値が出たのでしょうか?そうですね、int64 の範(fàn)囲を使い果たしたようです。そのため、値をマイナスに制限して最初からやり直しました。私の Java 仲間は、hashCode() の動(dòng)作からこれに精通しています。 修正は簡(jiǎn)単です。結(jié)果から絶対値を取得します。そうすれば、マイナス記號(hào)は無(wú)視されます:

Current timestamp:  1733691545
Base:  57789718

修正を加えたコードサンプル全體を次に示します:

Current timestamp:  1733691552
Base:  57789718

実行してみましょう:

Current timestamp:  1733691571
Base:  57789719

もう一度実行して、OTP 値が配布されていることを確認(rèn)してみましょう:

// gets current timestamp:
current := time.Now().Unix()
fmt.Println("Current timestamp: ", current)

// gets a number that is stable within 30 seconds:
base := current / 30
fmt.Println("Base: ", base)

// makes sure it has only 6 digits:
code := base % 1_000_000

// adds leading zeros if necessary:
formattedCode := fmt.Sprintf("%06d", code)
fmt.Println("Code: ", formattedCode)

なるほど、ついにまともな解決策ができました!

実際、それは私が手動(dòng)実裝プロセスをやめた瞬間でした。私は楽しみを共有し、何か新しいことを?qū)Wんだのでした。ただし、それは最善の解決策でもなければ、私が今後も続けていきたい解決策でもありません。とりわけ、これには大きな欠陥があります。ご覧のとおり、ハッシュ ロジックとタイムスタンプ値のせいで、私たちのロジックは常に大きな數(shù)値を扱います。つまり、1 または 2 で始まる結(jié)果を生成できる可能性は非常に低いことを意味します。より多くのゼロ: 完全に有効であっても、 012345 、 001234 など。そのため、可能な値が 100,000 個(gè)足りません。これは、アルゴリズムの可能な結(jié)果の數(shù)の 10% です。この方法では、衝突の可能性が高くなります。カッコ悪い!

ここからどこへ行くか

実際のアプリケーションで使用される実裝については詳しく説明しませんが、興味がある方のために、一読の価値のある 2 つの RFC を紹介します。

  • HOTP: HMAC ベースのワンタイム パスワード アルゴリズム
  • TOTP: 時(shí)間ベースのワンタイム パスワード アルゴリズム

そして、上記の RFC に基づいて意図した方法で動(dòng)作する疑似コードの実裝は次のとおりです。

Current timestamp:  1733692423
Base:  57789747
Code:  789747

ご覧のとおり、これに非常に近づいていますが、元のアルゴリズムではより高度なハッシュ (この例では HMAC-SHA1) が使用され、出力を正規(guī)化するためにいくつかのビット単位の演算が実行されます。

セキュリティに関する考慮事項(xiàng): 自分で構(gòu)築するのではなく再利用する

しかし、この話を終える前にもう 1 つ取り上げておきたいことがあります。それはセキュリティです。 OTP を生成するロジックを獨(dú)自に実裝しないことを強(qiáng)くお?jiǎng)幛幛筏蓼?。それを?qū)g行してくれるライブラリがたくさんあるからです。エラーの余地は非常に大きく、悪意のある者によって発見(jiàn)され悪用される脆弱性はすぐそこにあります。

生成ロジックを正しく作成し、テストでカバーしたとしても、他にも問(wèn)題が発生する可能性があります。たとえば、6 桁のコードを総當(dāng)たり攻撃するのにどれくらいの時(shí)間がかかると思いますか?実験してみましょう:

// gets current timestamp:
current := time.Now().Unix()
fmt.Println("Current timestamp: ", current)

このコードを?qū)g行してみましょう:

Current timestamp:  1733691162

そしてもう一度:

// gets current timestamp
current := time.Now().Unix()
fmt.Println("Current timestamp: ", current)

// gets a number that is stable within 30 seconds
base := current / 30
fmt.Println("Base: ", base)

ご覧のとおり、単純なブルートフォース for ループによるコードの推測(cè)には約 70 ミリ秒かかります。これは、OTP の壽命よりも 400 倍高速です。 OTP メカニズムを使用するアプリ/Web サイトのサーバーは、たとえば、試行が 3 回失敗した後、次の 5 秒または 10 秒間は新しいコードを受け入れないようにすることで、これを防ぐ必要があります。この方法では、攻撃者は 30 秒以內(nèi)に 18 回または 9 回の試行しか受けられませんが、これは 100 萬(wàn)個(gè)の可能な値のプールには十分ではありません。

他にもこのような見(jiàn)落としがちなものがあります。したがって、繰り返しますが、これを最初から構(gòu)築するのではなく、既存のソリューションに頼ってください。

とにかく、今日は何か新しいことを?qū)Wべたことを願(yuàn)っています。この時(shí)點(diǎn)から OTP ロジックは謎ではなくなります。また、人生のある時(shí)點(diǎn)で、再現(xiàn)可能なアルゴリズムを使用してオフライン デバイスに値を生成させる必要がある場(chǎng)合、どこから始めればよいかがわかります。

この記事を読んでいただきありがとうございます。楽しんでください! =)

追伸新しい投稿を公開(kāi)するとメールが屆きます - ここから購(gòu)読してください

追記他のクールな子供たちと同じように、私も最近 Bluesky アカウントを作成しました。フィードをもっと楽しくするために協(xié)力してください =)

以上がOTP の謎を解く: トークンのオフライン生成の背後にあるロジックの詳細(xì)內(nèi)容です。詳細(xì)については、PHP 中國(guó)語(yǔ) Web サイトの他の関連記事を參照してください。

このウェブサイトの聲明
この記事の內(nèi)容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰屬します。このサイトは、それに相當(dāng)する法的責(zé)任を負(fù)いません。盜作または侵害の疑いのあるコンテンツを見(jiàn)つけた場(chǎng)合は、admin@php.cn までご連絡(luò)ください。

ホットAIツール

Undress AI Tool

Undress AI Tool

脫衣畫像を無(wú)料で

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード寫真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

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

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無(wú)料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡(jiǎn)単に交換できます。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無(wú)料のコードエディター

SublimeText3 中國(guó)語(yǔ)版

SublimeText3 中國(guó)語(yǔ)版

中國(guó)語(yǔ)版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強(qiáng)力な PHP 統(tǒng)合開(kāi)発環(huán)境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開(kāi)発ツール

SublimeText3 Mac版

SublimeText3 Mac版

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

デフォルトでGoの靜的リンクの意味は何ですか? デフォルトでGoの靜的リンクの意味は何ですか? Jun 19, 2025 am 01:08 AM

プログラムをデフォルトでスタンドアロンのバイナリにコンパイルします。主な理由は靜的リンクです。 1.よりシンプルな展開(kāi):依存関係ライブラリの追加インストールは、Linux分布全體で直接実行できます。 2。バイナリサイズの大きい:すべての依存関係を含むと、ファイルサイズが増加しますが、構(gòu)築フラグまたは圧縮ツールを通じて最適化できます。 3.予測(cè)可能性とセキュリティの高まり:外部ライブラリバージョンの変更によってもたらされたリスクを避け、安定性を高めます。 4.制限された操作の柔軟性:共有ライブラリのホットアップデートはできません。依存関係の脆弱性を修正するには、再コンパイルと展開(kāi)が必要です。これらの機(jī)能により、CLIツール、マイクロサービス、その他のシナリオに適していますが、ストレージが制限されているか、集中管理に依存している環(huán)境でトレードオフが必要です。

Cのような手動(dòng)メモリ管理なしでメモリの安全性をどのように保証しますか? Cのような手動(dòng)メモリ管理なしでメモリの安全性をどのように保証しますか? Jun 19, 2025 am 01:11 AM

guensuresmemorysafetywithoutwithoutmanagemationgarbagecolectrection、nopointerariThmetic、safeconcurrency、andruntimechecks.first、go’sgarbagecollectorectivative -sunusedmemory、rieksanddanglingpointers.second、itdidilowsepointe

GOでバッファーチャネルを作成するにはどうすればよいですか? (例えば、make(chan int、10)) GOでバッファーチャネルを作成するにはどうすればよいですか? (例えば、make(chan int、10)) Jun 20, 2025 am 01:07 AM

GOでバッファチャネルを作成するには、Make関數(shù)の容量パラメーターを指定するだけです。バッファチャネルは、指定された容量を超えない限り、受信機(jī)がない場(chǎng)合に送信操作が一時(shí)的にデータを保存できるようにします。たとえば、ch:= make(chanint、10)は、最大10個(gè)の整數(shù)値を保存できるバッファチャネルを作成します。バッファーされていないチャネルとは異なり、データは送信時(shí)にすぐにブロックされませんが、データはレシーバーによって奪われるまで一時(shí)的にバッファーに保存されます。それを使用する場(chǎng)合、注意してください。1。メモリの無(wú)駄や頻繁なブロックを避けるために、容量設(shè)定は妥當(dāng)でなければなりません。 2。バッファは、バッファーにメモリの問(wèn)題が無(wú)期限に蓄積されないようにする必要があります。 3.信號(hào)は、リソースを保存するために、chantruct {}タイプを渡すことができます。一般的なシナリオには、並行性の數(shù)、生産者消費(fèi)者モデル、および差別化の制御が含まれます

システムプログラミングタスクにGOにどのように使用できますか? システムプログラミングタスクにGOにどのように使用できますか? Jun 19, 2025 am 01:10 AM

GOは、Cなどのコンパイルされた言語(yǔ)のパフォーマンスと、最新言語(yǔ)の使いやすさとセキュリティを組み合わせているため、システムプログラミングに最適です。 1.ファイルとディレクトリの操作に関して、GOのOSパッケージは、ファイルとディレクトリが存在するかどうかの作成、削除、名前変更、チェックをサポートします。 OS.ReadFileを使用して、バックアップスクリプトまたはログ処理ツールの書(shū)き込みに適した1行のコードでファイル全體を読み取ります。 2。プロセス管理の観點(diǎn)から、OS/EXECパッケージのexec.command関數(shù)は、外部コマンドを?qū)g行し、出力をキャプチャし、環(huán)境変數(shù)を設(shè)定し、入力と出力フローをリダイレクトし、自動(dòng)化ツールと展開(kāi)スクリプトに適したプロセスライフサイクルを制御できます。 3。ネットワークと並行性の観點(diǎn)から、ネットパッケージはTCP/UDPプログラミング、DNSクエリ、オリジナルセットをサポートします。

GOの構(gòu)造インスタンスでメソッドを呼び出すにはどうすればよいですか? GOの構(gòu)造インスタンスでメソッドを呼び出すにはどうすればよいですか? Jun 24, 2025 pm 03:17 PM

GO言語(yǔ)では、構(gòu)造メソッドを呼び出すには、最初に構(gòu)造と受信機(jī)を結(jié)合する方法を定義し、ポイント番號(hào)を使用してアクセスする必要があります。構(gòu)造の長(zhǎng)方形を定義した後、メソッドは値受信機(jī)またはポインターレシーバーを介して宣言できます。 1。func(rrectangle)領(lǐng)域()intなどの値受信機(jī)を使用し、rect.area()を介して直接呼び出します。 2.構(gòu)造を変更する必要がある場(chǎng)合は、FUNC(r*長(zhǎng)方形)setWidth(...)などのポインターレシーバーを使用し、GOはポインターと値の変換を自動(dòng)的に処理します。 3.構(gòu)造を埋め込むと、埋め込まれた構(gòu)造の方法が改善され、外側(cè)の構(gòu)造を介して直接呼び出すことができます。 4。GOは、Getter/Setterを使用する必要はありません。

GOのインターフェイスとは何ですか?また、それらを定義するにはどうすればよいですか? GOのインターフェイスとは何ですか?また、それらを定義するにはどうすればよいですか? Jun 22, 2025 pm 03:41 PM

Goでは、インターフェイスは、実裝を指定せずに動(dòng)作を定義するタイプです。インターフェイスはメソッドシグネチャで構(gòu)成され、これらのメソッドを?qū)g裝する任意のタイプは、インターフェイスを自動(dòng)的に満たします。たとえば、speak()メソッドを含むスピーカーインターフェイスを定義する場(chǎng)合、メソッドを?qū)g裝するすべてのタイプをスピーカーと見(jiàn)なすことができます。インターフェイスは、一般的な関數(shù)、抽象的な実裝の詳細(xì)、およびテストで模擬オブジェクトの使用に適しています。インターフェイスの定義は、インターフェイスキーワードを使用し、メソッドシグネチャをリストし、インターフェイスを?qū)g裝するためにタイプを明示的に宣言することはありません。一般的なユースケースには、ログ、フォーマット、さまざまなデータベースまたはサービスの抽象化、および通知システムが含まれます。たとえば、犬とロボットの両方のタイプは、話す方法を?qū)g裝し、それらを同じannoに渡すことができます

GOの文字列パッケージから文字列関數(shù)を使用するにはどうすればよいですか? (例えば、len()、strings.contains()、strings.index()、strings.replaceall()) GOの文字列パッケージから文字列関數(shù)を使用するにはどうすればよいですか? (例えば、len()、strings.contains()、strings.index()、strings.replaceall()) Jun 20, 2025 am 01:06 AM

GO言語(yǔ)では、文字列操作は主に文字列パッケージと組み込み関數(shù)を介して実裝されます。 1.Strings.Contains()は、文字列にサブストリングを含み、ブール値を返すかどうかを判斷するために使用されます。 2.Strings.index()は、サブストリングが初めて表示される場(chǎng)所を見(jiàn)つけることができ、存在しない場(chǎng)合は-1を返します。 3.Strings.ReplaceAll()は、一致するすべてのサブストリングを置き換えることができ、strings.replace()を介して交換の數(shù)も制御できます。 4.Len()関數(shù)は、文字列のバイトの長(zhǎng)さを取得するために使用されますが、Unicodeを処理する場(chǎng)合は、文字とバイトの違いに注意を払う必要があります。これらの機(jī)能は、データフィルタリング、テキスト解析、文字列処理などのシナリオでよく使用されます。

IOパッケージを使用して、GOの入力ストリームと出力ストリームを使用するにはどうすればよいですか? IOパッケージを使用して、GOの入力ストリームと出力ストリームを使用するにはどうすればよいですか? Jun 20, 2025 am 11:25 AM

thegoiopackageProvidesInterfacesLikerEaderAnderandRitoHandlei/ooperationsUniformlyAcrossources.1.io.Reader'SreadMethodenablessablesSreadingSuourCessuchasfilesorhtttttttttts

See all articles