在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ GO/ 4.5 基本類型和運(yùn)算符
4.7 strings 和 strconv 包
13.6 啟動(dòng)外部命令和程序
?# 11.4 類型判斷:type-switch
12.1 讀取用戶的輸入
10.6 方法
12.2 文件讀寫(xiě)
13 錯(cuò)誤處理與測(cè)試
9.3 鎖和 sync 包
12.3 文件拷貝
?# 11.7 第一個(gè)例子:使用 Sorter 接口排序
?# 11.5 測(cè)試一個(gè)值是否實(shí)現(xiàn)了某個(gè)接口
6.4 defer 和追蹤
12.10 XML 數(shù)據(jù)格式
13.10 性能調(diào)試:分析并優(yōu)化 Go 程序
?# 11.1 接口是什么
2.2 Go 環(huán)境變量
2.6 安裝目錄清單
2.5 在 Windows 上安裝 Go
11.11 Printf 和反射
1.2 語(yǔ)言的主要特性與發(fā)展的環(huán)境和影響因素
9.0 包(package)
7.4 切片重組(reslice)
13.2 運(yùn)行時(shí)異常和 panic
10.2 使用工廠方法創(chuàng)建結(jié)構(gòu)體實(shí)例
12.8 使用接口的實(shí)際例子:fmt.Fprintf
2.4 在 Mac OS X 上安裝 Go
3.8 Go 性能說(shuō)明
7.2 切片
8.0 Map
3.1 Go 開(kāi)發(fā)環(huán)境的基本要求
5.6 標(biāo)簽與 goto
6.10 使用閉包調(diào)試
9.5 自定義包和可見(jiàn)性
4.3 常量
?# 11.2 接口嵌套接口
6.5 內(nèi)置函數(shù)
前言
10.8 垃圾回收和 SetFinalizer
2.8 Go 解釋器
13.7 Go 中的單元測(cè)試和基準(zhǔn)測(cè)試
6.8 閉包
4.9 指針
13.1 錯(cuò)誤處理
10.1 結(jié)構(gòu)體定義
5.1 if-else 結(jié)構(gòu)
6.6 遞歸函數(shù)
9.9 通過(guò) Git 打包和安裝
2.7 Go 運(yùn)行時(shí)(runtime)
10.7 類型的 String() 方法和格式化描述符
3.7 其它工具
9.6 為自定義包使用 godoc
11.12 接口與動(dòng)態(tài)類型
13.3 從 panic 中恢復(fù)(Recover)
10.3 使用自定義包中的結(jié)構(gòu)體
11.14 結(jié)構(gòu)體、集合和高階函數(shù)
3.6 生成代碼文檔
9.2 regexp 包
4.1 文件名、關(guān)鍵字與標(biāo)識(shí)符
?# 11.6 使用方法集與接口
7.0 數(shù)組與切片
7.1 聲明和初始化
12.11 用 Gob 傳輸數(shù)據(jù)
5.5 Break 與 continue
1.1 起源與發(fā)展
?# 11 接口(Interfaces)與反射(reflection)
6.9 應(yīng)用閉包:將函數(shù)作為返回值
4.2 Go 程序的基本結(jié)構(gòu)和要素
8.6 將 map 的鍵值對(duì)調(diào)
6.11 計(jì)算函數(shù)執(zhí)行時(shí)間
5.0 控制結(jié)構(gòu)
10.5 匿名字段和內(nèi)嵌結(jié)構(gòu)體
4.6 字符串
3.0 編輯器、集成開(kāi)發(fā)環(huán)境與其它工具
13.8 測(cè)試的具體例子
7.6 字符串、數(shù)組和切片的應(yīng)用
8.4 map 類型的切片
3.9 與其它語(yǔ)言進(jìn)行交互
7.3 For-range 結(jié)構(gòu)
9.7 使用 go install 安裝自定義包
6.0 函數(shù)
9.8 自定義包的目錄結(jié)構(gòu)、go install 和 go test
6.3 傳遞變長(zhǎng)參數(shù)
13.9 用(測(cè)試數(shù)據(jù))表驅(qū)動(dòng)測(cè)試
11.9 空接口
8.1 聲明、初始化和 make
6.2 函數(shù)參數(shù)與返回值
9.11 在 Go 程序中使用外部庫(kù)
3.3 調(diào)試器
4.5 基本類型和運(yùn)算符
?# 11.8 第二個(gè)例子:讀和寫(xiě)
12.5 用 buffer 讀取文件
總結(jié):Go 中的面向?qū)ο?/span>
11.10 反射包
12.7 用 defer 關(guān)閉文件
9.4 精密計(jì)算和 big 包
4.4 變量
6.1 介紹
13.4 自定義包中的錯(cuò)誤處理和 panicking
12.4 從命令行讀取參數(shù)
9.10 Go 的外部包和項(xiàng)目
8.3 for-range 的配套用法
3.5 格式化代碼
10.4 帶標(biāo)簽的結(jié)構(gòu)體
7.5 切片的復(fù)制與追加
?# 11.3 類型斷言:如何檢測(cè)和轉(zhuǎn)換接口變量的類型
5.4 for 結(jié)構(gòu)
4.8 時(shí)間和日期
2.3 在 Linux 上安裝 Go
12 讀寫(xiě)數(shù)據(jù)
6.12 通過(guò)內(nèi)存緩存來(lái)提升性能
9.1 標(biāo)準(zhǔn)庫(kù)概述
12.6 用切片讀寫(xiě)文件
10 結(jié)構(gòu)(struct)與方法(method)
8.5 map 的排序
12.9 JSON 數(shù)據(jù)格式
13.5 一種用閉包處理錯(cuò)誤的模式
3.2 編輯器和集成開(kāi)發(fā)環(huán)境
12.12 Go 中的密碼學(xué)
5.2 測(cè)試多返回值函數(shù)的錯(cuò)誤
6.7 將函數(shù)作為參數(shù)
8.2 測(cè)試鍵值對(duì)是否存在及刪除元素
3.4 構(gòu)建并運(yùn)行 Go 程序
2.1 平臺(tái)與架構(gòu)
5.3 switch 結(jié)構(gòu)

