《Go语言圣经》阅读笔记:第三章基础数据类型
第三章 基础数据类型
Go语言将数据类型分为四类:
- 基础类型
- 数字
- 整数
- 浮点数
- 复数
- 字符串
- 布尔
- 数字
- 复合类型
- 数据
- 结构体
- 引用类型
- 指针
- 切片
- 字典
- 函数
- 通道
- 接口类型
在此章节中先介绍基础类型。
3.1 整型
Go语言中提供了有符号数和无符号数两种整型运算。
有符号数有:int8, int16, int32, int64
无符号数有:uint8, uint16, uint32, uint64
此外还有两种针对特定CPU平台机器字大小的有符号数int和无符号数uint, 它们的大小与硬件平台有关。
rune类型与int32等价
byte类型与uint8等价
一般使用byte类型强调数值是一个原始数据,而并非是一个小整数。
int, uint, int32他们属于不同的类型,不能直接进行操作(需要强转)。
Go语言中有关算数运算、逻辑运算、比较运算的二元运算符,它们按照递减顺序排列如下:
* / % << >> & &^
+ - | ^
== != < <= > >=
&&
||
* | / | % | << | >> | & | &^ |
---|---|---|---|---|---|---|
+ | - | \ | ^ | |||
== | != | < | <= | > | >= | |
&& | ||||||
|| |
二元运算符有五种优先级(见上图),同一优先级之间,使用左优先结合的原则,但是可以使用括号来提升优先级。例如 mask & 1 << 28, 因为& <<属于相同优先级,因此先计算mask&1, 然后再将其结果左移28位。我们可以使用括号来提升优先级:
mask & (1 << 28)算术运算符+、-、*和/ 可以适用于整数、浮点数、复数运算,但是取模运算符%只能用于整数之间
在Go语言中,%取模运算的符号与被取模的符号数总是一致的。例如
-5%3=-2
,-5%-3=-2
两个相同的整数类型可以使用下面的二元比较运算符进行比较,其结果为布尔型:
- ==
- !=
- <
- <=
- >
- >=
在Go中,有两个一元运算符:
+ 一元加法
- 负数
对于整数,+x是0+x的简写; -x是0-x的简写;
对于浮点数和复数,+x就是x;-x就是x的复数。
Go语言中还提供了bit位操作运算符,前四个不区分有符号数还是无符号数:
& 位运算AND
| 位运算OR
^ 位运算XOR
&^ 位清空(AND NOT)
<< 左移
>> 右移
位运算^ 作为二元运算符时按位异或;当作为一元运算符时表示按位取反
移位操作(如x<<n),n要求必须为无符号数,x可以是有符号数也可以是无符号数。左移运算,使用0填充右边空缺Bit位;无符号数右移也是用0填充左边的空缺位,但是有符号数右移则会使用符号位填充左边的空缺位(负数右移仍然为负数)。
func main() {
var i int8 = -64
fmt.Println(i)
fmt.Println(i >> 2)
fmt.Println(i >> 4)
fmt.Println(i >> 5)
fmt.Println(i >> 6)
fmt.Println(i >> 10)
fmt.Printf("%09b\n", i)
fmt.Printf("%09b\n", i>>2)
fmt.Printf("%09b\n", i>>4)
fmt.Printf("%09b\n", i>>5)
fmt.Printf("%09b\n", i>>6)
fmt.Printf("%09b\n", i>>10)
}
结果:
-64
-16
-4
-2
-1
-1
-01000000
-00010000
-00000100
-00000010
-00000001
-00000001
强制类型转换:
func main() {
var apples int32 = 1
var oranges int16 = 2
var compote int = apples + oranges
}
如果未做转换,则无法编译通过,提示如下错误:
# command-line-arguments
section3\forceConv.go:7:27: invalid operation: apples + oranges (mismatched types int32 and int16)
而比较常用的解决办法是:类型强制转换. 之后程序便可以成功编译运行。
var compote int = int(apples) + int(oranges)
同其他语言一样,在高精度向低精度类型强制转换过程中存在丢失精度的问题
关于使用Printf函数的注意事项:
func main() {
x := 100
fmt.Printf("%d %[1]x %#[1]x %#[1]b\n", x)
}
执行结果如下:
100 64 0x64 0b1100100
可以看出:
- 在%之后的[1]用来告诉Printf函数再次使用第一个操作数
- 在%之后的#用来告诉Printf函数在使用%o、%x、%X等输出时添加0、0x、0X的前缀。
- 字符使用%c参数打印,或者是用%q参数打印带单引号的字符
这两个东西都比较好用…切记切记
3.2浮点类型
Go语言提供了两种精度的浮点数,float32和float64。
file:///F:/golang/Bible/section3/surface.xml
3.3 复数
Go语言提供了两种精度的复数类型:complex64和complex128,分别对应float32和float64两种浮点数精度。
内置的complex函数用于构建复数,内建的real和imag函数分别返回复数的实部和虚部:
func main() {
var x complex128 = complex(1, 2)
var y complex128 = complex(2, 3)
/*复数相乘是交叉相乘,类似于(a+b) * (c+d) */
fmt.Println(x * y)
fmt.Println(real(x * y))
fmt.Println(imag(x * y))
fmt.Println(1i * 1i)
fmt.Println(cmplx.Sqrt(-1))
}
执行结果如下:
(-4+7i)
-4
7
(-1+0i)
(0+1i)
3.4 布尔型
一个布尔类型的值只有两种:true和false。
if和for语句的条件部分都是布尔类型的值,并且==和<等比较操作也会产生布尔型的值。
- &&运算符的优先级高于||, 因此下面的代码没有问题
if 'a' <= c && c <= 'z' ||
'A' <= c && c <= 'Z' ||
'0' <= c && c <= '9' {
/* c is letter or digit */
}
- [x]布尔值不会隐式转换为0或者1,反之亦然。两者之间需要做显式转换
func itob(i int) bool {
return i != 0
}
func btoi(b bool) int {
if b {
return 1
}
return 0
}
3.5字符串
- 在Go中,字符串是一个常量,不可修改的。
- 内置的len函数可以返回一个字符串中的字节数目(不是rune字符数目)
- 越界访问会导致panic异常
- 子字符串操作s[i:j]基于原始的s字符串的第i个字节开始到第j个字节(并不包含j本身)生成一个新字符串
- 不管i还是j都可能被忽略,当它们被忽略时将采用0作为开始位置,采用len(s)作为结束的位置。
字符串操作demo:
func main() {
s := "hello, world!!!"
fmt.Println(len(s))
fmt.Printf("s[0]= %[1]c %[1]d\n", s[0])
fmt.Printf("s[7]= %[1]c %[1]d\n", s[7])
//fmt.Println(s[len(s)]) /*index out of range [15] with length 15*/
/*支持索引访问,如果超出范围仍然会有panic异常*/
fmt.Println(s[2:8])
fmt.Println(s[:8])
fmt.Println(s[2:])
fmt.Println(s[:])
/*可以用来拼接字符串*/
fmt.Println("Oh,shit" + s[5:])
t := s
s += "Oh,Ye!!! Oh Ye"
/*t没有变化,s字符串被追加了一段*/
fmt.Println(t)
fmt.Println(s)
s[0] = 'H' //cannot assign to s[0]
}
3.6 常量
- 常量表达式的值在编译期计算,而不是在运行期。
- 常量的值不可修改,这样可以防止在运行期被意外或恶意的修改。
- 和变量声明一样,可以批量声明多个常量;这比较适合声明一组相关的常量:
const (
e = 2.71828182845904523536028747135266249775724709369995957496696763
pi = 3.14159265358979323846264338327950288419716939937510582097494459
)
- 如果是批量声明的常量,除了第一个外其它的常量右边的初始化表达式都可以省略,如果省略初始化表达式则表示使用前面常量的初始化表达式写法,对应的常量类型也一样的, 详见下面例子:
func main() {
const (
a = 1
b
c = 2
d
)
fmt.Println(a) //1
fmt.Println(b) //1
fmt.Println(c) //2
fmt.Println(d) //2
}
这个是itoa常量生成器的一个前提。
3.6.1 itoa常量生成器
常量声明可以使用iota常量生成器初始化,它用于生成一组以相似规则初始化的常量,但是不用每行都写一遍初始化表达式。在一个const声明语句中,在第一个声明的常量所在的行,iota将会被置为0,然后在每一个有常量声明的行itoa值加一。
例如:
const (
Sunday Weekday = iota
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
)
func main() {
fmt.Println(Sunday) //0
fmt.Println(Monday) //1
fmt.Println(Tuesday) //2
fmt.Println(Wednesday) //3
fmt.Println(Thursday) //4
fmt.Println(Friday) //5
fmt.Println(Saturday) //6
}
下面是一个更复杂的例子,每个常量都是1024的幂
const (
_ = 1 << (10 * iota)
KiB // 1024
MiB // 1048576
GiB // 1073741824
TiB // 1099511627776 (exceeds 1 << 32)
PiB // 1125899906842624EiB // 1152921504606846976
ZiB // 1180591620717411303424 (exceeds 1 << 64)
YiB // 1208925819614629174706176
)
不过iota常量生成规则也有其局限性。例如,它并不能用于产生1000的幂(例如KB、MB等)
3.6.2 无类型常量
Go语言的常量有个不同寻常之处:存在无类型的常量,且精度更高。
许多常量并没有一个明确的基础类型。编译器为这些没有明确的基础类型的数字常量提供比基础类型更高精度的算术运算
只有常量可以是无类型的。
《Go语言圣经》阅读笔记:第三章基础数据类型的更多相关文章
- 《Interest Rate Risk Modeling》阅读笔记——第三章:拟合期限结构
目录 第三章:拟合期限结构 思维导图 扩展 第三章:拟合期限结构 思维导图 扩展 NS 模型的变种
- C++PRIMER 阅读笔记 第三章
本章主要介绍 string vector 和 bitset, 不能贪多,现在本文主要介绍 string 与 vector 头文件中最好不要使用namespace std, 因为头文件会直接被预处理器放 ...
- 阅读笔记---第三章 Xen信息页
1.文件/xen/include/public/xen.h 2.第一个数据结构:启动信息页strat_info,启动信息页是GuestOS内核启动时,由Xen映射到GusetOS内存空间的一个物理页面 ...
- Java 学习笔记 ------第三章 基础语法
本章学习目标: 认识类型与变量 学习运算符的基本使用 了解类型转换细节 运用基本流程语法 一.类型(基本类型) 所谓基本类型,就是在使用时,得考虑一下数据用多少内存长度存比较经济,利用程序语法告诉JV ...
- Hadoop阅读笔记(三)——深入MapReduce排序和单表连接
继上篇了解了使用MapReduce计算平均数以及去重后,我们再来一探MapReduce在排序以及单表关联上的处理方法.在MapReduce系列的第一篇就有说过,MapReduce不仅是一种分布式的计算 ...
- 《大象Think in UML》阅读笔记(三)
Think in UML 阅读笔记(三) 把从现实世界中记录下来的原始需求信息,再换成一种可以知道开发的表达方式.UML通过被称为之概念化的过程来建立适合计算机理解和实现的模型,这个模型被称为分析模型 ...
- The Road to learn React书籍学习笔记(第三章)
The Road to learn React书籍学习笔记(第三章) 代码详情 声明周期方法 通过之前的学习,可以了解到ES6 类组件中的生命周期方法 constructor() 和 render() ...
- Android群英传笔记——第三章:Android控件架构与自定义控件讲解
Android群英传笔记--第三章:Android控件架构与自定义控件讲解 真的很久没有更新博客了,三四天了吧,搬家干嘛的,心累,事件又很紧,抽时间把第三章大致的看完了,当然,我还是有一点View的基 ...
- 《DOM Scripting》学习笔记-——第三章 DOM
<Dom Scripting>学习笔记 第三章 DOM 本章内容: 1.节点的概念. 2.四个DOM方法:getElementById, getElementsByTagName, get ...
随机推荐
- 移动APP我们需要关注什么
移动APP关注的点比web或者PC上的程序更多 1.测试用例的设计 移动互联网的快节奏,要放弃传统的测试用例编写方式,不需要写详细的测试用例,采用罗列测试点的方式如思维导图,这样既节省时间又能够直观清 ...
- Docker 网络解读
Docker 容器在运行时,会涉及多个容器相互连接,甚至与宿主机上的应用连接的问题.既然需要产生连接,那么就必然要依赖网络. 网络在Docker的技术体系中,是一个不容易搞清楚的要点.因此,希望您读完 ...
- canal同步异常:当表结构变化时,同步失败
场景 canal 同步Mysql一段时间后突然失败,报如如下错误: 2021-08-06 16:16:51.732 [MultiStageCoprocessor-Parser-Twt_instance ...
- Redis 实战篇:巧用数据类型实现亿级数据统计
在移动应用的业务场景中,我们需要保存这样的信息:一个 key 关联了一个数据集合,同时还要对集合中的数据进行统计排序. 常见的场景如下: 给一个 userId ,判断用户登陆状态: 两亿用户最近 7 ...
- js原始数据类型有哪些,引用数据类型有哪些
js的数据类型划分方式为 原始数据类型和 引用数据类型 栈: 原始数据类型(Undefined,Null,Boolean,Number.String) 堆: 引用数据类型(对象.数组.函数) 两种类型 ...
- 两万字长文,彻底搞懂Kafka!
1.为什么有消息系统 1.解耦合 2.异步处理 例如电商平台,秒杀活动. 一般流程会分为: 风险控制 库存锁定 生成订单 短信通知 更新数据 通过消息系统将秒杀活动业务拆分开,将不急需处理的业务放在后 ...
- 使用AVPro Video在Unity中播放开场视频(CG)笔记
游戏中的开场CG(播放视频),采用的插件为AVPro Video1.x(和W的版本一致),Unity版本为2018.4.0f1 Asset Store:AVPro Video - Core Andro ...
- K8s 部署 Gitlab CI Runner
K8s 版本:1.20.6 GitLab CI 最大的作用是管理各个项目的构建状态.因此,运行构建任务这种浪费资源的事情交给一个独立的 Gitlab Runner 来做就会好很多,而且 Gitlab ...
- PyCharm启动报错 TypeError: unsupported operand type(s) for /: ‘str’ and ‘str’ 解决
这个提示大概是说:"类型错误:不支持操作类型为字符串和字符串",直接把两个字符串(BASE_DIR = os.path.dirname(os.path.dirname(os.pat ...
- yum clean all大坑解决
在Centos7系统中执行yum clean all 之后,发现yum的其他执行都报错了: 要解决,关键在这里: 把/var/cache/yum/ 下面的文件删除了 接下来,如果执行yum repol ...