第三章 基础数据类型

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. 从 HTTP 切换到 HTTPS,这下我的技术博客安全了吧?

    博客园 的小伙伴们,大家好,我是刚脱离险境的二哥呀! 很久(大概两年)之前,我就搞了一个独立的个人博客网站,长下面这样. 大家有访问过的,可以在评论区扣 1 可惜一直没搞备案和 HTTPS,导致每次访 ...

  2. ERROR: database "db" is being accessed by other users

    执行DROP DATABASE testdb;的时候提示: ERROR: database "testdb" is being accessed by other users DE ...

  3. 面试必知道的APP测试adb命令

    查看当前连接设备: adb devices 如果发现多个设备: adb -s 设备号 其他指令 查看日志: adb logcat 安装apk文件: adb install xxx.apk 此安装方式, ...

  4. javaSE基础之变量,常量,作用域和运算符

    变量 变量是什么? 变量是可以变化得量 Java是一种强类型语言,每个变量都必须声明其类型. Java变量是程序中最基本的存储单元,其要素包括变量名,变量类型和作用域 type varName [=v ...

  5. remote: Support for password authentication was removed

    周末提交代码,把代码push到github上,控制台报了下面的错误: remote: Support for password authentication was removed on August ...

  6. CAS5.3服务器搭建与客户端整合SpringBoot以及踩坑笔记

    CAS5.3服务器搭建与客户端整合SpringBoot以及踩坑笔记 cas服务器的搭建 导出证书(1和2步骤是找了课程,随便写了一下存记录,不过对于自己测试不投入使用应该不影响) C:\Users\D ...

  7. MyBatis学习01(初识MyBatis和CRUD操作实现)

    1.初识MyBatis 环境说明: jdk 8 + MySQL 5.7.19 maven-3.6.1 IDEA 学习前需要掌握: JDBC MySQL Java 基础 Maven Junit 什么是M ...

  8. Git(6)-- 记录每次更新到仓库(git clone、status、add、diff、commit、rm、mv命令详解)

    @ 目录 1.克隆现有仓库:git clone 2.检查当前文件状态 :git status 3.跟踪新文件:git add 4.暂存已修改的文件:git add 5.状态简览: git status ...

  9. iOS开发之Lame编译

    前言 为了保证音频格式在多端通用,需要将音频转化为MP3格式,本文讲解了如何使用Shell脚本来编译lame库. 编译脚本 #!/bin/sh CONFIGURE_FLAGS="--disa ...

  10. sqli-labs lesson 7-10 (文件导出,布尔盲注,延时注入)

    写在前面: 首先需要更改一下数据库用户的权限用于我们之后的操作. 首先在mysql命令行中用show variables like '%secure%';查看 secure-file-priv 当前的 ...