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

首頁 后端開發(fā) Golang 揭秘 OTP:離線生成代幣背后的邏輯

揭秘 OTP:離線生成代幣背后的邏輯

Dec 12, 2024 pm 10:23 PM

你好!另一個晚上,在回家的路上,我決定檢查一下郵箱。我指的不是我的電子郵件收件箱,而是郵遞員放置實(shí)際信件的老式實(shí)際盒子。令我驚訝的是,我在那里發(fā)現(xiàn)了一個信封,里面裝著一些東西!當(dāng)我打開它時,我花了一些時間希望這是來自霍格沃茨的遲來了幾十年的信。但當(dāng)我注意到這是一封來自銀行的無聊的“成人”信時,我不得不回到現(xiàn)實(shí)。我瀏覽了一下文字,意識到我的“酷孩子純數(shù)字”銀行已被當(dāng)?shù)厥袌錾献畲蟮耐婕沂召?。作為新開始的象征,他們在信封上添加了以下內(nèi)容:

Demystifying OTPs: the logic behind the offline generation of tokens

以及如何使用它的說明。

如果你像我一樣,從來沒有遇到過這樣的技術(shù)創(chuàng)新,讓我分享一下我從信中學(xué)到的東西:新所有者決定執(zhí)行他們公司的安全策略,這意味著所有用戶從現(xiàn)在開始,帳戶將啟用 MFA(順便說一句,這是值得稱贊的)。您在上面看到的設(shè)備會生成 6 位數(shù)字長的一次性令牌,在登錄您的銀行帳戶時用作第二因素。基本上,與 Authy、Google Authenticator 或 2FAS 等應(yīng)用程序的工作方式相同,但采用物理形狀。

所以,我嘗試了一下,登錄過程很順利:設(shè)備向我顯示了一個 6 位代碼,我在我的銀行應(yīng)用程序中輸入了它,這讓我進(jìn)入了。萬歲!但后來我突然意識到:這東西是如何工作的?它無法以某種方式連接到互聯(lián)網(wǎng),但它設(shè)法生成我的銀行服務(wù)器接受的正確代碼。嗯...里面有SIM卡或者類似的東西嗎?沒辦法!

意識到我的生活將永遠(yuǎn)不一樣,我開始想知道我上面提到的應(yīng)用程序(Authy 和朋友)?我內(nèi)心的研究員被喚醒了,所以我將手機(jī)切換到飛行模式,令我大吃一驚的是,我意識到它們在離線狀態(tài)下工作得非常好:它們不斷生成被應(yīng)用程序服務(wù)器接受的代碼。有趣!

不確定你的看法,但我一直認(rèn)為一次性代幣流是理所當(dāng)然的,并且從未真正認(rèn)真考慮過它(特別是因?yàn)楝F(xiàn)在我的手機(jī)很少沒有互聯(lián)網(wǎng),除非我正在做一些戶外探險),所以這是我驚訝的根本原因。否則,從安全的角度來看,以這種方式工作是完全有意義的,因?yàn)樯蛇^程純粹是本地的,因此對于外部參與者來說是安全的。但它是如何運(yùn)作的呢?

嗯,像 Google 或 ChatGPT 這樣的現(xiàn)代技術(shù)可以讓您輕松找到答案。但這個技術(shù)問題對我來說似乎很有趣,所以決定先嘗試一下并自己解決。

要求

讓我們從我們擁有的開始:

  • 可生成 6 位代碼的離線設(shè)備
  • 服務(wù)器接受這些代碼,驗(yàn)證它們,如果正確則發(fā)出綠色信號

服務(wù)器驗(yàn)證部分提示服務(wù)器必須能夠生成與離線設(shè)備相同的代碼來比較它們。嗯..這會很有幫助。

對我的新“玩具”的進(jìn)一步觀察帶來了更多發(fā)現(xiàn):

  • 如果我將其關(guān)閉然后再關(guān)閉,通常我可以看到與之前相同的代碼
  • 然而,偶爾,它會改變

