1. 程式人生 > 其它 >Golang語言社群--Go語言基礎第四節型別

Golang語言社群--Go語言基礎第四節型別

大家好,我是Golang語言社群主編彬哥,這節給大家講解Go語言中的型別。

Go語言中使用的型別包括:

基礎型別

布林型別(bool)

var b1 bool = true

整型

var v1 int = 12

浮點型別(float32、float64)

var f1 float32 = 12.0

複數型別(complex64、complex128)

var c1 complex64 = 3.2 + 12i

字串(string)

var s string = “sina”

字元型別(rune)

代表單個的unicode字元

錯誤型別(error)

複合型別

指標(pointer)

陣列(array)

[32] byte

切片(slice)

字典(map)

var word_count map[string] int

通道(chan)

用於協程間通訊

結構體(struct)

介面(interface)

1、布林型別

布林型別不能接受其它型別的賦值,不支援自動或強制的型別轉換,以下的示例是一些錯誤的用法:

var golang bool
golang = 1          // 錯誤
golang = bool(1)    // 錯誤

以下的用法是正確的:

var golang bool
golang = (1!=0)

2、整型

型別

長度

值範圍

int8

1

-128 ~ 127

uint8(即byte)

1

0 ~ 255

int16

2

-32768 ~ 32767

uint16

2

0 ~ 65535

int32

4

-2147483648 ~ 2147483647

uint32

4

0 ~ 4294967295

int64

8

(-2^63) ~ (2^63-1)

uint64

8

0 ~ (2^64-1)

int

平臺相關

平臺相關

uint

平臺相關

平臺相關

uintptr

同指針

32位平臺下為4位元組,64位平臺下為8位元組

需要注意的是,int和int32是不同的型別, 不能相互賦值,例如:

var val2 int32
val1 := 64     // val1會被自動推導為int型別
var2 = val1    // error
var2 = int32(val1)  // ok

此外,不同型別的整型數不能直接比較,比如int8型別的數和int型別的數不能直接比較,但各種型別的整型變數都可以直接與字面常量(literal)進行比較,比如:

var i int32
var j int64

i,j = 1,2 

if i==j {         // error
    fmt.Println("i and j are equal.") 
}

if i==1 || j==2 {     // ok
    fmt.Println("i and j are equal.") 
}   

3、浮點型

Go語言中的float32和float64分別等價於C語言的float、double型別;

var i float32 = 12.1 
j := 64.0      // 自動推導為float64型別
j = i        // error
j = float64(i)  // ok  

判斷兩個浮點數是否相等,是根據不同精度來的:

import "math"

func IsEqual(f1, f2, p float64) bool {
    return math.Fdim(f1, f2) < p
}

其中,p是使用者自定義的比較精度,比如p=0.00001。

4、字元型別

在Go語言中支援兩個字元型別,一個是byte(實際上是uint8的別名),代表UTF-8字串的單個位元組的值;另一個是rune,代表單個Unicode字元。

關於rune相關的操作,可查閱Go標準庫的unicode包;另外unicode/utf8包也提供了UTF8和Unicode之間的轉換。

5、字串

字串支援下標讀取操作:

str := "Hello world"
ch := str[0]
fmt.Printf("The length of "%s" is %dn", str, len(str))
fmt.Printf("The 1st character of "%s" is '%c'n", str, ch)

但字串的內容在初始化後不能被修改,例如:

str := "Hello world"
str[0] = 'X'    // error

常用的字串操作:

操作

含義

s1 + s2

字串連線

len(s)

字串長度

s[i]

取字元

字串遍歷有兩種方式:

str := "Hello,世界"

// 以位元組陣列的方式遍歷

for i := 0; i<len(str); i++ {
  ch := str[i]
  fmt.Println(i, ch)
}

 

// 以unicode字元方式遍歷,每個字元的型別是rune

for i, ch := range str {
  fmt.Println(i, ch) 
}

 

6、陣列

陣列的宣告方法比較多,比如:

