the-way-to-go(一)

基本结构和基本数据类型

常量

关键字const定义;存储的数据只可以是布尔、数字(整数、浮点、复数)和字符串

// type可省略,编译器自动推断
const identifier [type] = value

一个没有指定类型的常量被使用时,会根据其使用环境而推断出它所需要具备的类型(必需能够在编译期确定)
(未定义类型的常量会在必要时根据上下文来获取相关类型)

数字型的常量是没有大小和符号的,且可以使用任何精度而不会导致溢出

当常量赋值给一个精度过小的数字型变量时,可能会因为无法正确表达常量所代表的数值而导致溢出

允许使用并行赋值

变量

var identifier type

当一个变量被声明时,系统自动赋予类型零值

// 类型零值
int 0
float 0.0
bool false
string ""
指针 nil

命名规则遵循骆驼命名法

全局变量 && 局部变量

一般情况下,只有ab的类型相同时,才能进行如a=b的赋值

声明与赋值(初始化)的语句可以组合起来

使用:=声明(初始化声明)只能被用于函数体内,即只能用来声明局部变量

// var identifier type = value
var a int = 11
// 编译器自动推断类型(除非自动推断的类型不满足所需)
var a = 11
// 如果从未定义过,可以简写
a := 11

局部变量被声明必须要被使用

全局变量允许声明但不使用

如果想要交换两个变量的值,则可以简单地使用 a, b = b, a

空白标识符 _ 也被用于抛弃值(_ 实际上是一个只写变量,只是不能得到它的值)

值类型 & 引用类型

所有像 int、float、bool 和 string 这些基本类型都属于值类型,使用这些类型的变量直接指向存在内存中的值

数组和结构体也是值类型

当使用等号 = 将一个变量的值赋值给另一个变量时,如:j = i,实际上是在内存中将 i 的值进行了拷贝

可以通过 &i 来获取变量 i 的内存地址

值类型的变量的值存储在


更复杂的数据通常会需要使用多个内存块,这些数据一般使用引用类型保存

一个引用类型的变量 r1 存储的是 r1 的值所在的内存地址(数字),或内存地址中第一个内存块所在的位置,即指针

当使用赋值语句 r2 = r1 时,只有引用(地址)被复制

指针、slice、map、channel 属于引用类型

被引用的变量会存储在,以便进行垃圾回收,且比栈拥有更大的内存空间

init函数

不能被人为调用

在每个包完成初始化后自动执行,且执行优先级比main函数高

每个源文件都只能包含一个init函数。初始化总是以单线程执行,且按照包的依赖关系顺序执行

也经常被用在当一个程序开始之前调用后台执行的 goroutine

基本类型与运算符

一元运算符只可以用于一个值的操作(作为后缀),而二元运算符则可以和两个值或者操作数结合(作为中缀)

只有两个类型相同的值才可以和二元运算符结合

Go是强类型语言,不会进行隐式转换(必需显式说明)

布尔 bool

两个类型相同的值可以使用相等 == 或者不等 != 运算符来进行比较并获得一个布尔型的值

可以通过和逻辑运算符(非 !、和 &&、或 ||)结合来产生另外一个布尔值

&&、或 || 与相等 == 或不等 != 属于二元运算符,而非 ! 属于一元运算符

建议命名以 is 或者 Is 开头(或类似的)

数字类型

整型 int 和浮点型 float

原生支持复数

与操作系统相关的定义

  • intunint。32位操作系统:4个字节;64位操作系统:8个字节
  • uintptr。长度被设定为足够存放一个指针即可

Go中没有 float 类型,只有float32float64;没有 double 类型

与操作系统架构无关的,从类型名称也可看出来

  • 整数:int8 int16 int32 int64
  • 无符号整数:uint8 uint16 uint32 uint64
  • 浮点:float32 float64

int型是计算最快的一种类型

整型的零值为 0,浮点型的零值为 0.0

float32精确到小数点后7位,float64精确到小数点后15
使用 == 或 != 比较浮点数时,必需要非常小心

尽可能使用float64math包使用这个较多)

增加前缀 0 来表示 8 进制数(如:077),增加前缀 0x 来表示 16 进制数(如:0xFF),使用 e 来表示 10 的连乘

不允许不同类型的变量之间的混合使用(但常量之间可以混合使用)

复数(fixme)

复数使用 re+imI 来表示,其中 re 代表实数部分,im 代表虚数部分,I 代表根号负 1

complex64 (32 位实数和虚数)
complex128 (64 位实数和虚数)

函数 real(c)imag(c) 可以分别获得相应的实数和虚数部分

使用==!=时注意精度

cmath包含有一些操作复数的公共方法

如果对内存要求不是特别高,最好使用complex128(已有工具包使用这个比较多)

位运算

只能用于整数类型的变量,且需当它们拥有等长位模式时

二元运算符

  • 按位与 &
  • 按位或 |
  • 按位异或 ^
  • 位清除 &^:将指定位置上的值设置为 0

一元运算符

  • 按位补足 ^
  • 位左移 <<
  • 位右移 >>
type ByteSize float64
const (
    _ = iota // 通过赋值给空白标识符来忽略值
    KB ByteSize = 1<<(10*iota)
    MB
    GB
    TB
    PB
    EB
    ZB
    YB
)
逻辑运算符

==!=<<=>>= ==> 因为他们的运算结果总是bool

算术运算符

+-*/

字符串拼接时允许使用+的重载,Go本身不允许开发者进行自定义的运算符重载

/ 对于整数运算而言,结果依旧为整数

取余运算符只能作用于整数

浮点数除以 0.0 会返回一个无穷尽的结果,使用 +Inf 表示

+=-=*=/=%=

整数与浮点数支持自增自减(++--),只有后缀

带有 ++-- 的只能作为语句,而非表达式(例:不允许n = i++这种写法)

在运算时溢出不会产生错误,Go 会简单地将超出位数抛弃

如果需要范围无限大的整数或有理数,可以使用标准库中的big

随机数

math/rand

rand.Float32rand.Float64 返回介于 [0.0, 1.0) 之间的伪随机数

rand.Intn 返回介于 [0, n) 之间的伪随机数

类型别名

type typeAlias type

类型别名得到的新类型和原类型并非完全相同,新类型不会拥有原类型所附带的方法

字符类型

严格来说,字符并不是Go的一个类型,字符只是整数的特殊用例

byteuint8的别名;字符使用单引号括起来

// 字符 A 表示
var ch byte = 65 
// \x 总是紧跟着长度为 2 的 16 进制数
var ch byte = '\x41'

Go 同样支持 Unicode(UTF-8),因此字符同样称为 Unicode 代码点或者 runes ,并在内存中使用 int 来表示

rune 是 Go 当中的一个类型,并且是 int32 的别名

书写 Unicode 字符时,需要在 16 进制数之前加上前缀 \u 或者 \U

unicode 包含了一些针对测试字符的非常有用的函数

  • 判断是否为字母:unicode.IsLetter(ch)
  • 判断是否为数字:unicode.IsDigit(ch)
  • 判断是否为空白符号:unicode.IsSpace(ch)

字符串

是一种值类型,且值不可变

字符串是字节的定长数组

  • 解释字符串:转义字符被替换
    • \n:换行符
    • \r:回车符
    • \t:tab 键
    • \u\U:Unicode 字符
    • \\:反斜杠自身
  • 非解释字符串:反引号,支持换行
`This is a raw string \n` 中的 `\n\` 会被原样输出。

string类型的零值为长度为零的字符串,即空字符串""

一般的比较运算符(==!=<<=>=>)通过在内存中按字节比较来实现字符串的对比

可通过索引来获取字符串的内容(纯字节),索引从 0 开始(str[index];只对纯 ASCII 码的字符串生效)

获取字符串中的某个字节的地址是非法的

使用+实现拼接

不建议在循环中使用+进行字符串拼接,推荐strings.Join()或字节缓冲byts.Buffer(更好)

strings 和 strconv 包

与字符串相关的类型转换通过 strconv 包实现

任何类型 T 转换为字符串总是成功的

将字符串转换为其它类型 tp 并不总是可能的,可能会在运行时抛出错误

数字类型转换到字符串:

  • strconv.Itoa(i int) string 返回数字 i 所表示的字符串类型的十进制数
  • strconv.FormatFloat(f float64, fmt byte, prec int, bitSize int) string 将 64 位浮点型的数字转换为字符串
    • fmt 表示格式(其值可以是 'b''e’、'f''g'
    • prec 表示精度
    • bitSize 则使用 32 表示 float32,用 64 表示 float64

字符串类型转换为数字类型:

  • strconv.Atoi(s string) (i int, err error) 将字符串转换为 int 型
  • strconv.ParseFloat(s string, bitSize int) (f float64, err error) 将字符串转换为 float64 型

日期与时间

time

一般的格式化设计是通过对于一个标准时间的格式化描述来展现的

fmt.Println(t.Format("02 Jan 2006 15:04")) 
// 输出:21 Jul 2011 10:31
fmt.Println(t.Format("2006:01:02 15:04:05")) 
// 输出:2021:12:06 09:12:02

time.Aftertime.Ticker实现程序在经过一定时间或周期执行某项任务

指针

指针对于性能非常重要

取地址符是 &,放到一个变量前使用就会返回相应变量的内存地址

一个指针变量可以指向任何一个值的内存地址 它指向那个值的内存地址,在 32 位机器上占用 4 个字节,在 64 位机器上占用 8 个字节,并且与它所指向的值的大小无关

用一个指针引用一个值被称为间接引用

当一个指针被定义后没有分配到任何变量时,它的值为 nil

一个指针变量通常缩写为 ptr

对于任何一个变量 var, 如下表达式都是正确的:var == *(&var)

不能通过&来获取常量的内存地址

指针也可以指向另一个指针,并且可以进行任意深度的嵌套,导致可以有多级的间接引用,但在大多数情况这会使代码结构不清晰

对一个空指针的反向引用是不合法的,并且会使程序崩溃

func main() {
    var p *int = nil
    *p = 0
}

格式化输出

%t 用于格式化布尔型

%d用于格式化整数

%x%X用于格式化 16 进制表示的数字

%g用于格式化浮点

%f输出浮点数

%e输出科学计数表示法

%0d用于规定输出定长的整数,其中开头的数字 0 必须

%n.mg 用于表示数字 n 并精确到小数点后 m 位,除了使用 g 之外,还可以使用 e 或者 f

%v 来格式化复数,但当你希望只表示其中的一个部分的时候需要使用 %f

%b 用于表示位的格式化标识符

%c 用于格式化字符

%U 输出格式为 U+hhhh 的字符串

%p用于格式化指针

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值