我能想到的唯一邏輯解釋是這些代碼有一定的生命周期。我想講述一個我試圖以“1-2-3-...-N”方式計算它的持續(xù)時間的故事,但這不會是真的:我從像這樣的應(yīng)用程序中得到了一個很大的提示Authy and Co,我在那里看到了 30 秒的 TTL。很好的發(fā)現(xiàn),讓我們將其添加到已知事實(shí)列表中。

讓我們總結(jié)一下到目前為止我們的要求:

  • 以 6 位數(shù)字格式生成可預(yù)測(而不是隨機(jī))的代碼
  • 生成邏輯應(yīng)該是可重現(xiàn)的,這樣無論平臺如何,都可以得到相同的結(jié)果
  • 代碼生命周期為 30 秒,這意味著在這段時間內(nèi)生成算法會產(chǎn)生相同的值

大問題

好吧,但主要問題仍然沒有得到解答:離線應(yīng)用程序如何生成與其他應(yīng)用程序中的值相匹配的值?他們有什么共同點(diǎn)?

如果您喜歡《指環(huán)王》宇宙,您可能還記得比爾博如何與咕嚕玩謎語游戲,并解決了這個問題:

這個萬物吞噬之物:
鳥、獸、樹、花;
啃鐵咬鋼;
將堅(jiān)硬的石頭磨成粉;
殺死國王,摧毀城鎮(zhèn),
并擊敗高山。

劇透警告,但巴金斯先生很幸運(yùn),意外地得出了正確答案 - “時間!”。不管你相信與否,這也正是我們謎題的答案:任何 2 個(或更多)應(yīng)用程序都可以訪問同一時間,只要它們內(nèi)部有嵌入式時鐘。如今,后者已不再是問題,而且所討論的設(shè)備足夠大,可以容納它。環(huán)顧四周,你的手表、手機(jī)、電視、烤箱和墻上的時鐘上的時間很可能是相同的。我們在這里很感興趣,似乎我們已經(jīng)找到了 OTP(一次性密碼)計算的基礎(chǔ)!

挑戰(zhàn)

依賴時間有其自身的一系列挑戰(zhàn):

  • 時區(qū) - 使用哪一個?
  • 時鐘往往會不同步,這對分布式系統(tǒng)來說是一個巨大的挑戰(zhàn)

讓我們一一解決:

  • 時區(qū):這里最簡單的解決方案是確保所有設(shè)備都依賴于同一區(qū)域,并且 UTC 可以是一個很好的與位置無關(guān)的候選
  • 至于時鐘不同步:實(shí)際上,我們甚至可能不需要解決它,而是接受不可避免的事情,只要漂移在一兩秒之內(nèi),考慮到 30 秒的 TTL,這可能是可以容忍的。設(shè)備的硬件生產(chǎn)商應(yīng)該能夠預(yù)測何時會實(shí)現(xiàn)這種漂移,因此設(shè)備將使用它作為其到期日期,而銀行將簡單地用新的替換它們,或者將有辦法連接它們到網(wǎng)絡(luò)來校準(zhǔn)時鐘。至少,這是我的想法。

執(zhí)行

好的,這件事已經(jīng)解決了,所以讓我們嘗試以時間為基礎(chǔ)來實(shí)現(xiàn)我們算法的第一個版本。由于我們對 6 位數(shù)字結(jié)果感興趣,因此依賴時間戳而不是人類可讀的日期聽起來是一個明智的選擇。讓我們從這里開始:

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

根據(jù) Go 文檔,.Unix() 返回

自 UTC 1970 年 1 月 1 日以來經(jīng)過的秒數(shù)。

這是終端打印的內(nèi)容:

Current timestamp:  1733691162

這是一個好的開始,但是如果我們重新運(yùn)行該代碼,時間戳值將會改變,而我們希望保持它穩(wěn)定 30 秒。好吧,小菜一碟,我們將其除以 30 并使用該值作為基數(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)

