Go運算子、控制語句-DateWhale開源學習

crl7-key發表於2020-12-16

目錄

運算子

Go 語言內建的運算子有:

  • 算術運算子
  • 關係運算子
  • 邏輯運算子
  • 位運算子
  • 賦值運算子

假定A值為10B值為20

算數運算子

運算子描述例項
+相加A + B 輸出結果 30
-相減A - B輸出結果 -10
*相乘A * B 輸出結果 200
/相除B / A 輸出結果 2
%求餘B % A 輸出結果0
++自增A++輸出結果 11
--自減A-- 輸出結果 9

注意: ++(自增)和--(自減)在Go語言中是單獨的語句,並不是運算子。

關係運算子

運算子描述
==檢查兩個值是否相等,如果相等返回True否則返回False
!=檢查兩個值是否不相等,如果不相等返回True否則返回False
>檢查左邊值是否大於右邊值,如果是返回True否則返回False
<檢查左邊值是否小於右邊值,如果是返回True否則返回False
>=檢查左邊值是否大於等於右邊值,如果是返回True 否則返回 False
<=檢查左邊值是否小於等於右邊值,如果是返回 True 否則返回 False

邏輯運算子

運算子描述
&&邏輯 AND 運算子。 如果兩邊的運算元都是 True,則條件 True,否則為 False
| |邏輯OR運算子。 如果兩邊的運算元有一個 True,則條件 True,否則為 False
!邏輯 NOT運算子。 如果條件為 True,則邏輯 NOT條件 False,否則為 True

位運算子

運算子描述
&按位與運算子"&"是雙目運算子。 其功能是參與運算的兩數各對應的二進位相與。
|按位異或運算子"^"是雙目運算子。 其功能是參與運算的兩數各對應的二進位相異或,當兩對應的二進位相異時,結果為1
^按位異或運算子"^"是雙目運算子。 其功能是參與運算的兩數各對應的二進位相異或,當兩對應的二進位相異時,結果為1
>>右移運算子">>“是雙目運算子。右移n位就是除以2n次方。 其功能是把”>>“左邊的運算數的各二進位全部右移若干位,”>>"右邊的數指定移動的位數。
<<左移運算子"<<“是雙目運算子。左移n位就是乘以2n次方。 其功能把”<<“左邊的運算數的各二進位全部左移若干位,由”<<"右邊的數指定移動的位數,高位丟棄,低位補0

賦值運算子

運算子描述例項
=簡單的賦值運算子,將一個表示式的值賦給一個左值C = A + BA + B 表示式結果賦值給 C
+=相加後再賦值C += A等於 C = C + A
-=相減後再賦值C -= A 等於 C = C - A
*=相乘後再賦值C *= A 等於 C = C * A
/=相除後再賦值C /= A 等於 C = C / A
%=求餘後再賦值C %= A 等於 C = C % A
<<=左移後賦值C <<= 2 等於 C = C << 2
>>=右移後賦值C >>= 2 等於 C = C >> 2
&=按位與後賦值C &= 2 等於 C = C & 2
^=按位異或後賦值C ^= 2 等於 C = C ^ 2
|=按位或後賦值C |= 2等於 C = C | 2

其他運算子

運算子描述例項
&返回變數儲存地址&a; 將給出變數的實際地址。
*指標變數*a; 是一個指標變數

優先順序

優先順序運算子
5*/%<< >> &&^
4+-|^
3==!=<<=>>=
2&&
1||

控制語句

條件語句

指定一個或多個條件,並通過測試條件是否為true來決定是否執行指定語句,並在條件為false 的情況在執行另外的語句。

if語句

  • if 語句 由一個布林表示式後緊跟一個或多個語句組成。
  • if 語句 後可以使用可選的else語句, else語句中的表示式在布林表示式為false時執行。
  • ifelse if語句中可嵌入一個或多個ifelse if語句。
  • 同各類主流語言,不多贅述。但注意,Go 沒有三目運算子,所以不支援 ?: 形式的條件判斷
package main

import "fmt"

func main() {
   /* 定義區域性變數 */
   var a int = 10
   /* 使用 if 語句判斷布林表示式 */
   if a < 20 {
       /* 如果條件為 true 則執行以下語句 */
       fmt.Printf("a 小於 20\n" )
   }
   fmt.Printf("a 的值為 : %d\n", a)
}

switch語句

  • 用於基於不同條件執行不同動作,每一個case分支都是唯一的,從上至下逐一測試,直到匹配為止。
  • 匹配項後面不需要再加break
  • switch預設情況下case最後自帶break語句,匹配成功後就不會執行其他case,如果我們需要執行後面的case,可以使用fallthrough
  • fallthrough:強制執行後面的case語句,fallthrough不會判斷下一條case的表示式結果是否為 true
