「刷起來」Go必看的進階面試題詳解

来源:https://www.cnblogs.com/wangzhongyang/archive/2023/04/04/17287281.html
-Advertisement-
Play Games

勤學如春起之苗,不見其增日有所長;輟學如磨刀之石,不見其損日有所虧。 本文的重點:逃逸分析、延遲語句、散列表、通道、介面。 1.逃逸分析 逃逸分析是Go語言中的一項重要優化技術,可以幫助程式減少記憶體分配和垃圾回收的開銷,從而提高程式的性能。下麵是一道涉及逃逸分析的面試題及其詳解。 問題描述: 有如下 ...


勤學如春起之苗,不見其增日有所長;輟學如磨刀之石,不見其損日有所虧。

本文的重點:逃逸分析、延遲語句、散列表、通道、介面。

1.逃逸分析

逃逸分析是Go語言中的一項重要優化技術,可以幫助程式減少記憶體分配和垃圾回收的開銷,從而提高程式的性能。下麵是一道涉及逃逸分析的面試題及其詳解。

問題描述:

有如下Go代碼:

func foo() *int {
    x := 1
    return &x
}

func main() {
    p := foo()
    fmt.Println(*p)
}

請問上面的代碼中,變數x是否會發生逃逸?

答案解析:

在上面的代碼中,變數x只在函數foo()中被定義和初始化,然後其地址被返回給了主函數main()。因為返回值是指針類型,需要在堆上分配記憶體,所以變數x會發生逃逸。所謂逃逸,就是指變數的生命周期不僅限於函數棧幀,而是超出了函數的範圍,需要在堆上分配記憶體。

如果變數x沒有發生逃逸,那麼它會被分配在函數棧幀中,隨著函數的返回而被自動銷毀。而如果發生了逃逸,變數x就需要在堆上分配記憶體,並由垃圾回收器負責回收。在實際的程式中,大量的逃逸會導致記憶體分配和垃圾回收的開銷增加,從而影響程式的性能。

逃逸分析是Go語言的一項優化技術,可以在編譯期間分析代碼,確定變數的生命周期和分配位置,從而避免不必要的記憶體分配和垃圾回收。通過逃逸分析的優化,可以有效地提高程式的性能和可靠性。

更多逃逸分析的內容,可以閱讀我之前分享的文章:記憶體分配和逃逸分析詳解

2.延遲語句

defer語句是Go語言中的一項重要特性,可以用於在函數返回前執行一些清理或收尾工作,例如釋放資源、關閉連接等。下麵是一道涉及defer語句的面試題及其詳解。

問題描述:

有如下Go代碼:

func main() {
    defer func() {
        fmt.Println("defer 1")
    }()
    defer func() {
        fmt.Println("defer 2")
    }()
    fmt.Println("main")
}

請問上面的代碼中,輸出的順序是什麼?

答案解析:

在上面的代碼中,我們定義了兩個defer語句,它們分別輸出"defer 1"和"defer 2"。這兩個defer語句的執行順序是先進後出的,也就是說後定義的defer語句先執行,先定義的defer語句後執行。因此,輸出的順序應該是"main"、"defer 2"、"defer 1"。

這個例子也展示了defer語句的另一個特性,即在函數返回前執行。在main函數返回前,兩個defer語句分別執行了它們的函數體,輸出了相應的內容。這種特性可以用於釋放資源、關閉連接等操作,在函數返回前保證它們被執行。

需要註意的是,defer語句並不是一種非同步操作,它只是將被延遲執行的函數加入到一個棧中,在函數返回前按照後進先出的順序執行。因此,在defer語句中的函數應該是輕量級的,避免影響程式的性能。同時,也需要註意defer語句的執行順序和函數返回時的狀態,避免出現不符合預期的結果。

3.散列表Map

Go語言中的map是一種非常有用的數據結構,可以用於存儲鍵值對。下麵是一道涉及map的面試題及其詳解。

