丝袜人妻一区二区三区_少妇福利无码视频_亚洲理论片在线观看_一级毛片国产A级片

當前位置:首頁 > 話題廣場 > 財經專區(qū) > 銀行卡

0061開頭的銀行卡專題之golang 如何學習for語句

關于For語句的問題

在Golang中,循環(huán)語句只有for。在代碼中編寫循環(huán)通常需要for(當然也可以使用goto)。golang的for語句很方便,但很多初學者也對for語句有很多疑問。例如:

For語句有幾種表達式格式?

For語句的臨時變量是什么?(有時候通過賦值后,為什么所有值都等于最后一個元素?)

Range后支持哪些數(shù)據(jù)類型?

為什么范圍字符串類型是rune類型?

遍歷Slice時,如果添加或刪除數(shù)據(jù)會發(fā)生什么情況?

遍歷地圖時,如果添加或刪除數(shù)據(jù)會發(fā)生什么情況?

事實上,這里的很多疑問可以看到golang編程語言規(guī)范,感興趣的學生可以自己看,也可以根據(jù)自己的理解解答這些問題。

for語句的規(guī)范

for語句的功能用來指定重復執(zhí)行的語句塊,for語句中的表達式有三種:

官方的規(guī)范: ForStmt = "for" [ Condition | ForClause | RangeClause ] Block .

  • Condition = Expression .

  • ForClause = [ InitStmt ] “;” [ Condition ] “;” [ PostStmt ] .

  • RangeClause = [ ExpressionList “=” | IdentifierList “:=” ] “range” Expression .

單個條件判斷

形式:

for a < b { f(doThing) } // or 省略表達式,等價于truefor { // for true { f(doThing) }

這種格式,只有單個邏輯表達式, 邏輯表達式的值為true,則繼續(xù)執(zhí)行,否則停止循環(huán)。

for語句中兩個分號

形式:

for i:=0; i < 10; i++ { f(doThing) }// orfor i:=0; i < 10; { i++ f(doThing) }// or var i intfor ; i < 10; { i++ f(doThing) }

這種格式,語氣被兩個分號分割為3個表達式,第一個表示為初始化(只會在第一次條件表達式之計算一次),第二個表達式為條件判斷表達式, 第三個表達式一般為自增或自減,但這個表達式可以任何符合語法的表達式。而且這三個表達式, 只有第二個表達式是必須有的,其他表達式可以為空。

for和range結合的語句

形式:

for k,v := range []int{1,2,3} { f(doThing) }// or for k := range []int{1,2,3} { f(doThing) }// orfor range []int{1,2,3} { f(doThing) }

用range來迭代數(shù)據(jù)是最常用的一種for語句,range右邊的表達式叫范圍表達式, 范圍表達式可以是數(shù)組,數(shù)組指針,slice,字符串,map和channel。因為要賦值, 所以左側的操作數(shù)(也就是迭代變量)必須要可尋址的,或者是map下標的表達式。 如果迭代變量是一個channel,那么只允許一個迭代變量,除此之外迭代變量可以有一個或者兩個。

范圍表達式在開始循環(huán)之前只進行一次求值,只有一個例外:如果范圍表達式是數(shù)組或指向數(shù)組的指針, 至多有一個迭代變量存在,只對范圍表達式的長度進行求值;如果長度為常數(shù),范圍表達式本身將不被求值。

每迭代一次,左邊的函數(shù)調用求值。對于每個迭代,如果相應的迭代變量存在,則迭代值如下所示生成:

Range expression 1st value 2nd value array or slice a [n]E, *[n]E, or []E index i int a[i] E string s string type index i int see below runemap m map[K]V key k K m[k] V channel c chan E, <-chan E element e E
  1. 對于數(shù)組、數(shù)組指針或是分片值a來說,下標迭代值升序生成,從0開始。有一種特殊場景,只有一個迭代參數(shù)存在的情況下, range循環(huán)生成0到len(a)的迭代值,而不是索引到數(shù)組或是分片。對于一個nil分片,迭代的數(shù)量為0。

  2. 對于字符串類型,range子句迭代字符串中每一個Unicode代碼點,從下標0開始。在連續(xù)迭代中,下標值會是下一個utf-8代碼點的 第一個字節(jié)的下標,而第二個值類型是rune,會是對應的代碼點。如果迭代遇到了一個非法的Unicode序列,那么第二個值是0xFFFD, 也就是Unicode的替換字符,然后下一次迭代只會前進一個字節(jié)。

  3. map中的迭代順序是沒有指定的,也不保證兩次迭代是一樣的。如果map元素在迭代過程中被刪掉了,那么對應的迭代值不會再產生。 如果map元素在迭代中插入了,則該元素可能在迭代過程中產生,也可能被跳過,但是每個元素的迭代值頂多出現(xiàn)一次。如果map是nil,那么迭代次數(shù)為0。

  4. 對于管道,迭代值就是下一個send到管道中的值,除非管道被關閉了。如果管道是nil,范圍表達式永遠阻塞。

迭代值會賦值給相應的迭代變量,就像是賦值語句。

迭代變量可以使用短變量聲明(:=)。這種情況,它們的類型設置為相應迭代值的類型,它們的域是到for語句的結尾,它們在每一次迭代中復用。 如果迭代變量是在for語句外聲明的,那么執(zhí)行之后它們的值是最后一次迭代的值。