switch x.(type){
  case type:
    statement(s);
  case type:
    statement(s);
  default: // 可選
    statement(s);
}

解釋:
從第一個判斷表示式為truecase開始執行,如果case帶有fallthrough,程式會繼續執行下一條case,且它不會去判斷下一個case的表示式是否為true

  • 支援多條件匹配
  • 不同的case之間不使用break分隔,預設只會執行一個case
  • 如果想要執行多個 case,需要使用fallthrough關鍵字,也可用break終止
package main

import "fmt"

func main() {
    var x interface{}
    switch i := x.(type) { // 帶初始化語句
    case nil:
        fmt.Printf(" x 的型別 :%T\r\n", i)
    case int:
        fmt.Printf("x 是 int 型")
    case float64:
        fmt.Printf("x 是 float64 型")
    case func(int) float64:
        fmt.Printf("x 是 func(int) 型")
    case bool, string:
        fmt.Printf("x 是 bool 或 string 型")
    default:
        fmt.Printf("未知型")
    }
}

select語句

select {
  case communication clause  :
    statement(s);
  case communication clause  :
    statement(s);
  default : // 可選
    statement(s);
}
  • 每個case都必須是一個通訊(channel)
  • 所有channel表示式都會被求值
  • 所有被髮送的表示式都會被求值
  • 如果任意某個通訊可以進行,它就執行,其他被忽略。
  • 如果有多個case都可以執行,Select會隨機公平地選出一個執行。其他不會執行。 否則:
    • 如果有default子句,則執行該語句。
    • 如果沒有default子句,select將阻塞,直到某個通訊可以執行;Go不會重新對channel或值進行求值。
//比如在下面的場景中,使用全域性resChan來接受response,如果時間超過3S,resChan中還沒有資料返回,則第二條case將執行
var resChan = make(chan int)
// do request
func test() {
    select {
    case data := <-resChan:
        doData(data)
    case <-time.After(time.Second * 3):
        fmt.Println("request time out")
    }
}
func doData(data int) {
    //...
}
//在某些情況下是存在不希望channel快取滿了的需求的,可以用如下方法判斷
ch := make (chan int, 5)
//...
data:=0
select {
case ch <- data:
default:
    //做相應操作,比如丟棄data。視需求而定
}
//主執行緒(協程)中如下:
var shouldQuit=make(chan struct{})
fun main(){
    {
        //loop
    }
    //...out of the loop
    select {
        case <-c.shouldQuit:
            cleanUp()
            return
        default:
        }
    //...
}

//再另外一個協程中,如果執行遇到非法操作或不可處理的錯誤,就向shouldQuit傳送資料通知程式停止執行
close(shouldQuit)

迴圈語句

for迴圈

for init; condition; post { } //for
for condition { } //while
for {}
  • init: 一般為賦值表示式,給控制變數賦初值;
  • condition: 關係表示式或邏輯表示式,迴圈控制條件;
  • post: 一般為賦值表示式,給控制變數增量或減量。
  • for迴圈的range格式可以對slicemap、陣列、字串等進行迭代迴圈:
for key, value := range oldMap {
  newMap[key] = value
}
  • 可忽略不想要的返回值,或 “_” 這個特殊變數。
package main

func main() {
    s := "abc"
    // 忽略 2nd value,支援 string/array/slice/map。
    for i := range s {
        println(s[i])
    }
    // 忽略 index。
    for _, c := range s {
        println(c)
    }
    // 忽略全部返回值,僅迭代。
    for range s {

    }

    m := map[string]int{"a": 1, "b": 2}
    // 返回 (key, value)。
    for k, v := range m {
        println(k, v)
    }
}

迴圈巢狀

迴圈套迴圈,格式:

for [condition |  ( init; condition; increment ) | Range] {
 for [condition |  ( init; condition; increment ) | Range] {
   statement(s);
 }
 statement(s);
}

迴圈控制語句

break語句:

  • 用於迴圈語句中跳出迴圈,並開始執行迴圈之後的語句。
  • breakswitch(開關語句)中在執行一條case 後跳出語句的作用。
  • 在多重迴圈中,可以用標號label標出想break的迴圈。

continue語句:跳過當前迴圈的剩餘語句,然後繼續進行下一輪迴圈。

goto:無條件轉移到過程中指定行,與條件語句配合,實現條件轉移、構成迴圈、跳出迴圈體等(不建議用,造成混亂)

forfor range有什麼區別?

主要是使用場景不同

for可以:

  • 遍歷arrayslice
  • 遍歷key為整型遞增的map
  • 遍歷string

for range可以完成所有for可以做的事情,卻能做到for不能做的,包括:

  • 遍歷keystring型別的map並同時獲取keyvalue
  • 遍歷channe

相關文章