基础数据类型:数字、字符串、布尔型
复合数据类型:数组、结构体
引用数据类型:指针、切片、字典、函数、通道,他们都是对程序中一个变量或状态的间接引用,即对引用类型数据的修改会影响所有该引用的拷贝
接口类型:是对其他类型行为的抽象和概括
Go语言提供了有符号和无符号类型的整数运算。按照长度划分:
有符号: int8、int16、int32、in64
无符号:uint8、uint16、uint32、uint64
类型 | 描述 |
---|---|
int8 | 有符号8位整型(-128-127) |
int16 | 有符号16位整型(-32768-32767) |
int32 | 有符号32位整型 (-(2^31) - (2^31-1)) |
int64 | 有符号64位整型(- (2^63)- (2^63-1)) |
uint8 | 无符号8位整型(0-255) |
uint16 | 无符号16位整型(0-65535) |
uint32 | 无符号32位整型 (0 - (2^32-1)) |
uint64 | 无符号64位整型 (0 - (2^64-1)) |
类型 | 描述 |
---|---|
int | 应用最广泛的数据类型,32位系统int32,64位操作系统int64 |
uint | 32位操作系统uint32,64位操作系统就是uint64 |
uintptr | 无符号整型,适用于底层编程,存储指针 |
rune | Unicode的rune类型等价于int32,常用来处理unicode或utf-8字符 |
byte | byte类型等价于int8,byte用于强调数值是一个原始的数据而不是一个小的整数。常用来处理ascii字符 |
注:在涉及到二进制传输、读写文件的结构描述时,为了保持文件的结构不会受到不同编译目标平台字节长度影响,不要使用int和uint。
go语言中没有内置 int 类型的最大值和最小值方法
无符号整型
const UINT_MIN uint = 0
const UINT_MAX uint =^uint(0)
有符号整型
最大值: 二进制补码,第一位为0 ,其余为1
const INT_MAX = int(^uint(0)>>1)
最小值:第一位为1,其余为0
const INT_MIN = ^INT_MAX
在go语言中整型不同长度之间是不允许进行计算的,比如
var i uint32 = 111
var j uint64 = 222
fmt.Println(i + j)
//会抛出异常
"invalid operation: i + j (mismatched types uint32 and uint64)"
尽管go语言提供了无符号整型,我们在编程中还是倾向于使用有符号整型,比如数组长度,虽然使用无符号更加的合理,但go的内置函数len()依然返回的是有符号整型。
var temp = [3]int{1, 2, 3}
for i := len(temp); i >= 0; i-- {
fmt.Println(i)
}
试想一下,如果len()返回的是无符号的int,那么i>=0
永远为真,此循环无法结束。
无符号数往往只有在位运算或其他特殊的场景才会使用,就像bit集合、分析二进制文件格式或者哈希和加密操作等。它们通常并不用于仅仅是表达非负数量的场合。
go语言支持两种浮点数: float32
和 float64
。
取值范围在math
math.MaxFloat32 //大约 3.4e38
math.MaxFloat64 //大约 1.8e308
math.SmallestNonzeroFloat32 //大约1.40e-45
math.SmallestNonzeroFloat64 //大约4.9e-324
float32的有效bit位只有23个,其它的bit位用于指数和符号,当整数大于23bit能表达的范围时,float32的表示将出现误差。
var f float32 = 1 << 24
fmt.Println(f == f+1) // true
%g
、%f
、%e
常用浮点型打印的区别
//%g更紧凑的输出方式(无末尾0) 精度为所有数字的总数
var x = 123.45
fmt.Printf("%.4g", x) //123.5
//%f 有小数点而无指数
fmt.Printf("%6.2f", x) //123.45
//%e 科学计数法
fmt.Printf("%.4e", y) //1.2345e+02
var y = 123.56789123
// %e和%f默认精度是6
fmt.Printf("%e", y) //1.235679e+02
fmt.Printf("%f", y) //123.567891
go语言提供了2种精度的复合类型:complex64和complex128。分别对应float32和float64的精度。内置的complex函数用于构建复数,real和imag函数分别返回复数的实部和虚部。对于comple64的复数,其实部和虚部都为32位。complex128实部和虚部为64位。
//复数
var z complex128 = complex(1, 2)
fmt.Println(z)
fmt.Println(real(z))
fmt.Println(imag(z))
math.cmplx包中提供了许多复数的运算。
布尔型的值只有true和false两种。
!true == false
对于布尔型可以使用一元操作符。
布尔值也支持使用&&、|| 操作符。
与一些语言不同的是,go语言中的布尔值并不会隐式的转换成0或者1,必须使用辅助函数进行转换。
布尔值默认值是false。
go语言中的字符串的内部实现使用的是UTF-8
编码。文本字符串通常被解释为采用UTF-8
编码的Unicode(rune)序列。
字符串是不可改变的字节序列,也就是说字符串定义后不可以改变。不可变性使得字符串复制和切片的代价是极低的,因为他们可以底层共用数据结构。
var str1 string = "hello world"
str1[0] = 'w' // 编译不过,因为字符串不可改变
子字符串s[i:j] 是从第i位开始到第j位,左闭右开区间。如果左端省略则为0,如果右端省略则为len(s)。len() 是内部方法,返回一个字符串的长度。
str1 := "hello world"
fmt.Println(str1[:5]) //hello
fmt.Println(str1[6:]) //world
fmt.Println(str1[1:3]) //el
使用+
号可以对字符串进行拼接,并返回一个新的字符串。
strLeft := "你好"
fmt.Println(strLeft + " " + str1[:5])
go语言中的字符串使用双引号""
来表示。
常见的转义符包含回车、换行、单双引号、制表符等
转义符 | 含义 |
---|---|
\n | 换行符 |
\r | 回车符 |
\t | 制表符 |
\v | 垂直制表符 |
\’ | 单引号 |
\" | 双引号 |
\\ | 反斜杠 |
多行文本使用``来表示
multiline := ` this is go
two line
`
计算机早期时,使用的是7bit来表示的ASCII字符集,随着计算机的发展,需要文本表示的语言字符丰富多彩,Unicode 的出现是为了处理这些丰富多样的文本数据。
Unicode 第八版本中就收集了超过120000的字符,每个字符都分配一个唯一的Unicode码点,Unicode码点对应着go语言中的rune(int32)。
UTF-8是Unicode的标准,它的出现是为了解决Unicode 码点为int32 这种浪费存储空间的表示方法的。
UTF-8编码使用1-4个字节来表示每个Unicode码点,ASCII部分字符只使用1个字节,常用字符部分使用2或3个字节表示,每个符号编码后第一个字节的高端bit位用于表示编码总共有多少个字节。如果第一个字节的高端bit为0,则表示对应7bit的ASCII字符,ASCII字符每个字符依然是一个字节,和传统的ASCII编码兼容。如果第一个字节的高端bit是110,则说明需要2个字节;后续的每个高端bit都以10开头。
0xxxxxxx runes 0-127 (ASCII)
110xxxxx 10xxxxxx 128-2047 (values <128 unused)
1110xxxx 10xxxxxx 10xxxxxx 2048-65535 (values <2048 unused)
11110xxx 10xxxxxx 10xxxxxx 10xxxxxx 65536-0x10ffff (other values unused)
标准库有4个包对于字符串的处理非常重要。
strings常用方法
方法 | 含义 |
---|---|
len(s) | 字符串的长度 |
+或者fmt.Sprintf() | 字符串拼接 |
strings.LastIndex() 、strings.Index() | 子串出现的位置 |
strings.Split() | 字符串切割 |
strings.Contains(s, substr string) | 字串包含 |
strings.Join(elems []string, sep string) | 字符串join |
strings.Count(s, sep string) int | 返回字符串中字符的个数 |
strings.func HasPrefix(s, prefix string) bool | 前缀/后缀判断 |
go语言中的字符分为byte类型和rune类型
byte类型为uint8,通常用来表示一个ascii
rune 类型为int32,通常用来处理中文、日文等。
ss := "hello 世界"
for i := 0; i < len(ss); i++ { //byte
fmt.Printf("%v", ss[i])
}
fmt.Println()
for _, r := range ss { //rune
fmt.Printf("%v", r)
}
string和byte之间的转换
s := "abc"
b := []byte(s)
fmt.Println(b) //[97 98 99]
s2 := string(b)
fmt.Println(s2) //abc
转换的本质是 新开辟了一个字节数组来保存字符串数据的拷贝,然后引用这个底层的字节数组。以确保更改[]byte b不会引起s的改变。string(b)的操作是构造一个字符串的拷贝,以确保s2是只读的。
string和int之间的转换
// int ->string
x := 123
y := fmt.Sprintf("%d", x)
fmt.Println(y, strconv.Itoa(x)) // "123 123"
// string -> int
z, err := strconv.ParseInt(y, 10, 64) // base 10, up to 64 bits
if err != nil {
return
}
fmt.Println(z)
常量表达式的值在编译期计算,而不是在运行期。每种常量的潜在类型都是基础类型:boolean、string或数字。常量值不可修改。
const pi = 3.14159
//或者定义多行
const (
e = 2.71828182845904523536028747135266249775724709369995957496696763
pi = 3.14159265358979323846264338327950288419716939937510582097494459
)
定义多行常量时,除了第一行外,其他行右侧赋值都可以省略,默认使用第一行的赋值。
const (
a = 1
b
c = 2
d
)//1 1 2 2
iota 是go语言的常量计数器,只能在常量的表达式中使用。
iota在const 关键字出现时 被置为0
const中每新增一行常量声明,iota就增加1
const(
n1 = iota //0
n2 //1
n3 //2
n4 //3
)
const n5 = iota //0