讓我們運(yùn)行它:

Current timestamp:  1733691545
Base:  57789718

再說一遍:

Current timestamp:  1733691552
Base:  57789718

基礎(chǔ)值保持不變。讓我們稍等一下,然后再次運(yùn)行:

Current timestamp:  1733691571
Base:  57789719

隨著 30 秒窗口的過去,基礎(chǔ)值已更改 - 干得好!

如果“除以30”的邏輯沒有意義,讓我用一個簡單的例子來解釋一下:

  • 想象一下我們的時間戳返回 1
  • 如果我們將 1 除以 30,結(jié)果將為 0,就像當(dāng)我們使用嚴(yán)格類型編程語言時,整數(shù)除以整數(shù)會返回另一個整數(shù),該整數(shù)與浮點(diǎn)部分無關(guān)
  • 這意味著在接下來的 30 秒內(nèi),當(dāng)時間戳介于 0 到 29 之間時,我們將得到 0
  • 一旦時間戳達(dá)到30,除法的結(jié)果就是1,直到60(變成2),依此類推

我希望它現(xiàn)在更有意義。

但是,還沒有滿足所有要求,因?yàn)槲覀冃枰?6 位數(shù)字的結(jié)果,而當(dāng)前基數(shù)截至今天是 8 位數(shù)字,但在未來的某個時間點(diǎn)可能會達(dá)到 9 位數(shù)字點(diǎn),依此類推。好吧,讓我們使用另一個簡單的數(shù)學(xué)技巧:將基數(shù)除以 1 000 000,并得到余數(shù),余數(shù)始終為 6 位數(shù)字,因?yàn)樘嵝芽梢允?0 到 999 999 之間的任何數(shù)字,但不能更大:

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

fmt.Sprintf(" d", code) 部分會附加前導(dǎo)零,以防我們的代碼值少于 6 位。例如,1234 將轉(zhuǎn)換為 001234。
這篇文章的完整代碼可以在這里找到。

讓我們運(yùn)行此代碼:

Current timestamp:  1733691162

好的,我們得到了 6 位代碼,萬歲!但這里感覺有些不對勁,不是嗎?如果我給您這個代碼,并且您將與我同時運(yùn)行它,您將獲得與我相同的代碼。這并不意味著它是一個安全的一次性密碼,對吧?新的要求來了:

  • 不同用戶的結(jié)果應(yīng)該不同

當(dāng)然,如果我們的用戶超過 100 萬,一些沖突是不可避免的,因?yàn)檫@是每 6 位數(shù)字的最大可能唯一值。但這些都是罕見的,技術(shù)上不可避免的碰撞,而不是像我們現(xiàn)在這樣的算法設(shè)計缺陷。

我認(rèn)為任何聰明的數(shù)學(xué)技巧本身都不會幫助我們:如果我們需要每個用戶單獨(dú)的結(jié)果,我們需要一個特定于用戶的狀態(tài)來實(shí)現(xiàn)它。作為工程師,同時也是許多服務(wù)的用戶,我們知道要授予對其 API 的訪問權(quán)限,服務(wù)依賴于私鑰,而私鑰對于每個用戶來說都是唯一的。讓我們?yōu)槲覀兊挠美胍粋€私鑰,以區(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 映射作為防止私鑰之間重復(fù)的方法,如果檢測到重復(fù),我們將再次運(yùn)行生成邏輯,直到獲得唯一的結(jié)果。

讓我們運(yùn)行此代碼來獲取私鑰示例:

Current timestamp:  1733691545
Base:  57789718

讓我們在代碼生成邏輯中使用此私鑰,以確保每個私鑰得到不同的結(jié)果。由于我們的私鑰是整數(shù)類型,所以我們能做的最簡單的事情就是將其添加到基值上,并保持其余算法不變:

Current timestamp:  1733691552
Base:  57789718

讓我們確保它對于不同的私鑰產(chǎn)生不同的結(jié)果:

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)

