golang:數據類型總結


Go語言將數據類型分為四類:基礎類型、復合類型、引用類型和接口類型。

基礎數據類型包括:

  • 基礎類型:
    - 布爾型、整型、浮點型、復數型、字符型、字符串型、錯誤類型。
  • 復合數據類型包括:
    - 指針、數組、切片、字典、通道、結構體、接口。

基礎數據類型

布爾值和布爾表達式

布爾類型的變量取值結果要么是真,要么是假,用bool關鍵字進行定義

布爾類型默認值為 false

指定格式的輸出 %t

語法 描述/結果
!b 邏輯非操作符 b值為true 則 操作結果為false
a || b 短路邏輯或,只要布爾值 a b 中任何一個為true表達式結果都為true
a && b 短路邏輯與,兩個表達式a b都為true,則整個表達式結果為true
x > y 表達式x的值小於表達式Y的值,則表達式的結果為true

數值類型

go語言提供了大內置的數值類型,標准庫也提供了big.Int類型的整數,和big.Rat類型的有理數,這些都是大小不限(只限於機器內存)

整型

GO語言提供了11種整型,包含5種有符號,和5種無符號的與一種用於存儲指針的整數類型。Go語言允許使用byte來作為無符號uint8類型的同義詞,在使用單個字符時提倡使用rune來替代 int32

類型 存儲空間 取值范圍
byte 8-bit 同uint8
int 系統決定 依賴不通平台實現,32位操作系統為int32的值范圍,64位操作系統為int64的值范圍
int8 8-bit [-128, 127] ,表示 UTF-8 字符串的單個字節的值,對應 ASCII 碼的字符值
int16 16-bit [-32678, 32767]
int32 32-bit [2147483648, 2147483647]
int64 64-bit [-9223372036854775808 , 9223372036854775807]
rune 32-bit 同uint32,表示 單個 Unicode 字符
uint 系統決定 依賴不通平台下的實現,可以是uint32或uint64
uint8 8-bit
uint16 16-bit [0, 65535]
uint32 32-bit [0, 4294967295]
uint64 64-bit [0, 18446744073709551615]
uintptr 系統決定 一個可以恰好容納指針值得無符號整數類型(32位操作系統為uint32的值范圍,64位系統為uint64的值范圍)

浮點類型

Go語言提供了兩種類型的浮點類型和兩種類型的復數類型,

類型 存儲空間 取值范圍
float32 32-bit [1.401298464324817070923729583289916131280e-45 , 3.402823466385288598117041834516925440e+38] 精確到小數點后7位
float64 64-bit [4.940656458412465441765687928682213723651e-324 , 1.797693134862315708145274237317043567981e+308] 精確到小數點后15位
complexm64 64-bit 實部和虛部都是一個float32
complexm128 128-bit 實部和虛部都是一個float64
fmt.printf("%.2f",num) // 保留兩位小數,同時進行了四舍五入

字符串 (string)

字符串使用雙引號 " 或者反引號 ```來創建,雙引號可以解析字符串變量

定義字符變量用 byte 關鍵詞 var ch byte = 'a' 8-bit,代表了 ASCII 碼的一個字符。指定格式的輸出 %c
定義字符變量用 rune 關鍵詞 var ch rune = 'a' 32-bit 代表了 Unicode(UTF-8)碼的一個字符。
定義字符變量用 string 關鍵詞 var ch string = "abc"指定格式的輸出 %s

字符串的結束標志 \0,Go語言使用的UTF8編碼,英文占1個字符,一個漢字占3個字符

自動推導類型

自動推到類型,創建的浮點型默認為 float64,整型為int

      a := "123"
      a := 10

使用fmt格式化輸出

格式指令通常由用於輸出單個值,每個值都按格式指令格式化。用於fmt.Printf() fmt.Errorf() fmt.Fprintf() fmt.Sprintf()函數的格式字符串包含一個或多個格式指令

格式指令 含義/結果
%b 二進制數值
%c 數值對應的 Unicode 編碼字符
%d 十進制數值
%o 八制數值
%e 科學計數法,e表示
%E 科學計數法,E表示
%f 有小數部分,無指數部分
%g 以%f或%e表示浮點數或復數
%G 以%f或%E表示浮點數或復數
%s 直接輸出字符串或者[]byte
%q 雙引號括起來的字符串或者[]byte
%x 每個字節用兩字節十六進制表示,a-f表示
%X 每個字節用兩字節十六進制表示,A-F表示
%t 以true或fales輸出布爾值
%T 輸出值得類型
%v 默認格式輸出內置或自定義類型的值

強制類型轉換

類型轉換用於將一種數據類型轉換為另外一種類型

var num float64 = 3.15
fmt.Printf("%d", int(num))