4.5 基本類型和運(yùn)算符

我們將在這個(gè)部分講解有關(guān)布爾型、數(shù)字型和字符型的相關(guān)知識(shí)。

表達(dá)式是一種特定的類型的值,它可以由其它的值以及運(yùn)算符組合而成。每個(gè)類型都定義了可以和自己結(jié)合的運(yùn)算符集合,如果你使用了不在這個(gè)集合中的運(yùn)算符,則會(huì)在編譯時(shí)獲得編譯錯(cuò)誤。

一元運(yùn)算符只可以用于一個(gè)值的操作(作為后綴),而二元運(yùn)算符則可以和兩個(gè)值或者操作數(shù)結(jié)合(作為中綴)。

只有兩個(gè)類型相同的值才可以和二元運(yùn)算符結(jié)合,另外要注意的是,Go 是強(qiáng)類型語(yǔ)言,因此不會(huì)進(jìn)行隱式轉(zhuǎn)換,任何不同類型之間的轉(zhuǎn)換都必須顯式說(shuō)明(第 4.2 節(jié))。Go 不存在像 C 和 Java 那樣的運(yùn)算符重載,表達(dá)式的解析順序是從左至右。

你可以在第 4.5.3 節(jié)找到有關(guān)運(yùn)算符優(yōu)先級(jí)的相關(guān)信息,優(yōu)先級(jí)越高的運(yùn)算符在條件相同的情況下將被優(yōu)先執(zhí)行。但是你可以通過(guò)使用括號(hào)將其中的表達(dá)式括起來(lái),以人為地提升某個(gè)表達(dá)式的運(yùn)算優(yōu)先級(jí)。

4.5.1 布爾類型 bool

一個(gè)簡(jiǎn)單的例子:var b bool = true。

布爾型的值只可以是常量 true 或者 false。

兩個(gè)類型相同的值可以使用相等 == 或者不等 != 運(yùn)算符來(lái)進(jìn)行比較并獲得一個(gè)布爾型的值。

當(dāng)相等運(yùn)算符兩邊的值是完全相同的值的時(shí)候會(huì)返回 true,否則返回 false,并且只有在兩個(gè)的值的類型相同的情況下才可以使用。

示例:

var aVar = 10
aVar == 5 -> false
aVar == 10 -> true

當(dāng)不等運(yùn)算符兩邊的值是不同的時(shí)候會(huì)返回 true,否則返回 false。

示例:

var aVar = 10
aVar != 5 -> true
aVar != 10 -> false

Go 對(duì)于值之間的比較有非常嚴(yán)格的限制,只有兩個(gè)類型相同的值才可以進(jìn)行比較,如果值的類型是接口(interface,第 11 章),它們也必須都實(shí)現(xiàn)了相同的接口。如果其中一個(gè)值是常量,那么另外一個(gè)值的類型必須和該常量類型相兼容的。如果以上條件都不滿足,則其中一個(gè)值的類型必須在被轉(zhuǎn)換為和另外一個(gè)值的類型相同之后才可以進(jìn)行比較。

布爾型的常量和變量也可以通過(guò)和邏輯運(yùn)算符(非 !、和 &&、或 ||)結(jié)合來(lái)產(chǎn)生另外一個(gè)布爾值,這樣的邏輯語(yǔ)句就其本身而言,并不是一個(gè)完整的 Go 語(yǔ)句。

邏輯值可以被用于條件結(jié)構(gòu)中的條件語(yǔ)句(第 5 章),以便測(cè)試某個(gè)條件是否滿足。另外,和 &&、或 || 與相等 == 或不等 != 屬于二元運(yùn)算符,而非 ! 屬于一元運(yùn)算符。在接下來(lái)的內(nèi)容中,我們會(huì)使用 T 來(lái)代表?xiàng)l件符合的語(yǔ)句,用 F 來(lái)代表?xiàng)l件不符合的語(yǔ)句。

Go 語(yǔ)言中包含以下邏輯運(yùn)算符:

非運(yùn)算符:!

!T -> false
!F -> true

非運(yùn)算符用于取得和布爾值相反的結(jié)果。

和運(yùn)算符:&&

T && T -> true
T && F -> false
F && T -> false
F && F -> false

只有當(dāng)兩邊的值都為 true 的時(shí)候,和運(yùn)算符的結(jié)果才是 true。

或運(yùn)算符:||

T || T -> true
T || F -> true
F || T -> true
F || F -> false

只有當(dāng)兩邊的值都為 false 的時(shí)候,或運(yùn)算符的結(jié)果才是 false,其中任意一邊的值為 true 就能夠使得該表達(dá)式的結(jié)果為 true。

在 Go 語(yǔ)言中,&& 和 || 是具有快捷性質(zhì)的運(yùn)算符,當(dāng)運(yùn)算符左邊表達(dá)式的值已經(jīng)能夠決定整個(gè)表達(dá)式的值的時(shí)候(&& 左邊的值為 false,|| 左邊的值為 true),運(yùn)算符右邊的表達(dá)式將不會(huì)被執(zhí)行。利用這個(gè)性質(zhì),如果你有多個(gè)條件判斷,應(yīng)當(dāng)將計(jì)算過(guò)程較為復(fù)雜的表達(dá)式放在運(yùn)算符的右側(cè)以減少不必要的運(yùn)算。

利用括號(hào)同樣可以升級(jí)某個(gè)表達(dá)式的運(yùn)算優(yōu)先級(jí)。

在格式化輸出時(shí),你可以使用 %t 來(lái)表示你要輸出的值為布爾型。

布爾值(以及任何結(jié)果為布爾值的表達(dá)式)最常用在條件結(jié)構(gòu)的條件語(yǔ)句中,例如:if、for 和 switch 結(jié)構(gòu)(第 5 章)。

對(duì)于布爾值的好的命名能夠很好地提升代碼的可讀性,例如以 is 或者 Is 開(kāi)頭的 isSortedisFinished、isVisible,使用這樣的命名能夠在閱讀代碼的獲得閱讀正常語(yǔ)句一樣的良好體驗(yàn),例如標(biāo)準(zhǔn)庫(kù)中的 unicode.IsDigit(ch)(第 4.5.5 節(jié))。

4.5.2 數(shù)字類型

4.5.2.1 整型 int 和浮點(diǎn)型 float

Go 語(yǔ)言支持整型和浮點(diǎn)型數(shù)字,并且原生支持復(fù)數(shù),其中位的運(yùn)算采用補(bǔ)碼(詳情參見(jiàn) 二的補(bǔ)碼 頁(yè)面)。

Go 也有基于架構(gòu)的類型,例如:int、uint 和 uintptr。