魅力十足!這意味著私鑰應(yīng)該先注入生成代碼的設(shè)備中,然后再發(fā)送給像我這樣的用戶:這對銀行來說根本不應(yīng)該是問題。

我們現(xiàn)在完成了嗎?好吧,前提是我們對我們使用的人工場景感到滿意。如果您曾經(jīng)為您擁有帳戶的任何服務(wù)/網(wǎng)站啟用過 MFA,您可能會注意到網(wǎng)絡(luò)資源要求您使用您選擇的第二因素應(yīng)用程序(Authy、Google Authenticator、2FAS 等)掃描 QR 碼。 ),它將把密碼輸入到您的應(yīng)用程序中,并從那時起開始生成 6 位數(shù)字的代碼?;蛘?,也可以手動輸入代碼。

我提出這個是為了一睹業(yè)界使用的真實(shí)私鑰的格式。它們通常是 16-32 個字符長的 Base32 編碼字符串,如下所示:

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

如您所見,這與我們使用的整數(shù)私鑰有很大不同,如果我們要切換到這種格式,我們算法的當(dāng)前實(shí)現(xiàn)將無法工作。我們?nèi)绾握{(diào)整我們的邏輯?

私鑰作為字符串

讓我們從一個簡單的方法開始:我們的代碼將無法編譯,因?yàn)檫@一行:

Current timestamp:  1733691162

因?yàn)?pk 從現(xiàn)在開始是字符串類型。那么我們?yōu)槭裁床话阉D(zhuǎn)換成整數(shù)呢?雖然有更優(yōu)雅和更高效的方法可以做到這一點(diǎ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 數(shù)據(jù)類型的 Java hashCode() 實(shí)現(xiàn)的啟發(fā),這使得它足以滿足我們的場景。

調(diào)整后的邏輯如下:

Current timestamp:  1733691545
Base:  57789718

這是終端輸出:

Current timestamp:  1733691552
Base:  57789718

很好,有 6 位代碼,干得好。讓我們等待到達(dá)下一個時間窗口并再次運(yùn)行它:

Current timestamp:  1733691571
Base:  57789719

嗯...它可以工作,但是代碼基本上是前一個值的增量,這不好,因?yàn)檫@樣 OTP 是可預(yù)測的,并且擁有它的值并知道它屬于什么時間,這是非常好的無需知道私鑰即可開始生成相同的值。這是此黑客攻擊的簡單偽代碼:

// 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 等等,以將該值保持在 6 位數(shù)字的限制范圍內(nèi)。

如您所見,這是一個嚴(yán)重的安全漏洞。為什么會發(fā)生這種情況?如果我們看一下基本計算邏輯,我們會發(fā)現(xiàn)它依賴于兩個因素:

  • 當(dāng)前時間戳除以 30
  • 私鑰的哈希值

哈希對于相同的鍵產(chǎn)生相同的值,因此它的值是恒定的。至于當(dāng)前的 / 30 ,它在 30 秒內(nèi)具有相同的值,但是一旦窗口過去,下一個值將是前一個值的增量。然后 base % 1_000_000 的行為就像我們看到的那樣。我們之前的實(shí)現(xiàn)(使用私鑰作為整數(shù))也有同樣的漏洞,但我們沒有注意到這一點(diǎn) - 缺乏測試。

我們需要將 current / 30 轉(zhuǎn)換成某種東西,使其值的變化更加明顯。

分布式 OTP 值

有多種方法可以實(shí)現(xiàn)這一點(diǎn),并且存在一些很酷的數(shù)學(xué)技巧,但出于教育目的,讓我們優(yōu)先考慮我們將采用的解決方案的可讀性:讓我們將 current / 30 提取到一個單獨(dú)的變量基數(shù)中并包含進(jìn)入哈希計算邏輯:

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

