1. 程式人生 > 實用技巧 >Go語言系列-02-常用資料型別

Go語言系列-02-常用資料型別

Go語言常用資料型別

Go 語言中有豐富的資料型別,除了基本的整型、浮點型、布林型、字串、byte/rune 之外,

還有陣列、切片、函式、map、通道(channel)、結構體等。

Go語言的基本型別和其他語言大同小異。

整型

整型分為:有符號整型、無符號整型

其中比較特殊的整型資料型別有3個

  • unit 無符號整型,它在32位的作業系統上就是uint32,在64位的作業系統上就是uint64

  • int 有服號整型, 它在32位的作業系統上就是nit32,在64位的作業系統上就是int64

  • uintptr 無符號整型,用於存放一個指標

    在使用 intuint 型別時,不能假定他是32位或是64位的整型型別,而是要考慮程式可能執行在不同的平臺上,導致資料位數不一樣。所以,為了保持檔案的結構不會受到不同的平臺的影響,建議不要使用 int

    uint

有符號整形

  • int、int8、int16、int32、int64 都屬於有符號整型的資料型別

無符號整型

  • uint、uint8、uint16、uint32、uint64 都屬於無符號整型的資料型別

整型資料練習,資料型別轉換

package main

import "fmt"

func main() {
	// 十進位制
	var i1 = 101
	fmt.Println("--- 十進位制 ---")
	fmt.Printf("%d\n", i1) // 十進位制
	fmt.Printf("%b\n", i1) // 十進位制 -> 二進位制
	fmt.Printf("%o\n", i1) // 十進位制 -> 八進位制
	fmt.Printf("%x\n", i1) // 十進位制 -> 十六進位制

	// 八進位制
	i2 := 077
	fmt.Println("--- 八進位制 ---")
	fmt.Printf("%d\n", i2) // 八進位制 -> 十進位制

	// 十六進位制
	i3 := 0x123456f
	fmt.Println("--- 十六進位制 ---")
	fmt.Printf("%d\n", i3) // 十六進位制 -> 十進位制
	fmt.Printf("%x\n", i3) // 十六進位制

	// 檢視變數型別
	fmt.Println("--- 檢視變數型別 ---")
	fmt.Printf("%T\n", i3) // 如果不指定資料型別,那麼預設則為int型別
	// 宣告int8型別的變數
	i4 := int8(9) // 明確指定int8型別,否則預設就是int型別
	fmt.Printf("%T\n", i4)
}
lichengguo@lichengguodeMacBook-Pro % go run main.go
--- 十進位制 ---
101
1100101
145
65
--- 八進位制 ---
63
--- 十六進位制 ---
19088751
123456f
--- 檢視變數型別 ---
int
int8

浮點型

浮點型分為 float32float64 兩種型別

  • float32
  • float64

浮點型別比較簡單,不多說,直接看程式碼

package main

import (
	"fmt"
	"math"
)

//浮點數

func main() {
	// math.MaxFloat32 float32最大值
	// math.MaxFloat64 float64最大值
	fmt.Println("--- 1. 浮點型最大值 ---")
	fmt.Println(math.MaxFloat32)
	fmt.Println(math.MaxFloat64)

	fmt.Println("---- 2.  -------")
	f1 := 1.23456189         // float64 型別
	fmt.Printf("%T\n", f1)   // 預設Go語言中的小數都是 float64 型別
	fmt.Printf("%f\n", f1)   // 1.234562 預設只打印小數點後六位,會採取進一法保留六位小數
	fmt.Printf("%.2f\n", f1) // 保留2位小數 1.23 會採用四捨五入保留2位小數

	fmt.Println("---- 3. float32 ----")
	f2 := float32(1.23456) // float32 型別
	fmt.Printf("%T\n", f2) // 顯示宣告 float32 型別
	// float32 型別的值不能直接賦值給 float64 型別的變數
	// f1 = f2 // 會報錯

	fmt.Println("---- 4. ----")
	// 同類型的可以直接賦值
	f3 := 1.2 // float64 型別
	f1 = f3
	fmt.Println(f1)
	fmt.Printf("%T\n", f1)
	fmt.Printf("%T\n", f3)
}

執行結果

lichengguo@lichengguodeMacBook-Pro % go run main.go
--- 1. 浮點型最大值 ---
3.4028234663852886e+38
1.7976931348623157e+308
---- 2.  -------
float64
1.234562
1.23
---- 3. float32 ----
float32
---- 4. ----
1.2
float64
float64

布林型

Go語言中以 bool 型別進行宣告布林型資料,布林型資料只有 truefalse 兩個值

  • 布林型別變數的預設值是 false
  • Go語言不允許將 整型 強制轉換為 布林型
  • 布林型無法參與數值運算,也無法與其他型別進行轉化
package main

import (
	"fmt"
)

func main() {
	b1 := true
	var b2 bool // 預設是false
	fmt.Printf("%T\n", b1)
	fmt.Printf("%T value:%v\n", b2, b2)
}

執行結果

lichengguo@lichengguodeMacBook-Pro day01 % go run main.go
bool
bool value:false

字串