var testdata *struct { a *[7]int}for i, _ := range { // is never evaluated; len() is constant // i ranges from 0 to 6 f(i) }var a [10]stringfor i, s := range a { // type of i is int // type of s is string // s == a[i] g(i, s) }var key stringvar val interface {} // value type of m is assignable to valm := map[string]int{"mon":0, "tue":1, "wed":2, "thu":3, "fri":4, "sat":5, "sun":6}for key, val = range m { h(key, val) }// key == last map key encountered in iteration// val == map[key]var ch chan Work = producer()for w := range ch { doWork(w) }// empty a channelfor range ch {}

for語句的內部實現(xiàn)-array

golang的for語句,對于不同的格式會被編譯器編譯成不同的形式,如果要弄明白需要看golang的編譯器和相關數(shù)據(jù)結構的源碼, 數(shù)據(jù)結構源碼還好,但是編譯器是用C++寫的,本人C++是個弱雞,這里只講array內部實現(xiàn)。

// The loop we generate:// len_temp := len(range)// range_temp := range// for index_temp = 0; index_temp < len_temp; index_temp++ {// value_temp = range_temp[index_temp]// index = index_temp// value = value_temp// original body// }// 例如代碼: array := [2]int{1,2}for k,v := range array { f(k,v) }// 會被編譯成: len_temp := len(array) range_temp := arrayfor index_temp = 0; index_temp < len_temp; index_temp++ { value_temp = range_temp[index_temp] k = index_temp v = value_temp f(k,v)}

所以像遍歷一個數(shù)組,最后生成的代碼很像C語言中的遍歷,而且有兩個臨時變量index_temp,value_temp, 在整個遍歷中一直復用這兩個變量。所以會導致開頭問題2的問題(詳細解答會在后邊)。

問題解答

  1. for語句一共有多少種表達式格式?

    這個問題應該很簡單了,上面的規(guī)范中就有答案了,一共有3種:

    Condition = Expression .ForClause = [ InitStmt ] ";" [ Condition ] ";" [ PostStmt ] .RangeClause = [ ExpressionList "=" | IdentifierList ":=" ] "range" Expression .
  2. for語句中臨時變量是怎么回事?(為什么有時遍歷賦值后,所有的值都等于最后一個元素)

    先看這個例子:

    var a = make([]*int, 3)for k, v := range []int{1, 2, 3} { a[k] = &v }for i := range a { (*a[i]) }// result: // 3 // 3 // 3

    由for語句的內部實現(xiàn)-array可以知道,即使是短聲明的變量,在for循環(huán)中也是復用的,這里的v一直 都是同一個零時變量,所以&v得到的地址一直都是相同的,如果不信,你可以打印該地址,且該地址最后存的變量等于最后一次循環(huán)得到的變量, 所以結果都是3。

  3. range后面支持的數(shù)據(jù)類型有哪些?

    共5個,分別是數(shù)組,數(shù)組指針,slice,字符串,map和channel

  4. range string類型為何得到的是rune類型?

    這個問題在for規(guī)范中也有解答,對于字符串類型,在連續(xù)迭代中,下標值會是下一個utf-8代碼點的第一個字節(jié)的下標,而第二個值類型是rune。 如果迭代遇到了一個非法的Unicode序列,那么第二個值是0xFFFD,也就是Unicode的替換字符,然后下一次迭代只會前進一個字節(jié)。

    其實看完這句話,我沒理解,當然這句話告訴我們了遍歷string得到的第二個值類型是rune,但是為什么是rune類型,而不是string或者其他類型? 后來在看了Rob Pike寫的blogStrings, bytes, runes and characters in Go 才明白點,首先需要知道runeint32的別名,且go語言中的字符串字面量始終保存有效的UTF-8序列。而UTF-8就是用4字節(jié)來表示Unicode字符集。 所以go的設計者用rune表示單個字符的編碼,則可以完成容納所表示Unicode字符。舉個例子:

    s := `漢語ab`("len of s:", len(s))for index, runeValue := range s { ("%#U starts at byte position %d\n", runeValue, index) } // result // len of s: 8// U+6C49 '漢' starts at byte position 0// U+8BED '語' starts at byte position 3// U+0061 'a' starts at byte position 6// U+0062 'b' starts at byte position 7

    根據(jù)結果得知,s的長度是為8字節(jié),一個漢子占用了3個字節(jié),一個英文字母占用一個字節(jié),而程序go程序是怎么知道漢子占3個字節(jié),而 英文字母占用一個字節(jié),就需要知道utf-8代碼點的概念,這里就不深究了,知道go是根據(jù)utf-8代碼點來知道該字符占了多少字節(jié)就ok了。

  5. 遍歷slice的時候增加或刪除數(shù)據(jù)會怎么樣?

    由for語句的內部實現(xiàn)-array可以知道,獲取slice的長度只在循環(huán)外執(zhí)行了一次, 該長度決定了遍歷的次數(shù),不管在循環(huán)里你怎么改。但是對索引求值是在每次的迭代中求值的,如果更改了某個元素且 該元素還未遍歷到,那么最終遍歷得到的值是更改后的。刪除元素也是屬于更改元素的一種情況。

    在slice中增加元素,會更改slice含有的元素,但不會更改遍歷次數(shù)。

    a2 := []int{0, 1, 2, 3, 4}for i, v := range a2 { (i, v) if i == 0 { a2 = append(a2, 6) } }// result// 0 0// 1 1// 2 2// 3 3// 4 4

    在slice中刪除元素,能刪除該元素,但不會更改遍歷次數(shù)。

    // 只刪除該元素1,不更改slice長度a2 := []int{0, 1, 2, 3, 4}for i, v := range a2 { (i, v) if i == 0 { copy(a2[1:], a2[2:]) } }// result// 0 0// 1 2// 2 3// 3 4// 4 4// 刪除該元素1,并更改slice長度a2 := []int{0, 1, 2, 3, 4}for i, v := range a2 { (i, v) if i == 0 { copy(a2[1:], a2[2:]) a2 = a2[:len(a2)-2] //將a2的len設置為3,但并不會影響臨時slice-range_temp } }// result// 0 0// 1 2// 2 3// 3 4// 4 4
  6. 遍歷map的時候增加或刪除數(shù)據(jù)會怎么樣?

    規(guī)范中也有答案,map元素在迭代過程中被刪掉了,那么對應的迭代值不會再產生。 如果map元素在迭代中插入了,則該元素可能在迭代過程中產生,也可能被跳過。

    在遍歷中刪除元素

    m := map[int]int{1: 1, 2: 2, 3: 3, 4: 4, 5: 5} del := falsefor k, v := range m { (k, v) if !del { delete(m, 2) del = true } }// result// 4 4// 5 5// 1 1// 3 3

    在遍歷中增加元素,多執(zhí)行幾次看結果

    m := map[int]int{1: 1, 2: 2, 3: 3, 4: 4, 5: 5} add := falsefor k, v := range m { (k, v) if !add { m[6] = 6 m[7] = 7 add = true } }// result1// 1 1// 2 2// 3 3// 4 4// 5 5// 6 6// result2// 1 1// 2 2// 3 3// 4 4// 5 5// 6 6// 7 7

    在map遍歷中刪除元素,將會刪除該元素,且影響遍歷次數(shù),在遍歷中增加元素則會有不可控的現(xiàn)象出現(xiàn),有時能遍歷到新增的元素, 有時不能。具體原因下次分析。

1.《0061開頭的銀行卡專題之golang 如何學習for語句》援引自互聯(lián)網,旨在傳遞更多網絡信息知識,僅代表作者本人觀點,與本網站無關,侵刪請聯(lián)系頁腳下方聯(lián)系方式。

2.《0061開頭的銀行卡專題之golang 如何學習for語句》僅供讀者參考,本網站未對該內容進行證實,對其原創(chuàng)性、真實性、完整性、及時性不作任何保證。

3.文章轉載時請保留本站內容來源地址,http://f99ss.com/caijing/2030339.html

上一篇

105開頭是哪家銀行卡,干貨看這篇!警方打掉販賣“兩卡”跨省犯罪團伙,50余張銀行卡流水高達2000余萬元

下一篇

關于0061開頭的銀行卡我想說字符串與正則的擴展

【0061開頭的銀行卡】這一次,終于把XSS理解透徹

  • 【0061開頭的銀行卡】這一次,終于把XSS理解透徹
  • 【0061開頭的銀行卡】這一次,終于把XSS理解透徹
  • 【0061開頭的銀行卡】這一次,終于把XSS理解透徹
0061開頭的銀行卡專題之中國第一大油氣田日產原油突破7萬噸

0061開頭的銀行卡專題之中國第一大油氣田日產原油突破7萬噸

0061開頭的銀行卡相關介紹,據(jù)5月25日中國石油長慶油田數(shù)字生產指揮中心屏幕顯示,該公司原油日產量突破7萬噸,達到7.0061萬噸,今年以來原油日產創(chuàng)新高,也為中國石油第一大油氣田長慶油田公司實現(xiàn)年原油產量2545萬噸奠定了堅實...

0061開頭的銀行卡,干貨看這篇!安全測試之XSS

0061開頭的銀行卡,干貨看這篇!安全測試之XSS

0061開頭的銀行卡相關介紹,用于安全測試的站點間腳本攻擊(XSS) 前言 隨著互聯(lián)網的不斷發(fā)展,web應用程序的交互也越來越強。 但正如一個硬幣會有兩面一樣,在用戶體驗提升的同時安全風險也會跟著有所增加。今天,我們就來講一講we...

0061開頭的銀行卡看這里!安全測試之XSS

0061開頭的銀行卡看這里!安全測試之XSS

0061開頭的銀行卡相關介紹,用于安全測試的站點間腳本攻擊(XSS) 前言 隨著互聯(lián)網的不斷發(fā)展,web應用程序的交互也越來越強。 但正如一個硬幣會有兩面一樣,在用戶體驗提升的同時安全風險也會跟著有所增加。今天,我們就來講一講we...

0061開頭的銀行卡專題之安全測試之XSS

0061開頭的銀行卡專題之安全測試之XSS

0061開頭的銀行卡相關介紹,用于安全測試的站點間腳本攻擊(XSS) 前言 隨著互聯(lián)網的不斷發(fā)展,web應用程序的交互也越來越強。 但正如一個硬幣會有兩面一樣,在用戶體驗提升的同時安全風險也會跟著有所增加。今天,我們就來講一講we...