這些類型的長(zhǎng)度都是根據(jù)運(yùn)行程序所在的操作系統(tǒng)類型所決定的:

  • intuint 在 32 位操作系統(tǒng)上,它們均使用 32 位(4 個(gè)字節(jié)),在 64 位操作系統(tǒng)上,它們均使用 64 位(8 個(gè)字節(jié))。
  • uintptr 的長(zhǎng)度被設(shè)定為足夠存放一個(gè)指針即可。

Go 語(yǔ)言中沒(méi)有 float 類型。

與操作系統(tǒng)架構(gòu)無(wú)關(guān)的類型都有固定的大小,并在類型的名稱中就可以看出來(lái):

整數(shù):

  • int8(-128 -> 127)
  • int16(-32768 -> 32767)
  • int32(-2,147,483,648 -> 2,147,483,647)
  • int64(-9,223,372,036,854,775,808 -> 9,223,372,036,854,775,807)

無(wú)符號(hào)整數(shù):

  • uint8(0 -> 255)
  • uint16(0 -> 65,535)
  • uint32(0 -> 4,294,967,295)
  • uint64(0 -> 18,446,744,073,709,551,615)

浮點(diǎn)型(IEEE-754 標(biāo)準(zhǔn)):

  • float32(+- 1e-45 -> +- 3.4 * 1e38)
  • float64(+- 5 1e-324 -> 107 1e308)

int 型是計(jì)算最快的一種類型。

整型的零值為 0,浮點(diǎn)型的零值為 0.0。

float32 精確到小數(shù)點(diǎn)后 7 位,float64 精確到小數(shù)點(diǎn)后 15 位。由于精確度的緣故,你在使用 == 或者 != 來(lái)比較浮點(diǎn)數(shù)時(shí)應(yīng)當(dāng)非常小心。你最好在正式使用前測(cè)試對(duì)于精確度要求較高的運(yùn)算。

你應(yīng)該盡可能地使用 float64,因?yàn)?math 包中所有有關(guān)數(shù)學(xué)運(yùn)算的函數(shù)都會(huì)要求接收這個(gè)類型。

你可以通過(guò)增加前綴 0 來(lái)表示 8 進(jìn)制數(shù)(如:077),增加前綴 0x 來(lái)表示 16 進(jìn)制數(shù)(如:0xFF),以及使用 e 來(lái)表示 10 的連乘(如: 1e3 = 1000,或者 6.022e23 = 6.022 x 1e23)。

你可以使用 a := uint64(0) 來(lái)同時(shí)完成類型轉(zhuǎn)換和賦值操作,這樣 a 的類型就是 uint64。

Go 中不允許不同類型之間的混合使用,但是對(duì)于常量的類型限制非常少,因此允許常量之間的混合使用,下面這個(gè)程序很好地解釋了這個(gè)現(xiàn)象(該程序無(wú)法通過(guò)編譯):

示例 4.8 type_mixing.go

package main

func main() {
    var a int
    var b int32
    a = 15
    b = a + a    // 編譯錯(cuò)誤
    b = b + 5    // 因?yàn)?5 是常量,所以可以通過(guò)編譯
}

如果你嘗試編譯該程序,則將得到編譯錯(cuò)誤 cannot use a + a (type int) as type int32 in assignment

同樣地,int16 也不能夠被隱式轉(zhuǎn)換為 int32。

下面這個(gè)程序展示了通過(guò)顯式轉(zhuǎn)換來(lái)避免這個(gè)問(wèn)題(第 4.2 節(jié))。

示例 4.9 casting.go

package main

import "fmt"

func main() {
    var n int16 = 34
    var m int32
    // compiler error: cannot use n (type int16) as type int32 in assignment
    //m = n
    m = int32(n)

    fmt.Printf("32 bit int is: %d\n", m)
    fmt.Printf("16 bit int is: %d\n", n)
}

輸出:

32 bit int is: 34
16 bit int is: 34

格式化說(shuō)明符

在格式化字符串里,%d 用于格式化整數(shù)(%x%X 用于格式化 16 進(jìn)制表示的數(shù)字),%g 用于格式化浮點(diǎn)型(%f 輸出浮點(diǎn)數(shù),%e 輸出科學(xué)計(jì)數(shù)表示法),%0d 用于規(guī)定輸出定長(zhǎng)的整數(shù),其中開(kāi)頭的數(shù)字 0 是必須的。

