網站首頁 編程語言 正文
每一個變量都有數據類型,Go中的數據類型有:
- 簡單數據類型:int、float、complex、bool和string
- 數據結構或組合(composite):struct、array、slice、map和channel
- 接口(interface)
當聲明變量的時候,會做默認的賦0初始化。每種數據類型的默認賦0初始化的0值不同,例如int類型的0值為數值0,float的0值為0.0,string類型的0值為空"",bool類型的0值為false,數據結構的0值為nil,struct的0值為字段全部賦0。
其實函數也有類型,不過一般稱之為返回類型。例如,下面的函數foo的返回類型是int:
func foo() int { ...CODE... return INT_TYPE_VALUE }
函數允許有多個返回值,它們使用逗號分隔,括號包圍:
func foo() (int,bool)
Number類型
Integer
Integer類型是整型數據,例如3 22 0 1 -3 -22
等。
Go中的Integer有以下幾種細分的類型:
- int8,int16,int32,int64
- uint8,uint16,uint32,uint64
- byte
- rune
- int,uint
其中8 16 32 64
表示該數據類型能存儲的bit位數。例如int8表示能存儲8位數值,所以這個類型占用1字節,也表示最大能存儲的整型數共2^8=256
個,所以int8類型允許的最大正數為127,允許的最小負數為-128,共256個數值。
uint中的u表示unsigned,即無符號整數,只保存0和正數。所以uint8能存儲256個數的時候,允許的最小值為0,允許的最大值為255。
額外的兩種Integer是byte和rune,它們分別等價于uint8(即一個字節大小的正數)、int32。從builtin包中的定義就可以知道:
$ go doc builtin | grep -E "byte|rune" type byte = uint8 type rune = int32
byte類型后面會詳細解釋。
還有兩種依賴于CPU位數的類型int和uint,它們分別表示一個機器字長。在32位CPU上,一個機器字長為32bit,共4字節,在64位CPU上,一個機器字長為64bit,共8字節。除了int和uint依賴于CPU架構,還有一種uintptr也是依賴于機器字長的。
一般來說,需要使用整型數據的時候,指定int即可,有明確的額外需求時再考慮是否換成其它整數類型。
在整數加上0前綴表示這是8進制,例如077
。加上前綴0x
表示這是16進制,例如0x0c
,使用e符號可以表示這是一個科學計數法,如1e3 = 1000,6.023e23 = 6.023 x 10^23
。
可以使用TYPE(N)的方式來生成一個數值,例如a := uint64(5)
。實際上這是類型轉換,將int類型的5轉換成int64類型的5。
byte類型
Go中沒有專門提供字符類型char,Go內部的所有字符類型(無論是ASCII字符還是其它多字節字符)都使用整數值保存,所以字符可以存放到byte、int等數據類型變量中。byte類型等價于uint8類型,表示無符號的1字節整數。
Go中的字符都使用單引號包圍,例如'a'
、'我'
,但單引號中包含了多個字符是錯誤的(如'aA'
),因為字符類型就是一個字符。
例如,ASCII的字母a表示97。下面這種定義方式是允許的:
var a byte = 'A' // a=65 var b uint8 = 'a' // b=97
注意,字符必須使用單引號,且必須只能是單個字符。所以byte類型經常被稱為character類型。
以下也都是允許的:
var a = 'A' var a uint32 = 'A' var a int64 = 'A'
所以,Integer類型當存儲的是以單引號包圍的字符時,它會將字符轉換成它二進制值對應的數值。同樣適用于unicode字符,它將用來存放各字節對應的二進制的數值:
var a int64 = '我' // a=25105
由于我
在Go中占用3字節,所以保存到byte中是報錯的:
var a byte = '我'
可以保存它的unicode字符的代碼點:
var a byte = '\u0041' // a=65,代表的字符A
如果不知道代碼點的值,可以將其以int類型保存并輸出。
fmt.Printf("%d", '我') // 25105
如果想將byte值轉換為字符,可以使用string()函數做簡單的類型轉換:
var a = 'A' println(string(a)) // 輸出:A
float和complex
float是浮點數(俗稱小數),例如0.0 3.0 -3.12 -3.120
等。
Go中的浮點數類型float有兩種:float32和float64。
complex表示復數類型(虛數),有complex64和complex128。
浮點數在計算機系統中非常復雜,對于學習來說,只需將其認為是數學中的一種小數即可。但以下幾個注意點需要謹記心中:
- 浮點數是不精確的。例如
1.01-0.99
從數學運算的角度上得到的值是0.02,但實際上的結果是0.020000000000000018(python運算的結果),在Go中會將其表示為+2.000000e-002
。這個結果是一種極限趨近于我們期待值的結果。 - float32的精度(7個小數位)低于float64(15個小數位),所以float64類型的值比float32類型的值更精確。
- 因為浮點數不精確,所以盡量不要對兩個浮點數數進行等值
==
和不等值!=
比較,例如(3.2-2.8) == 0.4
返回Flase。如果非要比較,應該通過它們的減法求絕對值,再與一個足夠小(不會影響結果)的值做不等比較,例如abs((3.2-2.8)-0.4) < 0.0002
返回True。
一般來說,在程序中需要使用浮點數的時候都使用float64類型,不僅因為精確,更因為幾乎所有包中需要float參數的類型都是float64。
在Go的數學運算中,默認取的是整型數據,如果想要得到浮點數結果,必須至少讓運算的一方寫成浮點數格式:
var a := 3/2 // a得到截斷的整數:a=1 var b := 3/2.0 // b為浮點數b=+1.500000e+000 var c := 3 + 2.0 // c為浮點數
string類型
Go中的string用于保存UTF-8字符序列,它是動態大小的。對于字母和英文字母,它占用一個字節,對于其它unicode字符,按需占用2-4個字節。例如中文字符占用3個字節。
Go中的string類型要使用雙引號或反引號包圍,它們的區別是:
- 雙引號是弱引用,其內可以使用反斜線轉義符號,如
ab\ncd
表示ab后換行加cd - 反引號是強引用,其內任何符號都被強制解釋為字面意義,包括字面的換行。也就是所謂的裸字符串。
func main() { println("abc\ndef") println(`ABC DEF`) }
上面的結果將輸出:
abc def ABC DEF
不能使用單引號包圍,單引號包圍的表示它的二進制值轉換成十進制的數值。例如字母對應的是ASCII碼。這個在前面byte類型中介紹過。所以,使用單引號包圍的字符實際上是整數數值。例如'a'
等價于97。
string的底層是byte數組,每個string其實只占用兩個機器字長:一個指針和一個長度。只不過這個指針在Go中完全不可見,所以對我們來說,string是一個底層byte數組的值類型而非指針類型。
所以,可以將一個string使用append()或copy()拷貝到一個給定的byte slice中,也可以使用slice的切片功能截取string中的片段。
func main() { var a = "Hello Gaoxiaofang" println(a[2:3]) // 輸出:l s1 := make([]byte,30) copy(s1,a) // 將字符串保存到slice中 println(string(s1)) // 輸出"Hello Gaoxiaofang" }
字符串串接
使用加號+
連接兩段字符串:"Hello" + "World"等價于"HelloWorld"。
可以通過+
的方式將多行連接起來。例如:
str := "Beginning string "+ "second string"
字符串連接+
操作符強制認為它兩邊的都是string類型,所以"abcd" + 2
將報錯。需要先將int類型的2轉換為字符串類型(不能使用string(2)
的方式轉換,因為這種轉換方式不能跨大類型轉換,只能使用strconv
包中的函數轉換)。
另一種更高效的字符串串接方式是使用strings
包中的Join()函數,它可以在緩沖中將字符串串接起來。
字符串長度
使用len()取字節數量(不是字符數量)。
例如len("abcde")
返回5,size(我是中國人)
返回15。
字符串截取
可以將字符串當作數組,使用索引號取部分字符串(按字節計算),索引號從0開始計算,如"abcd"[1]
。
從字符串取字符的時候,需要注意的是index按字節計算而非按字符計算。兩種取數據方式:
"string"[x] "string"[x:y]
第一種方式將返回第(x+1)個字節對應字符的二進制數值,例如字母將轉換為ASCII碼,unicode將取對應字節的二進制轉換為數值。
第二種方式將返回第(x+1)字節到第y字節中間的字符,Go中采取"左閉右開"的方式,所以所截取部分包括index=x,但不包括index=y。
例如:
func main() { println("abcde"[1]) // (1).輸出"98" println("我是中國人"[1]) // (2).輸出"136" println("abcde"[0:2]) // (3).輸出"ab" println("我是中國人"[0:3]) // (4).輸出"我" println("abcde"[3:4]) // (5).輸出"d" }
分析每一行語句:
- (1).取第2個字節的二進制值,即字符b對應的值,其ASCII為98
- (2).取第2個字節的二進制值,因為中文占用3個字節,所以取第一個字符"我"的第二個字節部分,轉換為二進制值,為136
- (3).取第1個字節到第3個字節(不包括)中間的字符,所以輸出"ab"
- (4).取前三個字節對應的字符,所以輸出"我"
- (5).取第4個字節對應的字符,所以輸出d
字符串遍歷
字符串是字符數組,如果字符串中全是ASCII字符,直接遍歷即可,但如果包含了多字節字符,則可以[]rune(str)
轉換后后再遍歷。
package main import "fmt" func main() { str := "Hello 你好" r := []rune(str) // 8 for i := 0; i < len(r); i++ { fmt.Printf("%c", r[i]) } }
字符串比較
可以使用< <= > >= == !=
對字符串進行比較,它將一個字符一個字符地比對。字母以A-Za-z
的ASCII方式排列。
// 字符串比較 println("a" < "B") // false // 數值比較,不是字符串比較 println('a' == 97) // true
修改字符串
字符串是一個不可變對象,所以對字符串s截取后賦值的方式s[1]="c"
會報錯。
要想修改字符串中的字符,必須先將字符串拷貝到一個byte slice中,然后修改指定索引位置的字符,最后將byte slice轉換回string類型。
例如,將"gaoxiaofang"改為"maoxiaofang":
s := "gaoxiaofang" bs := []byte(s) bs[0] = 'm' // 必須使用單引號 s = string(bs) println(s)
注意修改字符的時候,必須使用單引號,因為它是byte類型。
布爾類型(bool)
bool類型的值只有兩種:true和false。
有3種布爾邏輯運算符:&& || !
,分別別是邏輯與,邏輯或,取反。
func main() { println(true && true) // true println(true && false) // false println(true || true) // true println(true || false) // true println(!true) // false }
Go是一門非常嚴格的怨言,在使用==
進行等值比較的時候,要求兩邊的數據類型必須相同,否則報錯。如果兩邊數據類型是接口類型,則它們必須實現相同的接口函數。如果是常量比較,則兩邊必須是能夠兼容的數據類型。
在printf類的函數的格式中,占位符%t
用于代表布爾值。
布爾類型的變量、函數名應該以is或Is的方式開頭來表明這是一個布爾類型的東西。例如isSorted()
函數用于檢測內容是否已經排序,IsFinished()
用于判斷是否完成。
type關鍵字:類型別名
可以使用type定義自己的數據類型,例如struct、interface。
還可以使用type定義類型的別名。例如,定義一個int類型的別名INT:
type INT int
這樣INT類型的底層數據結構還是int類型。可以將它和int一樣使用:
var a INT = 5
type中可以一次性聲明多個別名:
type ( CT int IT int32 DT float32 )
獲取數據類型
reflect包的TypeOf(),或者Printf/Sprintf的"%T"。
package main import ( "reflect" "fmt" ) type IT int32 func main() { var a IT = 322 var b = 22 fmt.Println(reflect.TypeOf(a)) // main.IT fmt.Println(reflect.TypeOf(b)) // int fmt.Println(fmt.Sprintf("%T", a)) // main.IT }
數據類型的大小
unsafe包的Sizeof()查看變量或常量所屬數據類型占用空間的大小。
package main import ( "unsafe" "fmt" ) type IT int32 func main() { var a IT = 322 var b = 22 fmt.Println(unsafe.Sizeof(a)) // 4 fmt.Println(unsafe.Sizeof(b)) // 8 }
原文鏈接:https://www.cnblogs.com/f-ck-need-u/p/9863563.html
相關推薦
- 2023-04-19 Android.bp語法和使用方法講解_Android
- 2024-02-01 mybatis plus 分頁查詢出現count()
- 2024-02-01 idea設置格式化豎線
- 2022-09-03 Python標準庫sys庫常用功能詳解_python
- 2022-11-01 詳解golang中的閉包與defer_Golang
- 2024-02-01 springboot @spring.active@啟動報錯
- 2022-10-01 如何使用draw.io插件在vscode中一體化導出高質量圖片_python
- 2022-04-24 Python元素集合的列表切片_python
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支