大家好,我是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) |
布尔类型不能接受其它类型的赋值,不支持自动或强制的类型转换,以下的示例是一些错误的用法:
var golang bool
golang = 1 // 错误
golang = bool(1) // 错误
以下的用法是正确的:
var golang bool
golang = (1!=0)
类型 | 长度 | 值范围 |
---|---|---|
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.")
}
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。
在Go语言中支持两个字符类型,一个是byte(实际上是uint8的别名),代表UTF-8字符串的单个字节的值;另一个是rune,代表单个Unicode字符。
关于rune相关的操作,可查阅Go标准库的unicode包;另外unicode/utf8包也提供了UTF8和Unicode之间的转换。
字符串支持下标读取操作:
str := "Hello world"
ch := str[0]
fmt.Printf("The length of \"%s\" is %d\n", 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)
}
数组的声明方法比较多,比如:
[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)
}
另外,数组是值类型,如果将数组作为函数参数传递,则在函数调用的时候该参数将发生数据复制,因此,在函数体中无法修改传入的数组的内容。
数组切片的数据结构可以抽象为以下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中
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") // 删除一个键
}
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。