%n.mg 用于表示數(shù)字 n 并精確到小數(shù)點(diǎn)后 m 位,除了使用 g 之外,還可以使用 e 或者 f,例如:使用格式化字符串 %5.2e 來(lái)輸出 3.4 的結(jié)果為 3.40e+00。

數(shù)字值轉(zhuǎn)換

當(dāng)進(jìn)行類似 a32bitInt = int32(a32Float) 的轉(zhuǎn)換時(shí),小數(shù)點(diǎn)后的數(shù)字將被丟棄。這種情況一般發(fā)生當(dāng)從取值范圍較大的類型轉(zhuǎn)換為取值范圍較小的類型時(shí),或者你可以寫(xiě)一個(gè)專門(mén)用于處理類型轉(zhuǎn)換的函數(shù)來(lái)確保沒(méi)有發(fā)生精度的丟失。下面這個(gè)例子展示如何安全地從 int 型轉(zhuǎn)換為 int8:

func Uint8FromInt(n int) (uint8, error) {
    if 0 <= n && n <= math.MaxUint8 { // conversion is safe
        return uint8(n), nil
    }
    return 0, fmt.Errorf("%d is out of the uint8 range", n)
}

或者安全地從 float64 轉(zhuǎn)換為 int:

func IntFromFloat64(x float64) int {
    if math.MinInt32 <= x && x <= math.MaxInt32 { // x lies in the integer range
        whole, fraction := math.Modf(x)
        if fraction >= 0.5 {
            whole++
        }
        return int(whole)
    }
    panic(fmt.Sprintf("%g is out of the int32 range", x))
}

不過(guò)如果你實(shí)際存的數(shù)字超出你要轉(zhuǎn)換到的類型的取值范圍的話,則會(huì)引發(fā) panic(第 13.2 節(jié))。

問(wèn)題 4.1 int 和 int64 是相同的類型嗎?

4.5.2.2 復(fù)數(shù)

Go 擁有以下復(fù)數(shù)類型:

complex64 (32 位實(shí)數(shù)和虛數(shù))
complex128 (64 位實(shí)數(shù)和虛數(shù))

復(fù)數(shù)使用 re+imI 來(lái)表示,其中 re 代表實(shí)數(shù)部分,im 代表虛數(shù)部分,I 代表根號(hào)負(fù) 1。

示例:

var c1 complex64 = 5 + 10i
fmt.Printf("The value is: %v", c1)
// 輸出: 5 + 10i

如果 reim 的類型均為 float32,那么類型為 complex64 的復(fù)數(shù) c 可以通過(guò)以下方式來(lái)獲得:

c = complex(re, im)

函數(shù) real(c)imag(c) 可以分別獲得相應(yīng)的實(shí)數(shù)和虛數(shù)部分。

在使用格式化說(shuō)明符時(shí),可以使用 %v 來(lái)表示復(fù)數(shù),但當(dāng)你希望只表示其中的一個(gè)部分的時(shí)候需要使用 %f

復(fù)數(shù)支持和其它數(shù)字類型一樣的運(yùn)算。當(dāng)你使用等號(hào) == 或者不等號(hào) != 對(duì)復(fù)數(shù)進(jìn)行比較運(yùn)算時(shí),注意對(duì)精確度的把握。cmath 包中包含了一些操作復(fù)數(shù)的公共方法。如果你對(duì)內(nèi)存的要求不是特別高,最好使用 complex128 作為計(jì)算類型,因?yàn)橄嚓P(guān)函數(shù)都使用這個(gè)類型的參數(shù)。

4.5.2.3 位運(yùn)算

位運(yùn)算只能用于整數(shù)類型的變量,且需當(dāng)它們擁有等長(zhǎng)位模式時(shí)。

%b 是用于表示位的格式化標(biāo)識(shí)符。