類型不一致的不能進行運算,在類型轉換時,建議將低類型轉換為高類型,保證數據精度,高類型轉換成地類型,可能會丟失精度,或數據溢出

復合數據類型

數組

數組,一系列同一類型數據的集合,數組是值類型,在初始化后長度是固定的,無法修改其長度。

數組的定義

var arr [元素數量]類型

數組初始化

全部初始化 var arr [5]int = [5]int{1,2,3,4,5}

部分初始化 var arr [5]int = [5]int{1,2} ,沒有指定初值的元素將會賦值為其元素類型(int)的默認值(0)

指定下標初始化 var arr = [5]int{2:5, 3:6} key:value的格式

通過初始化確定數組長度,var arr = [...]int{1, 2, 3} 長度是根據初始化時指定個數

相同空間大小(類型)的數組可以用 == != 來比較是否相同。

package main

import "fmt"

func main() {
	var arr [2]int = [2]int{1, 2}
	var arr2 [2]int = [...]int{2, 2}
	fmt.Println(arr == arr2)
}


D:\go_work\src>go run main.go
false

數組的遍歷

  • 通過 for .. len() 完成遍歷
  • 通過 for .. range 完成遍歷

作為函數值傳遞

golang數組是值類型,當數組作為函數參數,函數中修改數組中的值,不會影響原數組

package main

import "fmt"

func test(t [2]int) {
	fmt.Println(&t)
}

func main() {
	var arr [2]int = [2]int{1, 2}
	test(arr)
}

二維數組

初始化方式

  • 全部初始化 var arr [2][2]int = [2][2]int{ {1,2},{3,4} }
  • 部分初始化 var arr [2][2]int = [2][2]int{ {1,2},{3} }
  • 指定元素初始化 var arr [2][2]int = [2][2]int{ 1:{1} }var arr [2][2]int = [2][2]int{ 1:{1:3} }
  • 通過初始化確定二維數組行數 var arr [...][2]int = [2][2]int{ {1,2},{3,4} } 行下標可以用 ... 列下標不可用 ...

map

Go語言中的字典結構是有鍵和值構成的,所謂的鍵,就類似於字典的索引,可以快速查詢出對應的數據。

map是只用無序的鍵值對的集合。

map最重要的一點是通過key來快速檢索數據,key類似於索引,指向數據的值。

map中key的值是不能重復的

引用類型或包含引用類型的數據類型不能作為key

map的創建

  • 字面量:var map_name map[keyType]valType
  • 類型推導: map_name := map[keyType]valType
  • 關鍵詞:make(map[keyType]valType)

map的初始化

  • 字面量:var maps[int]string = map[int]string{1: "zhangsan", 2: "lisi"}
  • 類型推導: maps := map[int]string{1: "zhangsan", 2: "lisi"}
  • 關鍵詞:maps := make(map[string]int,10); maps["zhangsan"] = 14

map的key value

通過key獲取值時,判斷key是否存在 var1, var2 := map[key],如存在,var1存儲對應的值,var2的值為true,var2否則為false

package main

import "fmt"

func initial(t []int) {
	for n := 0; n < 10; n++ {
		t[n] = n
	}
}

func main() {
	var m map[int]string = map[int]string{1: "zhangsan", 2: "lisi"}

	fmt.Println(m)
	v, ok := m[2]

	if ok {
		fmt.Println(v)
	} else {
		fmt.Println(ok)
	}

	v, ok = m[3]

	if ok {
		fmt.Println(v)
	} else {
		fmt.Println(ok)
	}
}

delete(map,2) 通過key刪除某個值

作為函數參數傳遞

slice map channel都是引用類型,所以改變是改變的變量的地址。

package main

import "fmt"

func initial(t map[int]string) {
	for n := 0; n < 10; n++ {
		t[n] = fmt.Sprintf("aaa%d", n)
	}
}

func main() {
	var m = make(map[int]string, 10)

	initial(m)
	fmt.Println(m)
}

切片

切片與數組相比,切片的長度是不固定的,可以追加元素,在追加時可能使切片的容量增大,所以可以將切片理解為“動態數組”,但是,它不是數組。

切片定義

var slice_name []type 默認空切片,長度為0

slice_name := []type{} 默認空切片,長度為0

make([]type, length, capacity) length:已初始化的空間,capacity:已開辟的空間(length+空閑)。length不能大於capacity

len() 返回長度 cap() 返回容量

如果使用字面量的方式創建切片,大部分的工作就都會在編譯期間完成,使用 make() 關鍵字創建切片時,很多工作都需要運行時的參與。

切片初始化

通過 var slice_name []type 方式創建

import "fmt"

func main() {
	var slices []int

	slices = append(slices, 1, 2, 3, 4, 5, 6)

	fmt.Print(slices)

	slices = append(slices, 100, 99)

	fmt.Print(slices)
}