這樣,即使底數(shù)每 30 秒變化 1,但在 hash() 函數(shù)邏輯中使用后,diff 的權(quán)重會因?yàn)橐幌盗谐朔ǖ膱?zhí)行而增加。

這是更新后的代碼示例:

Current timestamp:  1733691162

讓我們運(yù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)

繁榮!我們怎么會在這里得到負(fù)值呢?好吧,看起來我們已經(jīng)超出了 int64 范圍,因此它將值限制為負(fù)數(shù)并重新開始 - 我的 Java 同事通過 hashCode() 行為對此很熟悉。 解決方法很簡單:讓我們從結(jié)果中取絕對值,這樣減號就被忽略:

Current timestamp:  1733691545
Base:  57789718

這是修復(fù)后的完整代碼示例:

Current timestamp:  1733691552
Base:  57789718

讓我們運(yùn)行它:

Current timestamp:  1733691571
Base:  57789719

讓我們再次運(yùn)行它以確保 OTP 值現(xiàn)在已分發(fā):

// 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)

很好,終于有了一個不錯的解決方案!

實(shí)際上,那是我停止手動實(shí)施過程的那一刻,因?yàn)槲蚁硎艿搅藰啡げW(xué)到了新東西。然而,這既不是最好的解決方案,也不是我愿意接受的解決方案。除此之外,它還有一個很大的缺陷:如您所見,由于哈希邏輯和時間戳值,我們的邏輯總是處理大數(shù)字,這意味著我們不太可能生成以 1 或 1 開頭的結(jié)果。更多零:例如 012345 、 001234 等,即使它們完全有效。因此,我們還缺少 100 000 個可能的值,這比算法的可能結(jié)果數(shù)量少了 10% - 這樣碰撞的可能性會更高。不酷!

從這里到哪里去

我不會深入探討實(shí)際應(yīng)用程序中使用的實(shí)現(xiàn),但對于那些好奇的人,我將分享兩個值得一看的 RFC:

  • HOTP:一種基于 HMAC 的一次性密碼算法
  • TOTP:基于時間的一次性密碼算法

這是偽代碼實(shí)現(xiàn),它將根據(jù)上述 RFC 以預(yù)期方式工作:

Current timestamp:  1733692423
Base:  57789747
Code:  789747

如您所見,我們已經(jīng)非常接近了,但原始算法使用更高級的哈希(本例中為 HMAC-SHA1),并執(zhí)行一些按位運(yùn)算來標(biāo)準(zhǔn)化輸出。

安全考慮:重用而不是自己構(gòu)建

但是,在我們結(jié)束之前我還想講一件事:安全性。我強(qiáng)烈建議您不要自行實(shí)現(xiàn)生成 OTP 的邏輯,因?yàn)橛泻芏鄮煲呀?jīng)為我們完成了這一工作。犯錯的空間是巨大的,而且離不良行為者發(fā)現(xiàn)和利用的漏洞只有很短的距離。

即使您的生成邏輯正確并通過測試覆蓋它,也可能會出現(xiàn)其他問題。例如,您認(rèn)為暴力破解 6 位代碼需要花費(fèi)多少時間?讓我們來實(shí)驗(yàn)一下:

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

讓我們運(yùn)行此代碼:

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 循環(huán)猜測代碼大約需要 70 毫秒。這比 OTP 的壽命快 400 倍!使用 OTP 機(jī)制的應(yīng)用程序/網(wǎng)站的服務(wù)器需要通過例如在 3 次失敗嘗試后的接下來 5 或 10 秒內(nèi)不接受新代碼來防止這種情況。這樣,攻擊者在 30 秒的窗口內(nèi)只能相應(yīng)地獲得 18 或 9 次嘗試,這對于 100 萬個可能值的池來說是不夠的。

還有其他類似的事情很容易被忽視。所以,讓我再說一遍:不要從頭開始構(gòu)建它,而是依賴現(xiàn)有的解決方案。

無論如何,我希望你今天學(xué)到了一些新東西,從現(xiàn)在開始 OTP 邏輯對你來說不再是一個謎。此外,如果在生活中的某個時刻,您需要使用可重現(xiàn)的算法讓離線設(shè)備生成一些值,那么您很清楚從哪里開始。

感謝您花時間閱讀這篇文章,祝您玩得開心! =)

P.S.我發(fā)布新帖子后會收到一封電子郵件 - 在此訂閱

P.P.S.和其他酷孩子一樣,我最近創(chuàng)建了一個 Bluesky 帳戶,所以請幫助我讓我的 Feed 變得更有趣 =)

以上是揭秘 OTP:離線生成代幣背后的邏輯的詳細(xì)內(nèi)容。更多信息請關(guān)注PHP中文網(wǎng)其他相關(guān)文章!

本站聲明
本文內(nèi)容由網(wǎng)友自發(fā)貢獻(xiàn),版權(quán)歸原作者所有,本站不承擔(dān)相應(yīng)法律責(zé)任。如您發(fā)現(xiàn)有涉嫌抄襲侵權(quán)的內(nèi)容,請聯(lián)系admin@php.cn

熱AI工具

Undress AI Tool

Undress AI Tool

免費(fèi)脫衣服圖片

Undresser.AI Undress

Undresser.AI Undress

人工智能驅(qū)動的應(yīng)用程序,用于創(chuàng)建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用于從照片中去除衣服的在線人工智能工具。

Clothoff.io

Clothoff.io

AI脫衣機(jī)

Video Face Swap

Video Face Swap

使用我們完全免費(fèi)的人工智能換臉工具輕松在任何視頻中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費(fèi)的代碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

功能強(qiáng)大的PHP集成開發(fā)環(huán)境

Dreamweaver CS6

Dreamweaver CS6

視覺化網(wǎng)頁開發(fā)工具

SublimeText3 Mac版

SublimeText3 Mac版

神級代碼編輯軟件(SublimeText3)

如何在GO中的結(jié)構(gòu)實(shí)例上調(diào)用方法? 如何在GO中的結(jié)構(gòu)實(shí)例上調(diào)用方法? Jun 24, 2025 pm 03:17 PM

在Go語言中,調(diào)用結(jié)構(gòu)體方法需先定義結(jié)構(gòu)體和綁定接收者的方法,使用點(diǎn)號訪問。定義結(jié)構(gòu)體Rectangle后,可通過值接收者或指針接收者聲明方法;1.使用值接收者如func(rRectangle)Area()int,通過rect.Area()直接調(diào)用;2.若需修改結(jié)構(gòu)體,應(yīng)使用指針接收者如func(r*Rectangle)SetWidth(...),Go會自動處理指針與值的轉(zhuǎn)換;3.嵌入結(jié)構(gòu)體時,內(nèi)嵌結(jié)構(gòu)體的方法會被提升,可直接通過外層結(jié)構(gòu)體調(diào)用;4.Go無需強(qiáng)制使用getter/setter,字

GO中的接口是什么?如何定義它們? GO中的接口是什么?如何定義它們? Jun 22, 2025 pm 03:41 PM

在Go語言中,接口是一種定義行為而不指定實(shí)現(xiàn)方式的類型。接口由方法簽名組成,任何實(shí)現(xiàn)這些方法的類型都自動滿足該接口。例如,定義一個Speaker接口包含Speak()方法,則所有實(shí)現(xiàn)該方法的類型均可視為Speaker。接口適用于編寫通用函數(shù)、抽象實(shí)現(xiàn)細(xì)節(jié)和測試中使用mock對象。定義接口使用interface關(guān)鍵字并列出方法簽名,無需顯式聲明類型實(shí)現(xiàn)了接口。常見用例包括日志、格式化、不同數(shù)據(jù)庫或服務(wù)的抽象,以及通知系統(tǒng)等。例如,Dog和Robot類型均可實(shí)現(xiàn)Speak方法,并傳遞給同一個Anno

