Go语言内置以下这些基础类型:
- 布尔类型:
bool
- 整型:
int8
、byte
、int16
、int
、uint
、uintptr
- 浮点类型:
float32
、float64
- 复数类型:
complex64
、complex128
- 字符串类型:
string
- 字符类型:
rune
- 错误类型:
error
此外,Go语言也支持一下这些符合类型
- 指针(pointer)
- 数组(array)
- 切片(slice)
- 字典(map)
- 通道(chan)
- 结构体(struct)
- 接口(interface)
1、布尔类型
1 2 3 4 5 |
var b1 bool b1 = true b2 := (1 == 2) // b2也会推导成bool类型 |
2、整型
1 2 3 4 5 6 7 8 9 10 11 12 13 |
类型 长度(字节) 值范围 int8 1 -128 ~ 127 uint8(byte) 1 0 ~ 255 int16 2 -32 768 ~ 32 767 uint16 2 0 ~ 65 535 int32 4 -2 147 483 648 ~ 2 147 483 647 uint32 4 0 ~ 4 294 947 295 int64 8 -9 223 372 036 854 775 808 ~ 9 223 372 036 854 775 807 uint64 8 0 ~ 18 446 744 073 709 551 615 int 平台相关 平台相关 uint 平台相关 平台相关 uintptr 同指针 在32位平台下为4字节,64位平台下为8字节 |
在Go语言中int
和int32
为不同的类型,以下为错误示例:
1 2 3 4 5 6 7 |
// 错误示例 var value2 int32 value1 := 64 // value1 自动编译成int类型 value2 = value1 // int类型赋值给int32类型,编译报错 // 正确示例 value2 = int32(value1) |
同时2个不同类型的变量不能直接进行比较,但是可以直接和字面常量进行比较
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
var ( i int32 j int64 ) i, j = 32, 64 if i == j { fmt.Println("i and j are equal.") } if i == 32 && j == 32 { fmt.Println("i and j are equal.") } |
3、浮点类型
1 2 3 4 5 |
var f1 float32 f1 = 12 f2 := 12.0 // 如果不加小数点,f2将被推导成整型而非浮点型 |
因为浮点数不是一种精确的表达方式,所以不能像整型那样直接用==
来判断两个浮点数是否相等,这可能会导致不稳定的结果。
下面是一种推荐的替代方案:
1 2 3 4 |
func IsEqual(f1, f2, p float64) bool { return math.Abs(f1-f2) < p } |
4、复数类型
复数实际上由两个实数(在计算机中用浮点数表示)构成,一个表示实部real
,一个表示虚部imag
。
1 2 3 4 5 6 |
var c1 complex64 c1 = 3.2 + 12i c2 := 3.2 + 12i // 类型为complex128 c3 := complex(3.2. 12) // 同c2结果一致 |
5、字符串
1 2 3 4 5 6 |
var str string str = "Hello World" ch := str[0] fmt.Printf("The length of \"%s\" is %d . \n", str, len(str)) fmt.Printf("The first character of \"%s\" is %c, type is %T . \n", str, ch, ch) |
Go支持两种方式遍历字符串,一种是以字节数组的方式遍历:
1 2 3 4 5 6 7 |
str := "Hello, 世界" n := len(str) for i := 0; i < n; i++ { ch := str[i] fmt.Println(i, ch) } |
执行此程序后发现,字符串长度为13,是因为中个字符在UTF-8
中占了3个字节。
一种是以Unicode
字符遍历:
1 2 3 4 5 |
str := "Hello, 世界" for i, ch := range str { fmt.Println(i, ch) // ch的类型为rune } |
以Unicode
方式遍历时,每个字符的类型是rune
。
6、字符类型
Go语言中支持两个字符类型,一个是byte
(实际上是uint8
的别名),代表UTF-8
字符串的单个字节的值;另个是rune
,代表单个Unicode
字符。
关于rune
相关操作, 可查阅Go标准库的unicode
包。另外unicode/utf8
包也提供了utf8
和unicode
之间的转换。
7、数组
以下为一些常规声明数组的方式:
1 2 3 4 5 6 |
[32]byte // 长度为32的数组,每个元素为1个字节 [2*N] struct {x, y int32} // 复杂类型数组 [1000]*float64 // 指针数组 [3][5]int // 二位数组 [2][2][2]float64 // 等同于[2]([2]([2]float64)) |
元素遍历
1 2 3 4 5 6 7 8 9 10 |
// 方法一 for i := 0; i < len(array); i++ { ... } // 方法二 for i, v := range array { ... } |
需要注意的是,在Go语言中数组是一个值类型value type
。所有的值类型变量在赋值和作为参数传递时都将产生一次复制动作。
8、切片
数组的长度定义后就无法修改,每次赋值都将产生一份副本。为了弥补数组的不足Go语言提供了切片这种数据类型。
初看起来,切片就像指向数组的指针,实际上他拥有自己的数据结构,二不仅仅是一个指针。切片的数据结构可以抽象成以下3个变量:
- 一个指向原生数组的指针
- 数组切片中的元素个数
- 切片已分配的存储空间
创建切片的方法主要有两种——基于数组和直接创建。
- 基于数组
1 2 3 4 5 6 7 8 9 10 |
// 创建数组 var arr [10]int = [10]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9} // 基于数组创建切片 var sli []int = arr[:5] // 基于arr的前5个元素创建切片 fmt.Println(cap(sli)) // 容量为10 fmt.Println(len(sli)) // 长度为5 // var sli []int = arr[:] // 基于arr的所有元素创建切片 // var sli []int = arr[5:] // 基于arr的后5个元素创建切片 |
- 直接创建
1 2 3 4 |
sli := make([]int, 5) // 创建一个初始元素个数为5的切片,初始值都为0 sli := make([]int, 5, 10) // 创建一个初始元素个数为5的切片,初始值都为0,并且预留了10个容量 sli := []int{1, 2, 3, 4, 5} // 直接创建并初始化包含5个元素的切片 |
元素遍历同数组一样
1 2 3 4 5 6 7 8 9 10 |
// 方法一 for i := 0; i < len(sli); i++ { ... } // 方法二 for i, v := range sli { ... } |
append
和copy
1 2 3 4 5 6 7 8 9 10 11 12 |
// append sli := make([]int, 5, 10) // len = 5 cap = 10 sli = [0 0 0 0 0] sli = append(sli, 1, 2, 3) // len = 8 cap = 10 sli = [0 0 0 0 0 1 2 3] sli_another := []int{8, 9, 10} sli = append(sli, sli_another...) // len = 11 cap = 20 sli = [0 0 0 0 0 1 2 3 8 9 10] // copy sli_a := []int{1, 2, 3, 4, 5} sli_b := []int{5, 4, 3} copy(sli_a, sli_b) // 只会复制sli_b的三个元素到sli_a的前三个位置中 sli_a = [5 4 3 4 5] copy(sli_b, sli_a) // 只会复制sli_a的前三个元素到sli_b中 sli_b = [1 2 3] |
9、map
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
package main import ( "fmt" ) func main() { // 创建map var personDB map[string]PersonInfo personDB = make(map[string]PersonInfo) // 元素赋值 personDB["1"] = PersonInfo{"1", "Tom", "Room 101..."} personDB["2"] = PersonInfo{"2", "Jack", "Room 102..."} personDB["3"] = PersonInfo{"3", "Peter", "Room 103..."} personDB["4"] = PersonInfo{"4", "Mike", "Room 104..."} // 元素删除 delete(personDB, "4") // 元素查询 person, ok := personDB["1"] if ok { fmt.Println("Found Person", person.Name, "with id ", person.ID) } else { fmt.Println("Did not find") } } type PersonInfo struct { ID string Name string Address string } |