通過 slice_name := []type{} 方式創建

  • 直接在 {} 中添加值
  • 通過 append() 添加

通過 make([]type, length, capacity) 方式創建

package main

import "fmt"

func main() {
	var slices []int

	slices = make([]int, 3, 5)

	slices[0] = 1
	slices[1] = 2
	slices[2] = 3
	slices[3] = 4

	fmt.Println(slices)
}

切片的截取

切片截取

操作 含義
s[n] 切片s中索引位置為N的項
s[:] 從切片s的索引位置到 len(s) - 1 處所獲得的切片
s[low:] 從切片s的索引位置low到 len(s) - 1 處所獲得的切片
s[:high] 從切片s的索引位置0到high處所獲得的切片 len=high
s[low:higt] 從切片s的索引位置low到high處所獲得的切片 len=high-low
s[low:higt:max] 從切片s的索引位置low到high處所獲得的切片,len=high-low,cap=max-low
len(s) 切片s的長度,<=cap(s)
cap(s) 切片s的容量,>=len(s)

slice[startVal, length, Capacity]

容量為:capacity - startVal

長度為: length - startVal

package main

import "fmt"

func main() {
	var slices []int

	slices = []int{1, 2, 3, 4, 5, 6, 7, 8}
	s := slices[1:3:5]

	fmt.Println(s)
	fmt.Println(len(s))
	fmt.Println(cap(s))
}

在截取時,capacity 不能超過原slice的 capacity

package main

import "fmt"

func main() {
	var slices []int

	slices = []int{1, 2, 3, 4, 5, 6, 7, 8}
	s := slices[1:3:10]

	fmt.Println(s)
	fmt.Println(len(s))
	fmt.Println(cap(s))
}

切片值得修改

問:切片截取后返回新切片,對新切片的值修改,會影響原切片嗎

當對切片進行截取操作后,產生了新的切片,新的切片是指向原有切片的,對新切片值修改,會影響到原有切片

package main

import "fmt"

func main() {
	var slices []int

	slices = []int{1, 2, 3, 4, 5, 6, 7, 8}
	s := slices[1:3]

	s[1] = 100

	fmt.Println(s)
	fmt.Println(slices)

}

追加和拷貝

  • append(slice, 1,2,3) 向切片末尾追加數據
  • copy(slice1, slice2) 拷貝的長度為兩個切片中長度較小的長度值

作為參數值傳遞,切片是數組的一個引用,因此切片是引用類型,操作會修改原有切片

package main

import "fmt"

func initial(t []int) {
	for n := 0; n < 10; n++ {
		t[n] = n
	}
}

func main() {
	var slices = make([]int, 10)
	fmt.Println(slices)
	initial(slices)
	fmt.Println(slices)

}

切片擴容

切片擴容,一般方式:上一次容量的2倍,超過1024字節,每次擴容上一次的1/4

package main

import "fmt"

func initial(t []int) {
	for n := 0; n < 10; n++ {
		t[n] = n
	}
}

func main() {
	var slices = make([]int, 3)
	var slices1 = []int{4, 5}

	copy(slices, slices1)

	fmt.Println(slices)
	fmt.Println(slices1)

}

struct 結構體

結構體 struct 是由一系列具有相同類型或不同類型的數據構成的數據集合,結構體可以很好的管理一批有聯系的數據,使用結構體可以提高程序的易讀性。Go中提供了對 struct 的支持,與數組一樣,struct屬於復合類型,並非引用類型

Go語言中結構體包含以下特性

  • 值傳遞,Go語言中結構體和數組一樣是值類型,可以聲明結構體指針向下傳遞
  • 不可繼承,Go語言中沒有繼承的概念,在結構體中,可以通過組合結構體,來構建更復雜的結構體。
  • 結構體不能包含自己。

結構體聲明

成員名稱前不能加 var

type Student struct {
	id int
    name string
    age int
    addr string
}

空結構體

結構體也可以不包含任何字段,稱為空結構體 struct{}

結構體初始化

  • 順序初始化 var stu = Student{ id:101, name:"zhangsan", age:19, addr:"shanghai" }
  • 指定成員初始化 var stu = Student{name:"zhangsan", age:19}
  • 通過 結構體變量.成員 完成初始化 var stu Student stu.age=19 stu.addr="peking"

結構體傳遞

結構體與數組一樣,都是值傳遞,將結構體作為函數實參傳給函數的形參時,會復制一個副本,所以為了提高性能,在結構體傳給函數時,可以使用指針結構體。

指針結構體定義:聲明結構體變量時,在結構體類型前加 * 號,便聲明一個指向結構體的指針。 var stu *Student
指針結構體訪問: 由於.的優先級高於*struct_name,故在使用時,需要對結構體加括號。(*struct_name).成員屬性 (*stu).name


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM