一.运算符
Go语言内置的运算符有:
算术运算符
关系运算符
逻辑运算符
位运算符
赋值运算符
1.1 算术运算符
注意:++(自增)和--(自减)在go语言中是单独的语句,并不是运算符。
1.2 关系运算符
1.3 逻辑运算符
1.4 位运算符
位运算符对整数在内存中的二进制位进行操作。
1.5 赋值运算符
二.变量和常量
1.1 变量
1.1.1 变量声明
Go语言中的变量需要声明后才能使用,同一作用域内不支持重复声明。并且Go语言的变量声明后必须使用。
- 标准声明
Go语言的变量声明格式为:
var 变量名 变量类型
变量声明以关键字var开头,变量类型放在变量的后面,行尾无需分号。
var name string
var age int
var isOk bool
- 批量声明
每声明一个变量就需要写var关键字会比较繁琐,go语言还支持批量声明变量:
var (
a string
b int
c bool
d float32
)
1.1.2 变量初始化
Go语言在声明变量的时候,会自动对变量对应的内存区域进行初始化操作。每一个变量都会被初始化成其类型的默认值,例如:整型和浮点型变量的默认值为0,字符串变量的默认值为空字符串,布尔型变量默认值为false,切片,函数,指针变量的默认值为nil。
当然我们也可以在声明变量的时候为其指定初始值。格式为:
var 变量名 类型 = 表达式
举个例子:
var name string = "zhangsan"
var sex int = 1
或者一次初始化多个变量:
var name, sex = "zhangsan", 1
- 类型推导
有时候我们会将变量的类型忽略,这个时候编译器会根据等号右边的值来推导变量类型完成初始化。
var name = "zhangsan"
var sex = 1
- 短变量声明
在函数内部,可以使用更加简略的 ' := ' 方式声明并初始化变量。
package main
import (
"fmt"
)
//全局变量
var m = 10
func main() {
n := 10
m := 200 //此处声明局部变量m
fmt.Println(m, n)
}
- 匿名变量
在使用多重赋值时,如果想要忽略某个值,可以使用匿名变量。匿名变量用一个下划线_表示:
package main
fmt (
"fmt"
)
func foo() (int, string) {
return 10, "zhangsan"
}
func main() {
x, _ := foo()
_, y := foo()
fmt.Println("x=", x)
fmt.Println("y=", y)
}
匿名变量不占用命令空间,不会分配内存,所以匿名变量之间不存在重复声明。(在Lua等编程语言中,匿名变量也被叫做哑元变量)。
注意事项:
- 函数外的每一个语句都必须以关键字开始(var const func等)。
- :=不能使用在函数外
- _多用于占位,表示忽略值
1.2 常量
1.2.1 简介
相对于变量,常量是恒定不变的值,多用于定义程序运行期间不会改变的值。常量的声明和变量声明非常相似,只是把var换成const,常量在定义的时候必须赋值。
const pi = 3.1415
const e = 2.7182
声明了pi和e这两个变量之后,在整个程序运行期间它们的值都不能再发生变化了。
多个常量也可以一起声明:
const (
pi = 3.1415
e = 2.7182
)
const同时声明多个常量时,如果省略了值则表示和上一行的值相同。
//n1,n2,n3的值都是100
const (
n1 = 100
n2
n3
)
1.2.2 iota
iota是go语言的常量计数器,只能在常量的表达式中使用,iota在const关键字出现是将被重置为0。const中每新增一行常量声明将使iota计数一次(iota可理解为const语句块中的行索引)。使用iota能简化定义,在定义枚举时很有用。
const (
n1 = iota //0
n2 //1
n3 //2
n4 //3
)
1.2.3 iota常见用法
- 使用下划线_跳过某些值
const (
n1 = iota //0
n2 //1
_
n3 //3
)
- iota声明在中间插队
const (
n1 = iota //0
n2 = 100
n3 = iota //2
n4 //3
)
const n5 = iota // 0
- 定义数量级
const (
_ = iota
KB = 1 << (10 * iota) // 1 << (10 * 1)
MB = 1 << (10 * iota) // 1 << (10 * 2)
GB = 1 << (10 * iota) // 1 << (10 * 3)
TB = 1 << (10 * iota) // 1 << (10 * 4)
PB = 1 << (10 * iota) // 1 << (10 * 5)
)
- 多个iota定义在一行
const (
a, b = 1 + iota, 2 + iota // 1 + 0,2 + 0
c, d // 1 + 1, 2 + 1
e, f // 1 + 2, 2 + 3
)
总结:同一行的iota值相同,经过一行,iota值加1,不管有没有用到iota。
三. 基本类型
3.1 基本类型的介绍
Golang更明确的数字类型命名,支持Unicode,支持常用数据结构。
支持八进制,六进制,以及科学记数法。标准库math定义了各数字类型取值范围。
a, b, c, d := 071, 0x1F, 1e9, math.MinInt16
空指针在go语言中是nil,而非C/C++的NULL。
3.1.1 整型
整型分为以下两大类:
- 有符号整型:int8,int16,int32,int64
- 无符号整型:uint8,uint16,uint32,uint64
其中uint8就是我们熟知的byte类型,int16对应C语言的short类型,int64对应C语言中的long类型。
3.1.2 浮点型
Go语言支持两种浮点类型:float32和float64。
这两种浮点型数据格式遵循IEEE 74标准:float32的浮点数最大范围约为3.4e38,可以使用常量定义math.MaxFloat32。float64的浮点数最大范围约为1.8e308,可以使用常量定义math.MaxFloat64。
3.1.3 复数
complex64和complex128
复数有实部和虚部,complex64的实部和虚部为32位,complex128的实部和虚部为64位。
3.1.4 布尔值
Go语言中以bool类型进行声明布尔型数据,布尔型数据只有true(真)和false(假)两个值。
注意:
- 布尔类型变量默认值为false。
- Go语言中不允许将整型强制转换为布尔型。
- 布尔型无法参与数值运算,也无法与其他类型进行转换。
3.1.5 字符串
Go语言中的字符串以原生数据类型出现,使用字符串就像使用其他原生数据类型一样。Go语言里的字符串的内部实现使用UTF-8编码。字符串的值为双引号中的内容,可以在Go语言的源码中直接添加非ASCII码字符。
s1 := "hello"
s2 := "你好"
- 字符串转义字符
Go语言的字符串常见转义符包含回车,换行,单双引号,制表符等:
- 多行字符串
Go语言中需要定义一个多行字符串时,就必须使用反引号字符:
反引号间换行将被作为字符串中的换行,但是所有的转义字符均无效,文本将会原样输出。
- 字符串的常用操作
3.1.6 byte和rune类型
组成每一个字符串的元素叫做字符,可以通过遍历或者单个获取字符串元素获取字符。字符用单引号包裹。
var a = '中'
var b = 'x'
Go语言的字符有以下两种:
uint8类型,或者叫byte类型,代表ASCII码的一个字符。
int32类型,或者叫rune类型,代表一个UTF-8字符。
当需要处理中文,日文或者其他复合字符时,则需要用到rune类型。rune类型实际是一个int32。Go使用特殊的rune类型来处理Unicode,让基于Unicode的文本处理更加方便,也可以使用byte类型进行默认字符串处理,性能和扩展性都有照顾。
因为UTF8编码下一个中文汉字由3~4个字节组成,所以我们不能简单的按照字节去遍历一个包含中文的字符串,否则会出现上面第一行的结果。
字符串底层是一个byte数组,所以可以和[]byte类型相互转换。字符串是不能修改的,字符串是由byte字节组成,所以字符串的长度是byte字节长度。rune类型用来表示utf8字符,一个rune字符由一个或多个byte组成。
一个字符可能由多个byte组成,所以len()字符串变量得到的长度可能大于字符串变量长度,想要得到实际字符串长度,可能先转为[]rune数组,求[]rune数组长度。
package main
import "fmt"
func traversalString(s string) {
fmt.Printf("strlen:%d", len(s))
fmt.Println()
//byte
bt := []byte(s)
for i := 0; i < len(bt); i++ {
fmt.Printf("%v(%c)", bt[i], bt[i])
}
fmt.Println()
//rune
rn := []rune(s)
for i := 0; i < len(rn); i++ {
fmt.Printf("%v(%c)", rn[i], rn[i])
}
fmt.Println()
fmt.Printf("[]rune:%d", len(rn))
}
func main() {
traversalString("pprof.cn博客")
}
- 修改字符串
要修改字符串,需要先将其转换成[]rune或[]byte,完成后再转换成string。无论哪种转换都会重新分配内存,并复制字节数组。
3.1.7 类型转换
Go语言中只有强制类型转换,没有隐式类型转换。并且该语法只能在两个类型之间支持相互转换的时候使用。
强制类型转换的基本语法:
T(表达式)
其中,T表示要转换的类型。表达式包括变量,复杂算子和函数返回值等。
package main
import (
"fmt"
"math"
)
func sqrtDemo() {
var a, b = 3, 4
var c int
//math.Sqrt参数类型是float64类型,需要强制类型转换
//返回值是float64,而c是int类型,需要强制类型转换
c = int(math.Sqrt(float64(a*a + b*b)))
fmt.Println(c)
}
func main() {
sqrtDemo()
}