二元運(yùn)算符

  • 按位與 &

    對(duì)應(yīng)位置上的值經(jīng)過(guò)和運(yùn)算結(jié)果,具體參見(jiàn)和運(yùn)算符,第 4.5.1 節(jié),并將 T(true)替換為 1,將 F(false)替換為 0

      1 & 1 -> 1
      1 & 0 -> 0
      0 & 1 -> 0
      0 & 0 -> 0
  • 按位或 |

    對(duì)應(yīng)位置上的值經(jīng)過(guò)或運(yùn)算結(jié)果,具體參見(jiàn)或運(yùn)算符,第 4.5.1 節(jié),并將 T(true)替換為 1,將 F(false)替換為 0

      1 | 1 -> 1
      1 | 0 -> 1
      0 | 1 -> 1
      0 | 0 -> 0
  • 按位異或 ^

    對(duì)應(yīng)位置上的值根據(jù)以下規(guī)則組合:

      1 ^ 1 -> 0
      1 ^ 0 -> 1
      0 ^ 1 -> 1
      0 ^ 0 -> 0
  • 位清除 &^:將指定位置上的值設(shè)置為 0。

一元運(yùn)算符

  • 按位補(bǔ)足 ^

    該運(yùn)算符與異或運(yùn)算符一同使用,即 m^x,對(duì)于無(wú)符號(hào) x 使用“全部位設(shè)置為 1”,對(duì)于有符號(hào) x 時(shí)使用 m=-1。例如:

      ^2 = ^10 = -01 ^ 10 = -11
  • 位左移 <<

    • 用法:bitP << n
    • bitP 的位向左移動(dòng) n 位,右側(cè)空白部分使用 0 填充;如果 n 等于 2,則結(jié)果是 2 的相應(yīng)倍數(shù),即 2 的 n 次方。例如:

          1 << 10 // 等于 1 KB
          1 << 20 // 等于 1 MB
          1 << 30 // 等于 1 GB
  • 位右移 >>

    • 用法:bitP >> n。
    • bitP 的位向右移動(dòng) n 位,左側(cè)空白部分使用 0 填充;如果 n 等于 2,則結(jié)果是當(dāng)前值除以 2 的 n 次方。

當(dāng)希望把結(jié)果賦值給第一個(gè)操作數(shù)時(shí),可以簡(jiǎn)寫(xiě)為 a <<= 2 或者 b ^= a & 0xffffffff。

位左移常見(jiàn)實(shí)現(xiàn)存儲(chǔ)單位的用例

使用位左移與 iota 計(jì)數(shù)配合可優(yōu)雅地實(shí)現(xiàn)存儲(chǔ)單位的常量枚舉:

type ByteSize float64
const (
    _ = iota // 通過(guò)賦值給空白標(biāo)識(shí)符來(lái)忽略值
    KB ByteSize = 1<<(10*iota)
    MB
    GB
    TB
    PB
    EB
    ZB
    YB
)

在通訊中使用位左移表示標(biāo)識(shí)的用例

type BitFlag int
const (
    Active BitFlag = 1 << iota // 1 << 0 == 1
    Send // 1 << 1 == 2
    Receive // 1 << 2 == 4
)

flag := Active | Send // == 3

4.5.2.4 邏輯運(yùn)算符

Go 中擁有以下邏輯運(yùn)算符:==、!=(第 4.5.1 節(jié))、<<=、>、>=

它們之所以被稱為邏輯運(yùn)算符是因?yàn)樗鼈兊倪\(yùn)算結(jié)果總是為布爾值 bool。例如:

b3:= 10 > 5 // b3 is true

4.5.2.5 算術(shù)運(yùn)算符

常見(jiàn)可用于整數(shù)和浮點(diǎn)數(shù)的二元運(yùn)算符有 +、-、*/。

(相對(duì)于一般規(guī)則而言,Go 在進(jìn)行字符串拼接時(shí)允許使用對(duì)運(yùn)算符 + 的重載,但 Go 本身不允許開(kāi)發(fā)者進(jìn)行自定義的運(yùn)算符重載)

/ 對(duì)于整數(shù)運(yùn)算而言,結(jié)果依舊為整數(shù),例如:9 / 4 -> 2。

取余運(yùn)算符只能作用于整數(shù):9 % 4 -> 1。

整數(shù)除以 0 可能導(dǎo)致程序崩潰,將會(huì)導(dǎo)致運(yùn)行時(shí)的恐慌狀態(tài)(如果除以 0 的行為在編譯時(shí)就能被捕捉到,則會(huì)引發(fā)編譯錯(cuò)誤);第 13 章將會(huì)詳細(xì)講解如何正確地處理此類情況。

浮點(diǎn)數(shù)除以 0.0 會(huì)返回一個(gè)無(wú)窮盡的結(jié)果,使用 +Inf 表示。