將Golang服務(wù)與現(xiàn)有Python基礎(chǔ)架構(gòu)集成的策略 將Golang服務(wù)與現(xiàn)有Python基礎(chǔ)架構(gòu)集成的策略 Jul 02, 2025 pm 04:39 PM

TOIntegrategolangServicesWithExistingPypythoninFrasture,userestapisorgrpcForinter-serviceCommunication,允許GoandGoandPyThonAppStoStoInteractSeamlessSeamLlyThroughlyThroughStandArdArdAdrotized Protoccols.1.usererestapis(ViaFrameWorkslikeSlikeSlikeGiningOandFlaskInpyThon)Orgrococo(wirs Propococo)

我如何使用時間軟件包來處理GO的時間和持續(xù)時間? 我如何使用時間軟件包來處理GO的時間和持續(xù)時間? Jun 23, 2025 pm 11:21 PM

Go的time包提供了處理時間和持續(xù)時間的功能,包括獲取當(dāng)前時間、格式化日期、計算時間差、處理時區(qū)、調(diào)度和休眠等操作。要獲取當(dāng)前時間,使用time.Now()獲取Time結(jié)構(gòu)體,并可通過Year()、Month()、Day()等方法提取具體時間信息;通過Format("2006-01-0215:04:05")可將時間格式化為字符串;計算時間差時,用Sub()或Since()獲取Duration對象,再通過Seconds()、Minutes()、Hours()轉(zhuǎn)換為對應(yīng)單位;添

我如何根據(jù)語句使用語句執(zhí)行代碼? 我如何根據(jù)語句使用語句執(zhí)行代碼? Jun 23, 2025 pm 07:02 PM

Ingo,ifstatementSexecuteCodeBasedonConconditions.1.BasicsStructurerunsablockifaconditionistrue,例如IFX> 10 {...}。2.Elseclausehan dlesfalseconditions,例如,else {...}。3。elseifchainsmultipleconditions,例如,elseifx == 10 {...}。4.variableInitializationInsideIndifif,l

了解Web API的Golang和Python之間的性能差異 了解Web API的Golang和Python之間的性能差異 Jul 03, 2025 am 02:40 AM

Golangofferssuperiorperformance,nativeconcurrencyviagoroutines,andefficientresourceusage,makingitidealforhigh-traffic,low-latencyAPIs;2.Python,whileslowerduetointerpretationandtheGIL,provideseasierdevelopment,arichecosystem,andisbettersuitedforI/O-bo

去支持并發(fā)如何? 去支持并發(fā)如何? Jun 23, 2025 pm 12:37 PM

Gohandlesconcurrencyusinggoroutinesandchannels.1.GoroutinesarelightweightfunctionsmanagedbytheGoruntime,enablingthousandstorunco??ncurrentlywithminimalresourceuse.2.Channelsprovidesafecommunicationbetweengoroutines,allowingvaluestobesentandreceivedinas

如何使用lock()和unlock()方法來保護(hù)GO中的重要代碼部分? 如何使用lock()和unlock()方法來保護(hù)GO中的重要代碼部分? Jun 23, 2025 pm 08:37 PM

在Go中保護(hù)臨界區(qū)的標(biāo)準(zhǔn)方法是使用sync.Mutex的Lock()和Unlock()方法。1.聲明一個mutex并將其與要保護(hù)的數(shù)據(jù)一起使用;2.在進(jìn)入臨界區(qū)前調(diào)用Lock(),確保只有一個goroutine能訪問共享資源;3.使用deferUnlock()確保鎖始終被釋放,避免死鎖;4.盡量縮短臨界區(qū)內(nèi)的操作以提高性能;5.對于讀多寫少的場景,應(yīng)使用sync.RWMutex,通過RLock()/RUnlock()進(jìn)行讀操作,通過Lock()/Unlock()進(jìn)行寫操作,從而提升并發(fā)效率。

See all articles