6.Go語言基本資料型別

BUG弄潮儿發表於2024-03-23

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))
}

相關文章