練習(xí) 4.4 嘗試編譯 divby0.go。

你可以將語(yǔ)句 b = b + a 簡(jiǎn)寫(xiě)為 b+=a,同樣的寫(xiě)法也可用于 -=*=、/=、%=

對(duì)于整數(shù)和浮點(diǎn)數(shù),你可以使用一元運(yùn)算符 ++(遞增)和 --(遞減),但只能用于后綴:

i++ -> i += 1 -> i = i + 1
i-- -> i -= 1 -> i = i - 1

同時(shí),帶有 ++-- 的只能作為語(yǔ)句,而非表達(dá)式,因此 n = i++ 這種寫(xiě)法是無(wú)效的,其它像 f(i++) 或者 a[i]=b[i++] 這些可以用于 C、C++ 和 Java 中的寫(xiě)法在 Go 中也是不允許的。

在運(yùn)算時(shí) 溢出 不會(huì)產(chǎn)生錯(cuò)誤,Go 會(huì)簡(jiǎn)單地將超出位數(shù)拋棄。如果你需要范圍無(wú)限大的整數(shù)或者有理數(shù)(意味著只被限制于計(jì)算機(jī)內(nèi)存),你可以使用標(biāo)準(zhǔn)庫(kù)中的 big 包,該包提供了類似 big.Intbig.Rat 這樣的類型(第 9.4 節(jié))。

4.5.2.6 隨機(jī)數(shù)

一些像游戲或者統(tǒng)計(jì)學(xué)類的應(yīng)用需要用到隨機(jī)數(shù)。rand 包實(shí)現(xiàn)了偽隨機(jī)數(shù)的生成。

示例 4.10 random.go 演示了如何生成 10 個(gè)非負(fù)隨機(jī)數(shù):

package main
import (
    "fmt"
    "math/rand"
    "time"
)

func main() {
    for i := 0; i < 10; i++ {
        a := rand.Int()
        fmt.Printf("%d / ", a)
    }
    for i := 0; i < 5; i++ {
        r := rand.Intn(8)
        fmt.Printf("%d / ", r)
    }
    fmt.Println()
    timens := int64(time.Now().Nanosecond())
    rand.Seed(timens)
    for i := 0; i < 10; i++ {
        fmt.Printf("%2.2f / ", 100*rand.Float32())
    }
}

可能的輸出:

816681689 / 1325201247 / 623951027 / 478285186 / 1654146165 /
1951252986 / 2029250107 / 762911244 / 1372544545 / 591415086 / / 3 / 0 / 6 / 4 / 2 /22.10
/ 65.77 / 65.89 / 16.85 / 75.56 / 46.90 / 55.24 / 55.95 / 25.58 / 70.61 /

函數(shù) rand.Float32rand.Float64 返回介于 [0.0, 1.0) 之間的偽隨機(jī)數(shù),其中包括 0.0 但不包括 1.0。函數(shù) rand.Intn 返回介于 [0, n) 之間的偽隨機(jī)數(shù)。

你可以使用 Seed(value) 函數(shù)來(lái)提供偽隨機(jī)數(shù)的生成種子,一般情況下都會(huì)使用當(dāng)前時(shí)間的納秒級(jí)數(shù)字(第 4.8 節(jié))。

4.5.3 運(yùn)算符與優(yōu)先級(jí)

有些運(yùn)算符擁有較高的優(yōu)先級(jí),二元運(yùn)算符的運(yùn)算方向均是從左至右。下表列出了所有運(yùn)算符以及它們的優(yōu)先級(jí),由上至下代表優(yōu)先級(jí)由高到低:

優(yōu)先級(jí)     運(yùn)算符
 7      ^ !
 6      * / % << >> & &^
 5      + - | ^
 4      == != < <= >= >
 3      <-
 2      &&
 1      ||

當(dāng)然,你可以通過(guò)使用括號(hào)來(lái)臨時(shí)提升某個(gè)表達(dá)式的整體運(yùn)算優(yōu)先級(jí)。

4.5.4 類型別名

當(dāng)你在使用某個(gè)類型時(shí),你可以給它起另一個(gè)名字,然后你就可以在你的代碼中使用新的名字(用于簡(jiǎn)化名稱或解決名稱沖突)。