問題描述:

有如下Go代碼:

func main() {
    m := make(map[int]string)
    m[1] = "a"
    m[2] = "b"
    fmt.Println(m[1], m[2])
    delete(m, 2)
    fmt.Println(m[2])
}

請問上面的代碼中,輸出的結果是什麼?

答案解析:

在上面的代碼中,我們使用make函數創建了一個map,然後向其中添加了兩個鍵值對,分別是1:"a"和2:"b"。接著,我們輸出了這兩個鍵對應的值,分別是"a"和"b"。

接下來,我們使用delete函數從map中刪除了鍵為2的元素。然後,我們嘗試輸出鍵為2的值,但是輸出為空。這是因為我們已經從map中刪除了鍵為2的元素,所以它對應的值已經不存在了。

需要註意的是,當我們從map中訪問一個不存在的鍵時,它會返回該值類型的零值。在本例中,值的類型是string,它的零值是""。所以,當我們嘗試輸出鍵為2的值時,它返回的是空字元串。

需要提醒的是,map是一種引用類型的數據結構,它的底層實現是一個哈希表。在使用map時,需要註意以下幾點:

  1. map是無序的,即元素的順序不固定。
  2. map的鍵必須是可以進行相等性比較的類型,如int、string、指針等。(通俗來說就是可以用==和!=來比較的,除了slice、map、function這幾個類型都可以)
  3. map的值可以是任意類型,包括函數、結構體等。
  4. 在多個goroutine之間使用map時需要進行加鎖,避免併發訪問導致的競態問題。

4.通道Channel

Go語言中的通道(channel)是一種非常有用的特性,用於在不同的goroutine之間傳遞數據。下麵是一道涉及通道的面試題及其詳解。

問題描述:

有如下Go代碼:

func main() {
    ch := make(chan int)
    go func() {
        ch <- 1
        ch <- 2
        ch <- 3
        close(ch)
    }()
    for {
        n, ok := <-ch
        if !ok {
            break
        }
        fmt.Println(n)
    }
    fmt.Println("done")
}

請問上面的代碼中,輸出的結果是什麼?

答案解析:

在上面的代碼中,我們使用make函數創建了一個整型通道ch。然後,我們啟動了一個goroutine,向通道中寫入了三個整數1、2和3,併在最後使用close函數關閉了通道。

接著,在主函數中,我們使用for迴圈不斷從通道中讀取數據,直到通道被關閉。每次從通道中讀取到一個整數後,我們將它輸出。最後輸出"done",表示所有的數據已經讀取完畢。

因為通道是一種同步的數據傳輸方式,寫入和讀取會阻塞直到對方準備好,所以輸出的結果應該是:

需要註意的是:在通道被關閉後,讀取操作仍然可以從通道中讀取到之前寫入的數據。這是因為通道中的數據並沒有立即消失,而是在讀取完畢後被垃圾回收器回收。因此,在使用通道時,需要根據實際情況判斷何時關閉通道,以避免出現不必要的競態和記憶體泄漏。

5.介面

Go語言中的介面(interface)是一種非常重要的特性,用於定義一組方法。下麵是一道涉及介面的面試題及其詳解。

問題描述:

有如下Go代碼:

type Animal interface {
    Speak() string
}

type Dog struct{}

func (d *Dog) Speak() string {
    return "Woof!"
}

type Cat struct{}

func (c *Cat) Speak() string {
    return "Meow!"
}

func main() {
    animals := []Animal{&Dog{}, &Cat{}}
    for _, animal := range animals {
        fmt.Println(animal.Speak())
    }
}

請問上面的代碼中,輸出的結果是什麼?

答案解析:

在上面的代碼中,我們定義了一個Animal介面,它有一個Speak方法。然後,我們定義了Dog和Cat兩個結構體,分別實現了Animal介面的Speak方法。

