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") // 删除一个键
}
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- akka-grpc - 基于akka-http和akka-streams的scala gRPC开发工具
- Redis Sentinel原理与实现 (中)
- Keras_Tutorial_v2a
- 根据字符串生成对应Hash值
- Redis Sentinel原理与实现 (下)
- 要点4:C的文件操作
- 服务器端请求伪造——SSRF
- 唯一ID生成原理与PHP实现
- Liquid模板语言参考文档
- 谈谈协程
- 获取图片的各类参数信息 查看图片用了何种修图软件
- Nginx线程池浅析
- Python实现实时截图文字内容识别OCR 图片内容转文本
- Residual_Networks_v2a
- C++中STL学习笔记——各类容器混合使用