Go語言中 字串 是用 雙引號" " 包裹的,用 單引號' ' 包裹的是 字元,Go語言裡的字串內部實現使用的是**UTF8 **編碼

  • ASCII編碼中: 一個字元 'A' 佔用1個位元組(Byte)

  • UTF8編碼中: 一個字元 'A' 佔用1個位元組(Byte),一個漢字 '中' 一般佔用3個位元組(Byte)

  • 小知識:

    ​ 1位元組(Byte) = 8bit (8個二進位制位)

    ​ 1024位元組(Byte) = 1KB

字串和字元這兩者之間的區別

字串

  • 雙引號
  • 字串有一個或者多個 字元 組成
  • 字串都是隱藏了一個結束符:\0

字元

  • 單引號
  • 往往只包含一個字元,轉義字元除外,如\n

下面通過程式碼具體來看一下

package main

import (
	"fmt"
)

func main() {
	// 字元
	fmt.Println("---- 1. 字元 ----")
	ch := 'a' // 簡短宣告變數並且賦值
	fmt.Println("ch =", ch)
	fmt.Printf("%T\n", ch)

	// 字串
	fmt.Println("---- 2. 字串 ----")
	s1 := "a"
	fmt.Println("s1 =", s1)
	fmt.Printf("%T\n", s1)
}

執行結果

從結果可以看出,字元型別本質上是一個int32 型別

lichengguo@lichengguodeMacBook-Pro day01 % go run main.go
---- 1. 字元 ----
ch = 97  // ASCII編碼97對應的是小寫字母a
int32
---- 2. 字串 ----
s1 = a
string

轉義符 \

package main

import (
	"fmt"
)

func main() {
	// \ 反斜槓是具有特殊含義的,應該告訴程式寫的 \ 就是一個單純的 \
	// path := "D:\\Go\\src\\studygo\\day01"
	// path := "'D:\\Go\\src\\studygo\\day01'"
	path := "\"D:\\Go\\src\\studygo\\day01\""
	fmt.Println(path)
}

多行字串

package main

import (
	"fmt"
)

func main() {
	// 多行字串
	s2 := `
	aaa
bbb
		ccc
	`
	fmt.Println(s2)

	s3 := `D:\Go\src\code.oldboyedu.com\studygo\day01`
	fmt.Println(s3)
}

字串的一些常用操作

package main

import (
	"fmt"
	"strings"
)

func main() {
	// 字串相關操作
	// 1. 統計位元組數
	fmt.Println("---- 1. 統計位元組數 ----")
	s1 := "hello中國"
	// 注意 len函式 統計字串的時候,是統計【位元組數長度】,而不是字元的個數
	// 在utf8編碼中,一個英文字元佔用1個位元組,一箇中文字元一般佔用3個位元組
	fmt.Println(len(s1)) // 此處的11是位元組數長度,而不是字元的個數

	// 2. 字串拼接
	fmt.Println("---- 2. 字串拼接 ----")
	name := "tom"
	world := "dsb"
	ss := name + world                         // 拼接方式1
	fmt.Println(ss)                            // tomdsb
	ss1 := fmt.Sprintf("%s - %s", name, world) // 拼接方式2
	fmt.Println(ss1)                           // tom - dsb

        // 3. strings包相關操作
	fmt.Println("---- 3. strings包相關操作 ----")
	
	// 3.1 分割
	fmt.Println("---- 3.1 分割 ----")
	s3 := `D:\Go\src\studygo\day01`
	ret := strings.Split(s3, "\\") // 注意這裡的 \\ 前面的反斜槓是為了不讓後面的反斜槓具有特殊意義
	fmt.Println(ret)               // [D: Go src studygo day01]

	// 3.2 包含
	fmt.Println("---- 3.2 包含 ----")
	fmt.Println(strings.Contains(ss, "dsb")) // true

	// 3.3 字首
	fmt.Println("---- 3.3 字首 ----")
	fmt.Println(strings.HasPrefix(ss, "tom")) // true

	// 3.4 字尾
	fmt.Println("---- 3.4 字尾 ----")
	fmt.Println(strings.HasSuffix(ss, "dsb")) // true

	// 3.5 查詢字串出現的索引
	fmt.Println("---- 3.5 查詢字串出現的索引 ----")
	s5 := "abcdeb"
	fmt.Println(strings.Index(s5, "c"))       // 2 從0開始計數
	fmt.Println(strings.LastIndex(s5, "eb"))  // 4

	// 單獨的字母、漢字、符號並且用單引號括起來的表示一個字元
	// 雙引號的是字串了
	fmt.Println("-----------------------------")
	s6 := 'c'
	fmt.Printf("s6: %T\n", s6)  // int32
	s7 := '中'
	fmt.Printf("s7: %T\n", s7)  // int32  
	s8 := "c"
	fmt.Printf("s8: %T\n", s8)  // string

	// 3.6 切片拼接
	fmt.Println("---- 3.6 切片拼接 ----")
	fmt.Println(strings.Join(ret, "+"))  // D:+Go+src+studygo+day01
}

