<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                [TOC] ## new 和 make 是什么,差異在哪? `make`僅支持`slice`、`map`、`channel`三種數據類型的內存創建,**其返回值是所創建類型的本身,而不是新的指針引用** ~~~ func make(t Type, size ...IntegerType) Type ~~~ `new`可以對類型進行內存創建和初始化。**其返回值是所創建類型的指針引用** ~~~ func new(Type) *Type ~~~ 總結: `make`函數: * 能夠**分配并初始化**類型所需的內存空間和結構,返回引用類型的本身。 * 具有使用范圍的局限性,僅支持`channel`、`map`、`slice`三種類型。 * 具有獨特的優勢,`make`函數會對三種類型的內部數據結構(長度、容量等)賦值。 `new`函數: * 能夠**分配**類型所需的內存空間,返回指針引用(指向內存的指針)。 * 可被替代,能夠通過字面值快速初始化。 ## GMP模型 ### 基礎 G:Goroutine,實際上我們每次調用`go func`就是生成了一個 G。 P:Processor,處理器,一般 P 的數量就是處理器的核數,可以通過`GOMAXPROCS`進行修改。 M:Machine,系統線程。 這三者交互實際來源于 Go 的 M: N 調度模型。也就是 M 必須與 P 進行綁定,然后不斷地在 M 上循環尋找可運行的 G 來執行相應的任務。 ### 原理 https://mp.weixin.qq.com/s/uWP2X6iFu7BtwjIv5H55vw ### Goroutine 數量控制在多少合適,會影響 GC 和調度? 這個先說一下gmp模型,再說一下限制 * M:有限制,默認數量限制是 10000,可調整。 * G:沒限制,但受內存影響。 ~~~ 假設一個 Goroutine 創建需要 4k: 4k * 80,000 = 320,000k ≈ 0.3G內存 4k * 1,000,000 = 4,000,000k ≈ 4G內存 以此就可以相對計算出來一臺單機在通俗情況下,所能夠創建 Goroutine 的大概數量級別。 注:Goroutine 創建所需申請的 2-4k 是需要連續的內存塊。 ~~~ * P:受本機的核數影響,可大可小,不影響 G 的數量創建。 ## interface https://mp.weixin.qq.com/s/vSgV_9bfoifnh2LEX0Y7cQ ![](https://img.kancloud.cn/40/98/4098c404d5fdc389e31d814c3d1f89b7_913x841.png) ## GMP模型為什么要由P? go1.0沒有P,存在如下問題: 1、每個 M 都需要做內存緩存(M.mcache) ~~~ 會導致資源消耗過大(每個 mcache 可以吸納到 2M 的內存緩存和其他緩存),數據局部性差 ~~~ 2、存在單一的全局 mutex(Sched.Lock)和集中狀態管理 ~~~ mutex 需要保護所有與 goroutine 相關的操作(創建、完成、重排等),導致鎖競爭嚴重。 ~~~ 3、頻繁的線程阻塞/解阻塞 ~~~ 在存在 syscalls 的情況下,線程經常被阻塞和解阻塞。這增加了很多額外的性能開銷 ~~~ 有了P之后: 1、大幅度的減輕了對全局隊列的直接依賴,所帶來的效果就是鎖競爭的減少。而 GM 模型的性能開銷大頭就是鎖競爭。 2、每個 P 相對的平衡上,在 GMP 模型中也實現了 Work Stealing 算法,如果 P 的本地隊列為空,則會從全局隊列或其他 P 的本地隊列中竊取可運行的 G 來運行,減少空轉,提高了資源利用率。 ## 結構體是否能被比較 當基礎類型存在slice、map、function,是不能比較的, ~~~ 切片之間是不能比較的,我們不能使用`==`操作符來判斷兩個切片是否含有全部相等元素。 切片唯一合法的比較操作是和`nil`比較 ~~~ ## G0和M0 ### m0 m0 是 Go Runtime 所創建的第一個系統線程,一個 Go 進程只有一個 m0,也叫主線程。 從多個方面來看: * 數據結構:m0 和其他創建的 m 沒有任何區別。 * 創建過程:m0 是進程在啟動時應該匯編直接復制給 m0 的,其他后續的 m 則都是 Go Runtime 內自行創建的。 * 變量聲明:m0 和常規 m 一樣,m0 的定義就是`var m0 m`,沒什么特別之處。 ### g0 g 一般分為三種,分別是: * 執行用戶任務的叫做 g。 * 執行`runtime.main`的 main goroutine。 * 執行調度任務的叫 g0。。 g0 比較特殊,每一個 m 都只有一個 g0(僅此只有一個 g0),且每個 m 都只會綁定一個 g0。在 g0 的賦值上也是通過匯編賦值的,其余后續所創建的都是常規的 g。 從多個方面來看: * 數據結構:g0 和其他創建的 g 在數據結構上是一樣的,但是存在棧的差別。在 g0 上的棧分配的是系統棧,在 Linux 上棧大小默認固定 8MB,不能擴縮容。而常規的 g 起始只有 2KB,可擴容。 * 運行狀態:g0 和常規的 g 不一樣,沒有那么多種運行狀態,也不會被調度程序搶占,調度本身就是在 g0 上運行的。 * 變量聲明:g0 和常規 g,g0 的定義就是`var g0 g`,沒什么特別之處。 ## Go是值傳遞還是引用傳遞? 值傳遞 傳值:**指的是在調用函數時將實際參數復制一份傳遞到函數中**,這樣在函數中如果對參數進行修改,將不會影響到實際參數 傳引用:**指在調用函數時將實際參數的地址直接傳遞到函數中**,那么在函數中對參數所進行的修改,將影響到實際參數 map 和 slice 的行為類似于指針,它們是包含指向底層 map 或 slice 數據的指針的描述符 ~~~ chan:返回的指針 makechan(t *chantype,size int64) *hchan{} map:返回的指針 makemap(t *maptype,hint int,h *hmap)*hmp ~~~ ## Go是如何實現面向對象的 封裝、繼承、多態 封裝:隱藏對象的內部屬性和實現細節,僅對外提供公開接口調用 在 Go 語言中的屬性訪問權限,通過首字母大小寫來控制: * 首字母大寫,代表是公共的、可被外部訪問的。 * 首字母小寫,代表是私有的,不可以被外部訪問。 ~~~ type Animal struct { name string } func NewAnimal() *Animal { return &Animal{} } func (p *Animal) SetName(name string) { p.name = name } func (p *Animal) GetName() string { return p.name } ~~~ 繼承:指的是子類繼承父類的特征和行為,使得子類對象(實例)具有父類的實例域和方法,或子類從父類繼承方法,使得子類具有父類相同的行為。 在go語言中是通過嵌套結構體來實現的 ~~~ type Dog struct { Animal jiao string } func main() { //an := NewAnimal() //an.Name = "旺財" dog := Dog{ Animal: Animal{ Name: "旺財", }, jiao: "wangwang~", } dog.SetName("旺財1") fmt.Println(dog)//{{旺財1} wangwang~} } ~~~ 多態:指的同一個行為具有多種不同表現形式或形態的能力,具體是指一個類實例(對象)的相同方法在不同情形有不同表現形式。 ~~~ type AnimalSounder interface { MakeDNA() } func MakeSomeDNA(animalSounder AnimalSounder) { animalSounder.MakeDNA() } func (c *Cat) MakeDNA() { fmt.Println("喵~喵~喵~") } func (c *Dog) MakeDNA() { fmt.Println("汪~汪~汪~") } func main() { MakeSomeDNA(&Cat{}) MakeSomeDNA(&Dog{}) } ~~~ ## 什么是協程,協程和線程的區別和聯系? **進程**:一個具有特定功能的程序運行在一個數據集上的一次動態過程。是操作系統資源分配的最小單位。 ~~~ 進程是為了壓榨cpu的性能,但是可能執行的不是計算型的任務,可能是網絡調用,單進程直接阻塞了,cpu就空閑了,就出現了多進程; 需要線程的原因: * 進程間的信息難以共享數據,父子進程并未共享內存,需要通過進程間通信(IPC),在進程間進行信息交換,性能開銷較大。 * 創建進程(一般是調用`fork`方法)的性能開銷較大。 ~~~ **線程**:一個進程可以有多個線程,每個線程會共享父進程的資源(創建線程開銷占用比進程小很多,可創建的數量也會很多),有時被稱為輕量級進程(Lightwight Process,LWP),是操作系統調度(CPU調度)執行的最小單位。 **多線程比多進程之間更容易共享數據,在上下文切換中線程一般比進程更高效**。 #### 有多進程為什么還需要線程? ~~~ 1、創建線程比創建進程要快 10 倍甚至更多 2、線程之間能夠非常方便、快速地共享數據 ~~~ **協程**:用戶態的線程。通常創建協程時,會從進程的堆中分配一段內存作為協程的棧。 線程的棧有 8 MB,而協程棧的大小通常只有 KB,而 Go 語言的協程更夸張,只有 2-4KB,非常的輕巧。 #### 有多線程為什么需要協程 * 節省 CPU:避免系統內核級的線程頻繁切換,造成的 CPU 資源浪費。好鋼用在刀刃上。而協程是用戶態的線程,用戶可以自行控制協程的創建于銷毀,極大程度避免了系統級線程上下文切換造成的資源浪費。 * 節約內存:在 64 位的Linux中,一個線程需要分配 8MB 棧內存和 64MB 堆內存,系統內存的制約導致我們無法開啟更多線程實現高并發。而在協程編程模式下,可以輕松有十幾萬協程,這是線程無法比擬的。 * 穩定性:前面提到線程之間通過內存來共享數據,這也導致了一個問題,任何一個線程出錯時,進程中的所有線程都會跟著一起崩潰。 * 開發效率:使用協程在開發程序之中,可以很方便的將一些耗時的IO操作異步化,例如寫文件、耗時 IO 請求等。 ## 進程、線程、協程的堆棧區別是什么? * 進程:有獨立的堆棧,不共享堆也不共享棧;由操作系統調度; * 線程:有獨立的棧,共享堆而不共享棧;由操作系統調度; * 協程:有獨立的棧,共享堆而不共享棧;由程序員自己調度。 ## goroutine泄露的問題 協程泄露:指goroutine創建后,長時間得不到釋放,并且還在不斷地創建新的goroutine協程,最終導致內存耗盡,程序崩潰。 1、只發送不接收 2、只接收不發送 3、只聲明了,沒有初始化 4、只加鎖,沒有解鎖 5、`wg.Add`的數量與`wg.Done`數量并不匹配,因此在調用`wg.Wait`方法后一直阻塞等待。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看