Go 語言基本資料型別
1、Golang 資料型別介紹
Go 語言中資料型別分為:基本資料型別和複合資料型別
基本資料型別有:
整型、浮點型、布林型、字串
複合資料型別有:
陣列、切片、結構體、函式、map、通道(channel)、介面等。
2、整型
整型分為以下兩個大類:
有符號整形按長度分為:int8、int16、int32、int64
對應的無符號整型:uint8、uint16、uint32、uint64
關於位元組:
位元組也叫 Byte,是計算機資料的基本儲存單位。
8bit(位)=1Byte(位元組)
1024Byte(位元組)=1KB
1024KB=1MB
1024MB=1GB
1024GB=1TB
在電腦裡一箇中文字是佔兩個位元組的。
特殊整型
型別 | 描述 |
---|---|
uint | 32 位作業系統上就是 uint32,64 位作業系統上就是 uint64 |
int | 32 位作業系統上就是 int32,64 位作業系統上就是 int64 |
uintptr | 無符號整型,用於存放一個指標 |
注意: 在使用 int 和 uint 型別時,不能假定它是 32 位或 64 位的整型,而是考慮 int 和 uint可能在不同平臺上的差異。
注意事項:實際專案中整數型別、切片、 map 的元素數量等都可以用 int 來表示。在涉及到二進位制傳輸、為了保持檔案的結構不會受到不同編譯目標平臺位元組長度的影響,不要使
用 int 和 uint。
package main
import (
"fmt"
)
func main() {
var num int64
num = 123
fmt.Printf("值:%v 型別%T", num, num)
}
unsafe.Sizeof
unsafe.Sizeof(n1) 是 unsafe 包的一個函式,可以返回 n1 變數佔用的位元組數
package main
import (
"fmt"
"unsafe"
)
func main() {
var a int8 = 120
fmt.Printf("%T\n", a)
fmt.Println(unsafe.Sizeof(a))
}
int 不同長度直接的轉換
package main
import (
"fmt"
)
func main() {
var num1 int8
num1 = 127
num2 := int32(num1)
fmt.Printf("值:%v 型別%T", num2, num2) //值:127 型別 int32
}
數字字面量語法(Number literals syntax)(瞭解)
Go1.13 版本之後引入了數字字面量語法,這樣便於開發者以二進位制、八進位制或十六進位制浮點數的格式定義數字,例如:
v := 0b00101101, 代表二進位制的 101101,相當於十進位制的 45。 v := 0o377,代表八進位制的377,相當於十進位制的 255。 v := 0x1p-2,代表十六進位制的 1 除以 2²,也就是 0.25。 而且還允許我們用 _ 來分隔數字,比如說:
v := 123_456 等於 123456。
我們可以藉助 fmt 函式來將一個整數以不同進位制形式展示。
package main
import "fmt"
func main(){
// 十進位制
var a int
a = 10
fmt.Printf("%d \n", a) // 10
fmt.Printf("%b \n", a) // 1010 佔位符%b 表示二進位制
// 八進位制 以 0 開頭
var b int
b = 077
fmt.Printf("%o \n", b) // 77
// 十六進位制 以 0x 開頭
var c int
c = 0xff
fmt.Printf("%x \n", c) // ff
fmt.Printf("%X \n", c) // FF
fmt.Printf("%d \n", c) // 255
}
參考: http://docscn.studygolang.com/pkg/fmt/
3、浮點型
Go 語言支援兩種浮點型數:float32 和 float64。這兩種浮點型資料格式遵循 IEEE 754 標準:float32 的浮點數的最大範圍約為 3.4e38,可以使用常量定義:math.MaxFloat32。float64 的浮數的最大範圍約為 1.8e308,可以使用一個常量定義:math.MaxFloat64。
列印浮點數時,可以使用 fmt 包配合動詞%f,程式碼如下:
package main
import (
"fmt"
"math"
)
func main() {
fmt.Printf("%f\n", math.Pi) //預設保留 6 位小數
fmt.Printf("%.2f\n", math.Pi) //保留 2 位小數
}
Go 語言中浮點數預設是 float64
num := 1.1
fmt.Printf("值:%v--型別:%T", num, num) //值:1.1--型別:float64
Golang 中 float 精度丟失問題
幾乎所有的程式語言都有精度丟失這個問題,這是典型的二進位制浮點數精度損失問題,在定長條件下,二進位制小數和十進位制小數互轉可能有精度丟失。
d := 1129.6
fmt.Println((d * 100)) //輸出:112959.99999999999
var d float64 = 1129.6
fmt.Println((d * 100)) //輸出:112959.99999999999
m1 := 8.2
m2 := 3.8
fmt.Println(m1 - m2) // 期望是 4.4,結果列印出了 4.399999999999999
使用第三方包來解決精度損失問題:https://github.com/shopspring/decimal
Golang 科學計數法表示浮點型別
num8 := 5.1234e2 // ? 5.1234 * 10 的 2 次方
num9 := 5.1234E2 // ? 5.1234 * 10 的 2 次方 shift+alt+向下的箭頭
num10 := 5.1234E-2 // ? 5.1234 / 10 的 2 次方 0.051234
fmt.Println("num8=", num8, "num9=", num9, "num10=", num10)
4、布林值
Go 語言中以 bool 型別進行宣告布林型資料,布林型資料只有 true(真)和 false(假)兩個值。
注意:
-
布林型別變數的預設值為 false。
-
Go 語言中不允許將整型強制轉換為布林型. 3. 布林型無法參與數值運算,也無法與其他型別進轉換。
package main
import (
"fmt"
"unsafe"
)
func main() {
var b = true
fmt.Println(b, "佔用位元組:", unsafe.Sizeof(b))
}
5、字串
Go 語言中的字串以原生資料型別出現,使用字串就像使用其他原生資料型別(int、bool、float32、float64 等)一樣。 Go 語言裡的字串的內部實現使用 UTF-8 編碼。 字串的值為雙引號(")中的內容,可以在 Go 語言的原始碼中直接新增非 ASCII 碼字元,例如:
s1 := "hello"
s2 := "你好"
字串轉義符
Go 語言的字串常見轉義符包含回車、換行、單雙引號、製表符等,如下表所示。
轉義符 | 含義 |
---|---|
\r | 回車符(返回行首) |
\n | 換行符(直接跳到下一行的同列位置) |
\t | 製表符 |
' | 單引號 |
" | 雙引號 |
\ | 反斜槓 |
舉個例子,我們要列印一個 Windows 平臺下的一個檔案路徑:
package main
import (
"fmt"
)
func main() {
fmt.Println("str := \"c:\\Code\\demo\\go.exe\"")
}
多行字串
Go 語言中要定義一個多行字串時,就必須使用反引號字元:
s1 := `第一行
第二行
第三行
`
fmt.Println(s1)
反引號間換行將被作為字串中的換行,但是所有的跳脫字元均無效,文字將會原樣輸出。
字串的常用操作
方法 | 介紹 |
---|---|
len(str) | 求長度 |
+或 fmt.Sprintf | 拼接字串 |
strings.Split | 分割 |
strings.contains | 判斷是否包含 |
strings.HasPrefix,strings.HasSuffix | 字首/字尾判斷 |
strings.Index(),strings.LastIndex() | 子串出現的位置 |
strings.Join(a[]string, sep string) | join操作 |
len(str)求字串的長度
var str = "this is str"
fmt.Println(len(str))
拼接字串
var str1 = "你好"
var str2 = "golang"
fmt.Println(str1 + str2)
var str3 = fmt.Sprintf("%v %v", str1, str2)
fmt.Println(str3)
strings.Split 分割字串
var str = "123-456-789"
var arr = strings.Split(str, "-")
fmt.Println(arr)
拼接字串
var str = "this is golang"
var flag = strings.Contains(str, "golang")
fmt.Println(flag)
判斷首字元尾字母是否包含指定字元
var str = "this is golang"
var flag = strings.HasPrefix(str, "this")
fmt.Println(flag)
var str = "this is golang"
var flag = strings.HasSuffix(str, "go")
fmt.Println(flag)
判斷字串出現的位置
var str = "this is golang"
var index = strings.Index(str, "is") //從前往後
fmt.Println(index)
var str = "this is golang"
var index = strings.LastIndex(str, "is") //從後網前
fmt.Println(index)
Join 拼接字串
var str = "123-456-789"
var arr = strings.Split(str, "-")
var str2 = strings.Join(arr, "*")
fmt.Println(str2)
6、byte 和 rune 型別
組成每個字串的元素叫做“字元”,可以透過遍歷字串元素獲得字元。 字元用單引號(’)包裹起來,如:
package main
import "fmt"
func main() {
a := 'a' b := '0' //當我們直接輸出 byte(字元)的時候輸出的是這個字元對應的碼值
fmt.Println(a)
fmt.Println(b)
//如果我們要輸出這個字元,需要格式化輸出
fmt.Printf("%c--%c", a, b) //%c 相應 Unicode 碼點所表示的字元
}
位元組(byte):是計算機中 資料處理 的基本單位,習慣上用大寫 B 來表示,1B(byte,位元組)= 8bit(位)
字元:是指計算機中使用的字母、數字、字和符號
一個漢子佔用 3 個位元組 一個字母佔用一個位元組
a := "m"
fmt.Println(len(a)) //1
b := "張"
fmt.Println(len(b)) //3
Go 語言的字元有以下兩種:
- uint8 型別,或者叫 byte 型,代表了 ASCII 碼的一個字元。
- rune 型別,代表一個 UTF-8 字元。
當需要處理中文、日文或者其他複合字元時,則需要用到 rune 型別。rune 型別實際是一個int32。
Go 使用了特殊的 rune 型別來處理 Unicode,讓基於 Unicode 的文字處理更為方便,也可以使用 byte 型進行預設字串處理,效能和擴充套件性都有照顧。
// 遍歷字串
package main
import "fmt"
func main() {
s := "hello 張三"
for i := 0; i < len(s); i++ { //byte
fmt.Printf("%v(%c) ", s[i], s[i])
}
fmt.Println()
for _, r := range s { //rune
fmt.Printf("%v(%c) ", r, r)
}
fmt.Println()
}
輸出:
104(h) 101(e) 108(l) 108(l) 111(o) 32( ) 229(å) 188(¼) 160( ) 228(ä) 184(¸) 137()
104(h) 101(e) 108(l) 108(l) 111(o) 32( ) 24352(張) 19977(三)
因為 UTF8 編碼下一個中文漢字由 3 個位元組組成,所以我們不能簡單的按照位元組去遍歷一個包含中文的字串,否則就會出現上面輸出中第一行的結果。
字串底層是一個 byte 陣列,所以可以和[]byte 型別相互轉換。字串是不能修改的 字串是由 byte 位元組組成,所以字串的長度是 byte 位元組的長度。 rune 型別用來表示 utf8 字元,一個 rune 字元由一個或多個 byte 組成。
rune 型別實際是一個 int32
c3 := "營"
c4 := '營'
fmt.Printf("C3 的型別%T--C4 的型別%T", c3, c4) //C3 的型別 string--C4 的型別 int32
7、修改字串
要修改字串,需要先將其轉換成[]rune 或[]byte,完成後再轉換為 string。無論哪種換,都會重新分配記憶體,並複製位元組陣列。
func changeString() {
s1 := "big"
// 強制型別轉換
byteS1 := []byte(s1)
byteS1[0] = 'p' fmt.Println(string(byteS1))
s2 := "白蘿蔔"
runeS2 := []rune(s2)
runeS2[0] = '紅' fmt.Println(string(runeS2))
}