接著,在main函數中,我們創建了一個Animal類型的切片,其中包含了一個Dog對象和一個Cat對象。然後,我們使用for迴圈遍歷這個切片,調用每個對象的Speak方法,並輸出它們返回的字元串。

因為Dog和Cat都實現了Animal介面的Speak方法,所以它們都是Animal類型的對象,可以被放入Animal類型的切片中。在遍歷切片時,我們調用每個對象的Speak方法,它們分別返回"Woof!"和"Meow!",然後被輸出。

因此,輸出的結果應該是:


需要註意的是,介面是一種動態類型,它可以包含任何實現了它所定義的方法集的類型。在使用介面時,需要註意以下幾點:

  1. 介面是一種引用類型的數據結構,它的值可以為nil。
  2. 實現介面的類型必須實現介面中所有的方法,否則會編譯錯誤。
  3. 介面的值可以賦給實現介面的類型的變數,反之亦然。
  4. 在實現介面的類型的方法中,可以通過類型斷言來判斷介面值的實際類型和值。

總結

這篇文章總結了5個知識點的面試題:逃逸分析、延遲語句defer、散列表map、通道Channel、介面interface

下一篇文章計劃分享的5個知識點是:unsafe、context、錯誤處理、計時器、反射。

歡迎大家三連支持一波,你的點贊、分享,是我更文的最大動力。

公眾號:程式員升職加薪之旅


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 簡介 裝飾器模式(Decorator Pattern)是一種結構型設計模式。將對象放入到一個特殊封裝的對象中,為這個對象綁定新的行為,具備新的能力,同時又不改變其原有結構。 如果你希望在無需修改代碼的情況下即可使用對象,且希望在運行時為對象新增額外的行為,可以使用裝飾模式。或者你用繼承來擴展對象行為 ...
  • 在我們的研發生產活動中,經常會遇到如下類似的疑惑:業務和技術在公司組織活動中,究竟應該各扮演什麼樣的角色?技術的目的是什麼? ...
  • 對於日誌管理當前網路上提供了大量的日誌工具,今天就給大家分析總結一下這些常用工具的特點,希望對你們在選型時有所幫助。 ...
  • 異常的簡單分類 檢查性異常:最具代表性的檢查性異常是用戶錯誤或問題引起的異常,這是程式員無法預見的。例如用戶要打開一個不存在的文件,一個異常就發生了,這些異常在編譯時不能被簡單的忽略。 運行時異常:運行時異常是可能被程式員避免的異常,與檢查性異常相反,運行時異常可以在編譯時被忽略。 錯誤(error ...
  • 藍橋杯(全球變暖dfs) import java.util.Scanner; /** * 該題使用了深度優先演算法dfs用於把相連的#號當成一塊大陸,並通過數組記錄下有幾塊大陸 * dfs演算法並不難,只要對用dfs處理過後留下的aes數組和sea數組進行處理得到結果即可 * 我的思路就是 * 1、se ...
  • 搭建微服務基礎環境02 3.創建使用會員微服務模塊-service consumer 3.1需求分析 瀏覽器向service consumer請求某個數據,service consumer會去向service provider請求數據,然後將service provider返回的數據返回給瀏覽器。 ...
  • 之前學習時候,是使用老師的自定義的一個SpringMVC模式,今天突然好奇,官方的SpringMVC架構咋弄,於是帶著好奇的心去實現完成它 其實這個模式也比較簡單 1:首先,我們創建一個maven,web的網頁項目,JDK選擇1.8版本 2:在創建完之後,滑鼠右鍵點擊main目錄,同時選擇java和 ...
  • 1. 踩坑經歷 最近做了個需求,需要往公司微信公眾號推送一個模板消息,並且點擊該消息需要跳轉到公司小程式的某個頁面。 1.1 拿到模板id 既然是發送模板消息,第一步就需要登錄微信公眾號後臺新建模板消息,拿到模板id。 登錄地址:https://mp.weixin.qq.com 新建模板消息的方法如 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...