[32] byte                // 位元組陣列
[2*N] struct {x, y int 32}     // 結構體陣列
[1000] *float64           // 指標陣列
[3][5] int             // 二維陣列
[2][2][2] float64   

在宣告陣列時長度可以為一個常量或一個常量表達式,陣列長度在定義以後就不可以再改變。

陣列支援按下標讀寫元素,也支援range關鍵字的遍歷,例如:

var array = [5] int {10,20,30,40,50}

for i, v := range array {
    array[i] = v*2;
}

for i, v := range array {
    fmt.Println(i, v) 
}

另外,陣列是值型別,如果將陣列作為函式引數傳遞,則在函式呼叫的時候該引數將發生資料複製,因此,在函式體中無法修改傳入的陣列的內容。

7、slice

陣列切片的資料結構可以抽象為以下3個變數:

  • 一個指向原生陣列的指標;
  • 陣列切片中的元素個數;
  • 陣列切片已分配的儲存空間;

陣列切片類似於C++中STL的std::vector<>,支援動態擴充套件陣列,並且可以被作為函式引數傳遞而不會導致元素被複制。

建立陣列切片有下面多種方式:

1、基於陣列建立的方式

var myArray [10] int = [10] int {1,2,3,4,5,6,7,8,9,10}

var s1 = myArray[:]    // 基於myArray的所有元素建立陣列切片
var s2 = myArray[:5]   // 基於myArray的前5個元素建立陣列切片
var s3 = myArray[5:]   // 基於myArray從第5個元素開始的所有元素建立陣列切片

2、直接建立陣列切片的方式

s1 := make([] int,5)    // 建立一個初始元素個數為5的陣列切片,元素初始值為0
s2 := make([] int,5, 10) // 建立一個初始元素個數為5的陣列切片,元素初始值為0,並預留10個元素的儲存空間
s3 := []int{1,2,3,4,5}  // 建立並初始化包含5個指定元素的陣列切片

3、基於陣列切片建立的方式

oldSlice := []int{1,2,3,4,5}
newSlice := oldSlice[:3]

運算元組元素的所有方法都適用於陣列切片,比如陣列切片也可以按下標讀寫元素,用len()獲取元素個數,並支援使用range關鍵字來快速遍歷所有元素。

陣列切片支援可動態增減元素,內建的cap()和len()函式,分別返回陣列切片分配的空間大小、當前儲存的元素個數。

s := make([] int,5, 10)
fmt.Println("len(s)=",len(s))   // 5
fmt.Println("cap(s)=",cap(s))   // 10

使用append函式可以在陣列切片尾端新增新元素:

s = append(s, 1,2,3)

如果追加的內容長度超過當前已分配的儲存空間(即cap()返回值),陣列切片會自動分配一塊足夠大的記憶體。

還可以將另一個數組切片追加到一個數組切片末端:

s2 := []int{8,9,10}
s = append(s, s2...)  // s2後面的省略號必須要有

陣列切片的複製,如果兩個slice不一樣大,就會按其中較小的slice的元素個數進行復制,例如:

s1 := []int {1,2,3,4,5}
s2 := []int {5,4,7}
copy(s1, s2)  //只複製s2的3個元素到s1的前3個位置
copy(s2, s1)  //只複製s1的前3個元素到s2中

8、map

map是key-value結構的一個字典,類似於C++中STL的std::map<>。

例子:

type PersonInfo struct {
    ID string
    Name string
    Address string
}


func main() {
    var personDB map[string] PersonInfo      // 變數宣告
    personDB = make(map[string] PersonInfo)    // 變數建立

    personDB["1"] = PersonInfo{"12345","Tom","Room 203"}  // 增加了一個鍵

    person, ok := personDB["1"]                // 查詢
    if ok {
        fmt.Println("found person", person.Name, "with ID 1")
    } else {
        fmt.Println("Did not find person with ID 1")
    }

  delete(personDB, "1")        // 刪除一個鍵
}