1. 程式人生 > >Go語言資料型別

Go語言資料型別

目錄

Go 語言是一種靜態型別的程式語言,在 Go 程式語言中,資料型別用於宣告函式和變數。資料型別的出現是為了把資料分成所需記憶體大小不同的資料,程式設計的時候需要用大資料的時候才需要申請大記憶體,就可以充分利用記憶體。編譯器在進行編譯的時候,就要知道每個值的型別,這樣編譯器就知道要為這個值分配多少記憶體,並且知道這段分配的記憶體表示什麼。

基本資料型別說明

型別 描述
uint 32位或64位
uint8 無符號 8 位整型 (0 到 255)
uint16 無符號 16 位整型 (0 到 65535)
uint32 無符號 32 位整型 (0 到 4294967295)
uint64 無符號 64 位整型 (0 到 18446744073709551615)
int 32位或64位
int8 有符號 8 位整型 (-128 到 127)
int16 有符號 16 位整型 (-32768 到 32767)
int32 有符號 32 位整型 (-2147483648 到 2147483647)
int64 有符號 64 位整型 (-9223372036854775808 到 9223372036854775807)
byte 類似 uint8
rune 類似 int32,表示一個unicode碼
uintptr 無符號整型,用於存放一個指標是一種無符號的整數型別,沒有指定具體的bit大小但是足以容納指標。 uintptr型別只有在底層程式設計是才需要,特別是Go語言和C語言函式庫或作業系統介面相互動的地方。
float32 IEEE-754 32位浮點型數
float64 IEEE-754 64位浮點型數
complex64 32 位實數和虛數
complex128 64 位實數和虛數

整型

整型資料分為兩類,有符號無符號兩種型別

有符號: int, int8, int16, int32, int64

無符號: uint, uint8, uint16, uint32, uint64, byte 不同位數的整型區別在於能儲存整型數字範圍的大小;

有符號型別可以儲存任何整數,無符號型別只能儲存自然數

int和uint的大小和系統有關,32位系統表示int32和uint32,如果是64位系統則表示int64和uint64

byte與uint8類似,一般用來儲存單個字元

在保證程式正確執行下,儘量使用佔用空間小的資料型別

fmt.Printf("%T", var_name)輸出變數型別

unsafe.Sizeof(var_name)檢視變數佔用位元組

浮點型

浮點型也就是小數型別,可以存放小數。比如6.6,-12.34

  1. 關於浮點數在機器中存放形式的簡單說明,浮點數=符號位+指數位+尾數位

  2. 尾數部分可能丟失,造成精度損失。-123.0000901

    package main
    
    import "fmt"
    
    func main() {
    
        var num1 float32 = -123.0000901
        var num2 float64 = -123.0000901
        fmt.Println("num1 = ", num1, "num2 = ", num2);
    }

    說明:float64的精度要比float32的要準確

    說明:如果我們要儲存一個精度高的書,則應該選擇float64

  3. 浮點型的儲存分為三部分:符號位+指數位+尾數位,在儲存過程中,精度會有丟失

  4. golang的浮點型預設為float64型別

  5. 通常情況下,應該使用float64,因為它比float32更精確

  6. 0.123可以簡寫成.123,也支援科學計數法表示:5.1234e2 等價於512.34

字元

Golang中沒有專門的字元型別,如果要儲存單個字元(字母),一般使用byte來儲存。

字串就是一串固定長度的字元連線起來的字元序列。Go的字串是由單個位元組連線起來的,也就是說對於傳統的字串是由字元組成的,而Go的字串不同,它是由位元組組成的

  • 字元只能被單引號包裹,不能用雙引號,雙引號包裹的是字串
  • 當我們直接輸出type值時,就是輸出了對應字元的ASCII碼值
  • 當我們希望輸出對應字元,需要使用格式化輸出
  • Go語言的字元使用UTF-8編碼,英文字母佔一個字元,漢字佔三個字元
  • 在Go中,字元的本質是一個整數,直接輸出時,是該字元對應的UTF-8編碼的碼值。
  • 可以直接給某個變數賦一個數字,然後按格式化輸出時%c,會輸出該數字對應的unicode字元
  • 字元型別是可以運算的,相當於一個整數,因為它們都有對應的unicode碼
package main

import "fmt"

func main() {
    
    //字元只能被單引號包裹,不能用雙引號,雙引號包裹的是字串
    var c1 byte = 'a'
    var c2 byte = '0'

    //當我們直接輸出type值時,就是輸出了對應字元的ASCII碼值
    //'a' ==> 97
    fmt.Println(c1, "--", c2)
    //如果我們希望輸出對應字元,需要使用格式化輸出
    fmt.Printf("c2 = %c c2 = %c", c1, c2)
}

但是如果我們儲存的字元大於255,比如儲存漢字,這時byte型別就無法儲存,此時可以使用uint或int型別儲存

字元型別本質探討

  1. 字元型儲存到計算機中,需要將字元對應的碼值(整數)找出來

    儲存:字元 --> 碼值 --> 二進位制 --> 儲存

    讀取: 二進位制 -->碼值 --> 字元 --> 讀取

  2. 字元和碼值的對應關係是通過字元編碼表決定的(是規定好的)

  3. Go語言的編碼都統一成了UTF-8。非常的方便,很統一,再也沒有編碼亂碼的困擾了

布林型

布林型別也叫做bool型別,bool型別資料只允許取值true或false

bool型別佔1個位元組

bool型別適用於邏輯運算,一般用於流程控制

字串

字串就是一串固定長度的字元連線起來的字元序列。Go的字串是由單個位元組連線起來的。Go語言的字串的位元組使用UTF-8編碼標識Unicode文字

  1. 字串一旦賦值了,就不能修改了:在Go中字串是不可變的。

  2. 字串的兩種標識形式

    • 雙引號,會識別轉義字元

      var str = "abc\nabc" //輸出時會換行
    • 反引號,以字串的原生形式輸出,包括換行和特殊字元,可以實現防止攻擊、輸出原始碼等效果

      var str string = `abc\nabc` //輸出時原樣輸出,不會轉義
  3. 字串拼接方式"+"

    var str string = "hello " + "world"
    str += "!"
  4. 當一行字串太長時,需要使用到多行字串,可以使用如下處理

    //正確寫法
    str := "hello" + 
     " world!"
    fmt.Println(str)
    
    //錯誤寫法
    str := "hello "
     + "world!"
    fmt.Println(str)

指標

  1. 基本資料型別,變數存的就是值,也叫值型別
  2. 獲取變數的地址,用&,比如var num int,獲取num的地址:&num
  3. 指標型別,指標變數存的是一個地址,這個地址指向的空間存的才是值,比如:var ptr *int = &num
  4. 獲取指標型別所指向的值,使用:*,比如,var ptr *int,使用*ptr獲取ptr指向的值

指標細節說明:

  1. 值型別,都有對應的指標型別,形式為*資料型別,比如int對應的指標就是*int,float64對應的指標型別就是*float64,依此類推。
  2. 值型別包括:基本資料型別陣列結構體struct

值型別與引用型別

值型別和引用型別使用特點:

值型別:變數直接儲存值,記憶體通常在中分配

引用型別:變數儲存的是一個地址,這個地址對應的空間才真正儲存資料(值),記憶體通常在上分配,當沒有任何變數應用這個地址時,該地址對應的資料空間就成為一個垃圾,由GC來回收。

Golang中值型別和引用型別的區分

  1. 值型別:基本資料型別(int系列、float系列、bool、string)、陣列和結構體
  2. 引用型別:指標、slice切片、map、管道chan、interface等都是引用型別

基本資料型別預設值

在Golang中,資料型別都有一個預設值,當程式設計師沒有賦值時,就會保留預設值,在Golang中,預設值也叫做零值。

基本資料型別預設值如下:

資料型別 預設值
整型 0
浮點型 0
字串 ""
布林型別 false
package main

import "fmt"

func main() {
    
    var a int
    var b float32
    var isTrue bool
    var str string

    //這裡的%v,表示按照變數的值輸出
    fmt.Printf("a = %v, b = %v, isTrue = %v, str = %v", a, b, isTrue, str)
    fmt.Println("")
}

基本資料型別相互轉換

Golang和Java/C不同,Golang在不同型別的變數之間賦值時需要顯式轉換。也就是Golang中資料型別不能自動轉換

基本語法:

表示式var_type(var_name) 將值v轉換為型別var_type

var_type:就是資料型別,比如int32, int64, float32等等

var_name:就是需要轉換的變數

var num int = 42
var float float64 = float64(num)
var ui uint8 = uint8(float)
fmt.Println(num, float, ui)

注意事項

  1. Go中,資料型別的轉換可以是從表示範圍小-->表示範圍大,也可以 範圍大—>範圍小

  2. 被轉換的是變數儲存的資料(即值),變數本身的資料型別並沒有變化!

  3. 在轉換中,比如將int64轉成int8,編譯時不會報錯,只是轉換的結果是按溢位處理,和我們希望的結果不一樣。

  4. 資料的轉換必須顯式轉換,不能自動轉換

    package main
    import "fmt"
    
    func main() {
    
        var n1 int32 = 12
        var n2 int64
        var n3 int8
    
        n2 = n1 + 20 //int32  --> int64  錯誤
        n3 = n1 + 20 //int32  --> int8   錯誤
    
        n2 = int64(n1) + 20 //正確
        n3 = int8(n1) + 20  //正確
    }
  5. 定義一個int8型別的整數(var num int8 = 0),如果一直自加1,這個變數的值會是(0...127 -128 -127... 0 ...127)迴圈往復下去,而不會超過型別最大值得範圍

其他基本型別轉string型別

在程式開發中,我們經常需要將數值型轉成string型別,或者將string型別轉成數值型。

方式1:

func Sprintf(format string, a ...interface{}) string

Sprintf根據format引數生成格式化的字串並返回該字串。

package main

import "fmt"

func main() {
    
    var num1 int = 99;
    var num2 float64 = 23.456
    var isTrue bool = true 
    var char byte = 'A'

    var str string

    str = fmt.Sprintf("%d", num1)
    fmt.Printf("str型別為 %T str = %q\n",str, str)

    str = fmt.Sprintf("%f", num2)
    fmt.Printf("str型別為 %T str = %q\n",str, str)

    str = fmt.Sprintf("%t", isTrue)
    fmt.Printf("str型別為 %T str = %q\n",str, str)

    str = fmt.Sprintf("%d", char)
    fmt.Printf("str型別為 %T str = %q\n",str, str)
}

輸出結果為

str型別為 string str = "99"
str型別為 string str = "23.456000"
str型別為 string str = "true"
str型別為 string str = "65"

方式2:使用strconv包的函式

package main

import (
    "fmt"
    "strconv"
)

func main() {
    
    var num1 int = 99;
    var num2 float64 = 23.456
    var isTrue bool = true 

    var str string

    str = strconv.FormatInt(int64(num1), 10)
    str = strconv.Itoa(num1)
    fmt.Printf("str型別為 %T str = %q\n",str, str)

    str = strconv.FormatFloat(num2, 'f', 10, 64)
    fmt.Printf("str型別為 %T str = %q\n",str, str)

    str = strconv.FormatBool(isTrue)
    fmt.Printf("str型別為 %T str = %q\n",str, str)
}

輸出結果為

str型別為 string str = "99"
str型別為 string str = "23.4560000000"
str型別為 string str = "true"

string型別轉其他基本型別

方式1:使用strconv包的函式

package main

import (
    "fmt"
    "strconv"
)

func main() {
    
    var str string = "true"
    var str1 string = "123456"
    var str2 string = "123.456"

    var isTrue bool
    var num int64
    var num2 float64

    isTrue, _ = strconv.ParseBool(str)
    fmt.Printf("str型別為 %T str = %v\n",isTrue, isTrue)

    num, _ = strconv.ParseInt(str1, 10, 64)
    fmt.Printf("str型別為 %T str = %v\n",num, num)

    num2, _ = strconv.ParseFloat(str2, 64)
    fmt.Printf("str型別為 %T str = %v\n",num2, num2) 

}

資料結果為:

str型別為 bool str = true
str型別為 int64 str = 123456
str型別為 float64 str = 123.456

注意:在將string型別轉成其它基本資料型別時,要確保string型別能夠轉成有效的資料。比如,我們可以把”123“轉成數字123,但是不能把”hello“轉成一個整數,如果這樣做,Golang直接將其轉成0,其它型別也是一樣的道理,float => 0, bool => false