type TZ int 中,TZ 就是 int 類型的新名稱(用于表示程序中的時(shí)區(qū)),然后就可以使用 TZ 來(lái)操作 int 類型的數(shù)據(jù)。

示例 4.11 type.go

package main
import "fmt"

type TZ int

func main() {
    var a, b TZ = 3, 4
    c := a + b
    fmt.Printf("c has the value: %d", c) // 輸出:c has the value: 7
}

實(shí)際上,類型別名得到的新類型并非和原類型完全相同,新類型不會(huì)擁有原類型所附帶的方法(第 10 章);TZ 可以自定義一個(gè)方法用來(lái)輸出更加人性化的時(shí)區(qū)信息。

練習(xí) 4.5 定義一個(gè) string 的類型別名 Rope,并聲明一個(gè)該類型的變量。

4.5.5 字符類型

嚴(yán)格來(lái)說(shuō),這并不是 Go 語(yǔ)言的一個(gè)類型,字符只是整數(shù)的特殊用例。byte 類型是 uint8 的別名,對(duì)于只占用 1 個(gè)字節(jié)的傳統(tǒng) ASCII 編碼的字符來(lái)說(shuō),完全沒(méi)有問(wèn)題。例如:var ch byte = 'A';字符使用單引號(hào)括起來(lái)。

在 ASCII 碼表中,A 的值是 65,而使用 16 進(jìn)制表示則為 41,所以下面的寫(xiě)法是等效的:

var ch byte = 65 或 var ch byte = '\x41'

\x 總是緊跟著長(zhǎng)度為 2 的 16 進(jìn)制數(shù))

另外一種可能的寫(xiě)法是 \ 后面緊跟著長(zhǎng)度為 3 的八進(jìn)制數(shù),例如:\377。

不過(guò) Go 同樣支持 Unicode(UTF-8),因此字符同樣稱為 Unicode 代碼點(diǎn)或者 runes,并在內(nèi)存中使用 int 來(lái)表示。在文檔中,一般使用格式 U+hhhh 來(lái)表示,其中 h 表示一個(gè) 16 進(jìn)制數(shù)。其實(shí) rune 也是 Go 當(dāng)中的一個(gè)類型,并且是 int32 的別名。

在書(shū)寫(xiě) Unicode 字符時(shí),需要在 16 進(jìn)制數(shù)之前加上前綴 \u 或者 \U。

因?yàn)?Unicode 至少占用 2 個(gè)字節(jié),所以我們使用 int16 或者 int 類型來(lái)表示。如果需要使用到 4 字節(jié),則會(huì)加上 \U 前綴;前綴 \u 則總是緊跟著長(zhǎng)度為 4 的 16 進(jìn)制數(shù),前綴 \U 緊跟著長(zhǎng)度為 8 的 16 進(jìn)制數(shù)。

示例 4.12 char.go

var ch int = '\u0041'
var ch2 int = '\u03B2'
var ch3 int = '\U00101234'
fmt.Printf("%d - %d - %d\n", ch, ch2, ch3) // integer
fmt.Printf("%c - %c - %c\n", ch, ch2, ch3) // character
fmt.Printf("%X - %X - %X\n", ch, ch2, ch3) // UTF-8 bytes
fmt.Printf("%U - %U - %U", ch, ch2, ch3) // UTF-8 code point

輸出:

65 - 946 - 1053236
A - β - r
41 - 3B2 - 101234
U+0041 - U+03B2 - U+101234

格式化說(shuō)明符 %c 用于表示字符;當(dāng)和字符配合使用時(shí),%v%d 會(huì)輸出用于表示該字符的整數(shù);%U 輸出格式為 U+hhhh 的字符串(另一個(gè)示例見(jiàn)第 5.4.4 節(jié))。

unicode 包含了一些針對(duì)測(cè)試字符的非常有用的函數(shù)(其中 ch 代表字符):

  • 判斷是否為字母:unicode.IsLetter(ch)
  • 判斷是否為數(shù)字:unicode.IsDigit(ch)
  • 判斷是否為空白符號(hào):unicode.IsSpace(ch)

這些函數(shù)返回一個(gè)布爾值。包 utf8 擁有更多與 rune 相關(guān)的函數(shù)。

譯者注:關(guān)于類型的相關(guān)講解,可參考視頻教程 《Go編程基礎(chǔ)》 第 3 課:類型與變量

鏈接