第三章 基础数据类型

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语言圣经》阅读笔记:第三章基础数据类型的更多相关文章

  1. 《Interest Rate Risk Modeling》阅读笔记——第三章:拟合期限结构

    目录 第三章:拟合期限结构 思维导图 扩展 第三章:拟合期限结构 思维导图 扩展 NS 模型的变种

  2. C++PRIMER 阅读笔记 第三章

    本章主要介绍 string vector 和 bitset, 不能贪多,现在本文主要介绍 string 与 vector 头文件中最好不要使用namespace std, 因为头文件会直接被预处理器放 ...

  3. 阅读笔记---第三章 Xen信息页

    1.文件/xen/include/public/xen.h 2.第一个数据结构:启动信息页strat_info,启动信息页是GuestOS内核启动时,由Xen映射到GusetOS内存空间的一个物理页面 ...

  4. Java 学习笔记 ------第三章 基础语法

    本章学习目标: 认识类型与变量 学习运算符的基本使用 了解类型转换细节 运用基本流程语法 一.类型(基本类型) 所谓基本类型,就是在使用时,得考虑一下数据用多少内存长度存比较经济,利用程序语法告诉JV ...

  5. Hadoop阅读笔记(三)——深入MapReduce排序和单表连接

    继上篇了解了使用MapReduce计算平均数以及去重后,我们再来一探MapReduce在排序以及单表关联上的处理方法.在MapReduce系列的第一篇就有说过,MapReduce不仅是一种分布式的计算 ...

  6. 《大象Think in UML》阅读笔记(三)

    Think in UML 阅读笔记(三) 把从现实世界中记录下来的原始需求信息,再换成一种可以知道开发的表达方式.UML通过被称为之概念化的过程来建立适合计算机理解和实现的模型,这个模型被称为分析模型 ...

  7. The Road to learn React书籍学习笔记(第三章)

    The Road to learn React书籍学习笔记(第三章) 代码详情 声明周期方法 通过之前的学习,可以了解到ES6 类组件中的生命周期方法 constructor() 和 render() ...

  8. Android群英传笔记——第三章:Android控件架构与自定义控件讲解

    Android群英传笔记--第三章:Android控件架构与自定义控件讲解 真的很久没有更新博客了,三四天了吧,搬家干嘛的,心累,事件又很紧,抽时间把第三章大致的看完了,当然,我还是有一点View的基 ...

  9. 《DOM Scripting》学习笔记-——第三章 DOM

    <Dom Scripting>学习笔记 第三章 DOM 本章内容: 1.节点的概念. 2.四个DOM方法:getElementById, getElementsByTagName, get ...

随机推荐

  1. 随处可编辑的编辑器之神VIM

    据说这世界上只有三种编辑器:Vim,Emacs 和 其他编辑器,其中 Vim 被称作编辑器之神,Emacs 被称作神的编辑器,当然,其他编辑器永远只能是其他编辑器. 拿一位 网友的话 来说,VIM 的 ...

  2. 某学院m3u8视频解密获取分析实战分享

    [免责声明]本文来源于作者个人学习整理,仅供学习交流使用,不构成商业目的.所有资源均系本人个人学习或网络收集,仅提供一个展示.介绍.观摩学习的博文,不对其内容的准确性.可靠性.正当性.安全性.合法性等 ...

  3. RHCAS_DAY06

    vi/vim文本编辑器 Vim是从 vi 发展出来的一个文本编辑器,vim 具有程序编辑的能力,可以主动的以字体颜色辨别语法的正确性 vi/vim 共分为三种模式:命令模式.输入模式.底线命令模式(末 ...

  4. Android面试大揭秘!从技术面被“虐”到征服CTO,全凭这份强到离谱的pdf

    在笔者面试这一个月,看了不少文章,也刷了不少面试题,但真正有深度,适合4年及以上Android高工的内容少之又少 在面试准备阶段,笔者准备了三个月左右的时间,结合相关资料及源码,完成了一系列的深度学习 ...

  5. Flutter 中的动画

    Flutter 中动画的创建有很多种, 需要根据具体的需求选择不同的动画.如果只是简单的布局等的动画直接使用最简单的隐式动画就可以了,因为隐式动画是由框架控制的,所以仅仅只需要更改变需要变化属性就可以 ...

  6. 『Java』StringBuilder类使用方法

    String类存在的问题 String类的底层是一个被final修饰的byte[],不能改变. 为了解决以上问题,可以使用java.lang.StringBuilder类. StringBuilder ...

  7. Python脚本文件中使用中文

    Python做图形用户界面(GUI)开发时经常要在界面上显示中文,需要做如下处理(详见[1]和[2]2.3节): 在py文件的首行写上:# -- coding:utf-8 -- 保存py文件时要存为u ...

  8. 给 Arm 生态添把火,腾讯 Kona JDK Arm 架构优化实践

    前言 Arm 架构以其兼具性能与功耗的特点,在智能终端以及嵌入式领域得到了广泛的使用,不断扩大其影响力.而在 PC 端以及数据中心,之前往往是 x86 架构在其中发挥着主要的作用.最近,随着人工智能. ...

  9. Nginx搭建与相关配置

    目录 一.Nginx简介 1.1 概述 1.2 Nginx与Apache的差异 二.编译安装Nginx服务 2.1 将nginx软件包传到主机/opt目录下 2.2.安装依赖包 2.3.添加模块编译安 ...

  10. C51—模拟IIC总线实现EEPROM存取数据

    a - 什么是IIC总线 -什么是EEPROM -IIC总线的通信格式 模块化设计注解 整体代码 - 什么是IIC总线 IIC总线是同步通信的一种特殊形式,具有接线口少.控制简单.器件封装形式小.通信 ...