lichengguo@lichengguodeMacBook-Pro day01 % go run main.go 
---- 1. 統計位元組數 ----
11
---- 2. 字串拼接 ----
tomdsb
tom - dsb
---- 3. strings包相關操作 ----
---- 3.1 分割 ----
[D: Go src studygo day01]
---- 3.2 包含 ----
true
---- 3.3 字首 ----
true
---- 3.4 字尾 ----
true
---- 3.5 查詢字串出現的索引 ----
2
4
-----------------------------
s6: int32
s7: int32
s8: string
---- 3.6 切片拼接 ----
D:+Go+src+studygo+day01

byte和rune

Go語言中的 字元 有兩種資料型別

  • uint8型別,或者叫做 byte 型別,代表了ASCII編碼的一個字元
  • rune型別,代表了UTF-8編碼的一個字元

當需要處理中文、日文等其他複合字符時,則需要用到rune型別。rune型別實際上就是一個int32型別

遍歷字串

package main

import (
	"fmt"
)

// Go語言裡的字串內部實現使用的是UTF8編碼

func main() {
	s := "Hello中國"
	n := len(s)    // len 的結果是位元組的長度,而不是字元的數量
	fmt.Println(n) // 11

	// 遍歷字串
	// Go語言裡的字串內部實現使用的是UTF8編碼,而rune型別,代表了UTF8編碼的一個[字元]
	s1 := []rune(s)                 // 轉換成rune型別的切片
	fmt.Println("s1:", s1, len(s1)) // s1: [72 101 108 108 111 228 184 173 229 155 189] 7
	for i := 0; i < len(s1); i++ {
		fmt.Printf("%c", s1[i]) // %c 字元
	}
	fmt.Println()

	// 下面這種方法會亂碼
	for i := 0; i < len(s); i++ {
		fmt.Printf("%c", s[i])
	}
	fmt.Println()

	// 使用range這種方式去遍歷字串,得到每個字元。
	// 不管有沒有中文都能正常顯示
	for index, c := range s {
		// 注意這裡的index並不是按照1 2 3 4 這樣+1上去的,是按照字元所在的位元組位置,1箇中文一般等於3個位元組
		fmt.Printf("資料型別:%T - index:%d -- 字元:%c\n", c, index, c)
	}
}

輸出

lichengguo@lichengguodeMacBook-Pro day01 % go run test.go
11
s1: [72 101 108 108 111 20013 22269] 7
Hello中國
Hello中å½
資料型別:int32 - index:0 -- 字元:H
資料型別:int32 - index:1 -- 字元:e
資料型別:int32 - index:2 -- 字元:l
資料型別:int32 - index:3 -- 字元:l
資料型別:int32 - index:4 -- 字元:o
資料型別:int32 - index:5 -- 字元:中
資料型別:int32 - index:8 -- 字元:國

型別轉換

package main

import (
	"fmt"
)

func main() {
	// 型別轉換
	// int --> float
	fmt.Println("---- int --> float ----")
	n1 := 10
	f := float64(n1)
	fmt.Println(f)        // 10
	fmt.Printf("%T\n", f) // f:float64

	// float --> int 會把小數部分去掉
	fmt.Println("---- float --> int ----")
	f1 := float64(10.1)
	n2 := int(f1)
	fmt.Println(n2) // 10

	// string <--> rune
	fmt.Println("---- string <--> []rune ----")
	s1 := "tom"
	s2 := []rune(s1)
	fmt.Println(s2) // [116 111 109] ASCII編碼對照表

	s3 := "中國good"
	s4 := []rune(s3)       // string --> []rune
	fmt.Println(s4)        // [20013 22269 103 111 111 100]
	fmt.Printf("%T\n", s4) // 資料型別 []int32
	s5 := string(s4)       // []rune --> string
	fmt.Println(s5)        // 中國

	// string <--> byte
	fmt.Println("---- string <--> []byte ----")
	s6 := "你好hello"
	s7 := []byte(s6)
	fmt.Println(s7)        // [228 189 160 229 165 189 104 101 108 108 111] 一箇中文字元佔3個位元組
	fmt.Printf("%T\n", s7) // []uint8

	// 其他
	//s8 := []byte{'A', 1, 3, 'B', '漢'}  byte裡面不能存中文,會報錯 constant 27721 overflows byte
	fmt.Println("---- other ----")
	s8 := []byte{'A', 1, 3, 'B'}
	fmt.Println(s8)        // [65 1 3 66]
	fmt.Printf("%T\n", s8) // []uint8
	s9 := []rune{'中', 'A', 1, 3}
	fmt.Println(s9)        // [20013 65 1 3]
	fmt.Printf("%T\n", s9) // []int32

}

輸出

lichengguo@lichengguodeMacBook-Pro day01 % go run main.go
---- int --> float ----
10
float64
---- float --> int ----
10
---- string <--> []rune ----
[116 111 109]
[20013 22269 103 111 111 100]
[]int32
中國good
---- string <--> []byte ----
[228 189 160 229 165 189 104 101 108 108 111]
[]uint8
---- other ----
[65 1 3 66]
[]uint8
[20013 65 1 3]
[]int32