亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Go語(yǔ)言中for循環(huán)的經(jīng)典案例分析

 更新時(shí)間:2023年02月09日 14:46:26   作者:勁仔Go  
for循環(huán)問(wèn)題,在面試中經(jīng)常都會(huì)被問(wèn)到,并且在實(shí)際業(yè)務(wù)項(xiàng)目中也經(jīng)常用到for循環(huán),要是沒(méi)用好,一不下心就掉坑。本文為大家挑選了幾個(gè)經(jīng)典的案例,一塊來(lái)探討下,看看如何避免掉坑,多積累積累采坑經(jīng)驗(yàn)

前言

for循環(huán)問(wèn)題,在面試中經(jīng)常都會(huì)被問(wèn)到,并且在實(shí)際業(yè)務(wù)項(xiàng)目中也經(jīng)常用到for循環(huán),要是沒(méi)用好,一不下心就掉坑。

下面會(huì)挑選幾個(gè)經(jīng)典的案例,一塊來(lái)探討下,看看如何避免掉坑,多積累積累采坑經(jīng)驗(yàn)。

案例一:for+傳值

先來(lái)到開胃菜,熱熱身~

type student struct {
  name string
  age  int
}

func main() {
  m := make(map[string]student)
  stus := []student{
    {name: "張三", age: 18},
    {name: "李四", age: 23},
    {name: "王五", age: 26},
  }
  for _, stu := range stus {
    m[stu.name] = stu
  }
  for k, v := range m {
    fmt.Println(k, "=>", v.name)
  }
}

不出意料,輸出結(jié)果為

李四 => 李四
王五 => 王五
張三 => 張三

這題比較簡(jiǎn)單,就是簡(jiǎn)單的傳值操作,大家應(yīng)該都能答上來(lái)。下面加大難度,改為傳址操作

案例二:for+傳址

將案例一改為傳址操作

type student struct {
  name string
  age  int
}

func main() {
  m := make(map[string]*student)
  stus := []student{
    {name: "張三", age: 18},
    {name: "李四", age: 23},
    {name: "王五", age: 26},
  }
  for _, stu := range stus {
    m[stu.name] = &stu
  }
  for k, v := range m {
    fmt.Println(k, "=>", v.name)
  }
}

好好想想應(yīng)該輸出什么結(jié)果呢?還是跟案例一是一樣的結(jié)果嗎?難道會(huì)有坑?

不出意料,還是出了意外,輸出結(jié)果為

張三 => 王五
李四 => 王五
王五 => 王五

為什么呢?

  • 首先,關(guān)鍵點(diǎn)在于Go的for循環(huán),對(duì)循環(huán)變量stu每次是循環(huán)并不是迭代(簡(jiǎn)單的說(shuō),就是對(duì)循環(huán)變量stu只會(huì)做一次聲明和內(nèi)存地址的分配,后面循環(huán)就是不斷更新值);
  • 所以,取址操作 &stu,其實(shí)都是取的同一個(gè)變量的地址,只是值被循環(huán)更新為最后一個(gè)元素的值;
  • 最終,輸出的v.name,都是最后一個(gè)元素的name為王五。

解決方案

在for循環(huán)中,做同名變量覆蓋stu:=stu(即重新聲明一個(gè)局部變量,做值拷貝,避免相互影響)

type student struct {
  name string
  age  int
}

func main() {
  m := make(map[string]*student)
  stus := []student{
    {name: "張三", age: 18},
    {name: "李四", age: 23},
    {name: "王五", age: 26},
  }
  for _, stu := range stus {
    stu := stu  //同名變量覆蓋
    m[stu.name] = &stu
  }
  for k, v := range m {
    fmt.Println(k, "=>", v.name)
  }
}

輸出結(jié)果:

張三 => 張三
李四 => 李四
王五 => 王五

案例三:for+閉包

在for循環(huán)里,做閉包操作,也是很容易掉坑的??纯聪旅孑敵鍪裁矗?/p>

var prints []func()
for _, v := range []int{1, 2, 3} {
  prints = append(prints, func() { fmt.Println(v) })
}
for _, print := range prints {
  print()
}

一眼看過(guò)去,感覺(jué)是輸出1 2 3,但實(shí)際會(huì)輸出 3 3 3

為什么呢?

  • 首先,在分析了案例二后,我們知道了Go的for循環(huán)對(duì)循環(huán)變量v,其實(shí)每次是循環(huán)并不是迭代;
  • 然后,閉包=函數(shù)+引用環(huán)境,在同一個(gè)引用環(huán)境下,循環(huán)變量v的值會(huì)被不斷的覆蓋;
  • 所以最終,在打印時(shí),輸出的v,都是最后一個(gè)值3。

解決方案

和案例二解決方案一樣,是在for循環(huán)中,做同名變量覆蓋v:=v

var prints []func()
for _, v := range []int{1, 2, 3} {
  v := v //同名變量覆蓋  
  prints = append(prints, func() { fmt.Println(v) })
}
for _, print := range prints {
  print()
}

輸出結(jié)果:

1
2
3

案例四:for+goroutine

在for循環(huán)里,起goroutine協(xié)程,也是很迷惑很容易掉坑的。看看下面輸出什么?

var wg sync.WaitGroup
strs := []string{"1", "2", "3", "4", "5"}
for _, str := range strs {
  wg.Add(1)
  go func() {
    defer wg.Done()
    fmt.Println(str)
  }()
}
wg.Wait()

一眼看過(guò)去,感覺(jué)是會(huì)無(wú)序輸出1 2 3 4 5,但實(shí)際會(huì)輸出 5 5 5 5 5

為什么呢?

  • 首先,要記得Go的for循環(huán)對(duì)循環(huán)變量str,其實(shí)每次是循環(huán)并不是迭代;
  • 然后,main協(xié)程會(huì)和新起的協(xié)程做相互博弈,看誰(shuí)執(zhí)行更快,按這個(gè)案例執(zhí)行情況來(lái)看,main協(xié)程執(zhí)行速度明顯比新起的協(xié)程會(huì)更快,所以str被更新為最后一個(gè)元素值5(備注:并非絕對(duì));
  • 最終,在新起的協(xié)程中,使用str時(shí)值都為5,作為結(jié)果去輸出;
  • 拓展:如果在新起協(xié)程前,sleep個(gè)5s,輸出結(jié)果又會(huì)截然不同,感興趣的同學(xué)可以自行實(shí)驗(yàn)下,然后逐步深入地了解下GMP調(diào)度機(jī)制。

解決方案

和前面兩個(gè)案例解決方案一樣,是在for循環(huán)中,做同名變量覆蓋str:=str

var wg sync.WaitGroup
strs := []string{"1", "2", "3", "4", "5"}
for _, str := range strs {
  str := str //同名變量覆蓋
  wg.Add(1)
  go func() {
    defer wg.Done()
    fmt.Println(str)
  }()
}
wg.Wait()

輸出結(jié)果:

5
4
2
1
3

注意是1~5無(wú)序輸出

總結(jié)

for循環(huán)中做傳址、閉包、goroutine相關(guān)操作,千萬(wàn)要注意,一不小心就會(huì)很容易掉坑。

到此這篇關(guān)于Go語(yǔ)言中for循環(huán)的經(jīng)典案例分析的文章就介紹到這了,更多相關(guān)Go for循環(huán)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 詳解go語(yǔ)言單鏈表及其常用方法的實(shí)現(xiàn)

    詳解go語(yǔ)言單鏈表及其常用方法的實(shí)現(xiàn)

    這篇文章主要介紹了詳解go語(yǔ)言單鏈表及其常用方法的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • 安裝GoLang環(huán)境和開發(fā)工具的圖文教程

    安裝GoLang環(huán)境和開發(fā)工具的圖文教程

    Go是一門由Google開發(fā)的編程語(yǔ)言,GoLand的安裝非常簡(jiǎn)單,本文主要介紹了安裝GoLang環(huán)境和開發(fā)工具的圖文教程,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-09-09
  • Go素?cái)?shù)篩選分析詳解

    Go素?cái)?shù)篩選分析詳解

    學(xué)習(xí)Go語(yǔ)言的過(guò)程中,遇到素?cái)?shù)篩選的問(wèn)題。這是一個(gè)經(jīng)典的并發(fā)編程問(wèn)題,是某大佬的代碼,短短幾行代碼就實(shí)現(xiàn)了素?cái)?shù)篩選,這篇文章主要介紹了Go素?cái)?shù)篩選分析,需要的朋友可以參考下
    2022-10-10
  • 使用Go語(yǔ)言創(chuàng)建error的幾種方式小結(jié)

    使用Go語(yǔ)言創(chuàng)建error的幾種方式小結(jié)

    Go語(yǔ)言函數(shù)(或方法)是支持多個(gè)返回值的,因此在Go語(yǔ)言的編程哲學(xué)中,函數(shù)的返回值的最后一個(gè)通常都是error類型,所以本文給大家介紹了使用Go語(yǔ)言創(chuàng)建error的幾種方式小結(jié),文中通過(guò)代碼示例講解的非常詳細(xì),需要的朋友可以參考下
    2024-01-01
  • golang內(nèi)置函數(shù)len的小技巧

    golang內(nèi)置函數(shù)len的小技巧

    len是很常用的內(nèi)置函數(shù),可以測(cè)量字符串、slice、array、channel以及map的長(zhǎng)度/元素個(gè)數(shù)。本文就來(lái)介紹一下其他小技巧,感興趣的可以了解一下
    2021-07-07
  • Go框架三件套Gorm?Kitex?Hertz基本用法與常見(jiàn)API講解

    Go框架三件套Gorm?Kitex?Hertz基本用法與常見(jiàn)API講解

    這篇文章主要為大家介紹了Go框架三件套Gorm?Kitex?Hertz的基本用法與常見(jiàn)API講解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪<BR>
    2023-02-02
  • 一文讀懂go中semaphore(信號(hào)量)源碼

    一文讀懂go中semaphore(信號(hào)量)源碼

    這篇文章主要介紹了一文讀懂go中semaphore(信號(hào)量)源碼的相關(guān)知識(shí),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-04-04
  • Go type關(guān)鍵字(類型定義與類型別名的使用差異)用法實(shí)例探究

    Go type關(guān)鍵字(類型定義與類型別名的使用差異)用法實(shí)例探究

    這篇文章主要為大家介紹了Go type關(guān)鍵字(類型定義與類型別名的使用差異)用法實(shí)例探究,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2024-01-01
  • Redis?BloomFilter布隆過(guò)濾器原理與實(shí)現(xiàn)

    Redis?BloomFilter布隆過(guò)濾器原理與實(shí)現(xiàn)

    你在開發(fā)或者面試過(guò)程中,有沒(méi)有遇到過(guò)?海量數(shù)據(jù)需要查重,緩存穿透怎么避免等等這樣的問(wèn)題呢?下面這個(gè)東西超棒,好好了解下,面試過(guò)關(guān)斬將,凸顯你的不一樣
    2022-10-10
  • 執(zhí)行g(shù)o?vendor第三方包版本沖突問(wèn)題解決

    執(zhí)行g(shù)o?vendor第三方包版本沖突問(wèn)題解決

    這篇文章主要為大家介紹了執(zhí)行g(shù)o?vendor時(shí),第三方包go版本沖突問(wèn)題的解決方法,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-07-07

最新評(píng)論