本文学习Go语言的数据类型。
课题摘要
Go语言的数据类型系统包括基本数据类型、复合数据类型和引用类型。基本数据类型包括布尔型、整数型、浮点型、复数型和字符串。复合数据类型包括数组、切片、结构体、接口。引用类型包括指针、函数类型、通道、映射和错误类型。特殊类型有空接口。布尔型用于逻辑判断,数字类型用于数值表示,字符串用于文本数据表示。每种类型都有其特定的使用场景和内存占用。
一、基本数据类型
-
布尔型 (bool):表示逻辑值,仅有两个可选值
true
或false
。var isTrue bool = true var isFalse bool = false
-
整数型:
- 有符号整数:int8、int16、int32(通常对应C中的short)、int64(通常对应C中的long long)。
- 无符号整数:uint8(等同于byte)、uint16、uint32、uint64。
var i int8 = -128 // 最小值为-128,最大值为127 var u uint32 = 4294967295 // 最大值为 2^32 - 1
-
浮点型:
- float32:32位IEEE-754浮点数。
- float64:64位IEEE-754浮点数,这是Go中默认的浮点数类型。
var f float32 = 3.14159265 // 浮点数 var pi float64 = math.Pi // 使用math库中的π常数
-
复数型:
- complex64:由两个32位浮点数(实部和虚部)组成。
- complex128:由两个64位浮点数组成。
var c complex64 = 3 + 4i // 复数
-
字符串 (string):不可变的字符序列,使用UTF-8编码。
var s string = "Hello, World!" // 字符串
二、复合数据类型
-
数组 (array):固定长度的同类型元素集合,其长度在声明时必须确定。
var a [5]int // 声明一个包含5个整数的数组
-
切片 (slice):动态大小的、灵活的数组视图,它不拥有底层数据,而是指向底层数组的一个片段。
var s []int = make([]int, 0, 5) // 创建一个初始长度为0,容量为5的整数切片
-
结构体 (struct):用户自定义的数据类型,可以包含多个成员,每个成员可以是不同类型的变量。
type Person struct { Name string Age int } var p Person p.Name = "Alice" p.Age = 30
-
接口 (interface):定义了一组方法签名,任何实现了这些方法的类型都实现了该接口。
type Writer interface { Write(p []byte) (n int, err error) } type MyWriter struct {} func (w MyWriter) Write(p []byte) (n int, err error) { ... }
三、引用类型
-
指针 (pointer):存储变量内存地址的类型,允许直接操作内存中的值。
var x int = 10 var p *int = &x // 指针p指向变量x的地址 *p = 20 // 通过指针修改x的值
-
函数类型 (function type):可以像其他任何类型一样声明和赋值,允许作为参数传递或从函数返回。
func add(a, b int) int { return a + b } var myFunc func(int, int) int = add
-
通道 (channel):用于并发编程的通信机制,用于goroutine之间的同步和数据传输。
ch := make(chan int) // 创建一个int类型的通道 go func() { ch <- 42 // 向通道发送一个值 }() value := <-ch // 从通道接收一个值
-
映射 (map):关联键值对的数据结构,键和值可以是任意类型。
m := make(map[string]int) m["apple"] = 10
-
错误类型 (error):虽然不是内置类型,但error是一种广泛使用的接口类型,用于表示运行时错误。
四、特殊类型
- 空接口 (interface{}):不包含任何方法的接口,它可以容纳任何类型的值。
以上是对Go语言主要数据类型的详解。通过这些类型,开发者可以在Go程序中构建复杂的抽象,并实现高效的内存管理和类型安全。
数据类型需要通过实际应用来深入掌握。在后续内容中将逐步展开。
五、布尔类型(bool)
在Go语言中,布尔类型(bool)是一种基本数据类型,用于表示逻辑值,即真或假、是或否的情况。它主要用于条件判断和逻辑运算。
(一)定义与取值
- Go语言中的布尔类型关键字为
bool
。 - 布尔类型的变量只能有两个可能的取值:
true
和false
。 - 默认情况下,未初始化的布尔类型的变量值为
false
。
(二)声明布尔变量
var isDone bool // 未初始化,默认为 false
var isActive = true // 初始化为 true
var isReady := false // 简短声明方式,初始化为 false
(三)使用场景
- 条件语句:在
if
、for
、switch
等条件控制结构中作为判断条件。if isActive { fmt.Println("Task is active.") }
- 逻辑运算:通过比较运算符(如
==
,!=
,<
,>
,<=
,>=
)、逻辑运算符(&&
(逻辑与),||
(逻辑或),!
(逻辑非))生成新的布尔值。result := (x > 0) && (y < 10)
(四)大小与内存占用
- 在Go语言中,一个布尔类型的变量占用 1 个字节(byte)的内存空间。
(五)转换与类型安全
- Go语言中布尔类型与其他类型之间不能隐式转换,也就是说,你不能直接将整型或其他类型的数据赋给布尔变量,必须显式进行类型转换。
- 在实际编程中,通常会通过检查某个表达式的真假来决定布尔变量的值,而不是直接转换其他类型的数据。
(六)常用于流程控制
- 布尔类型的变量在程序流程控制中扮演着核心角色,它们决定了代码块是否执行以及循环何时终止等关键行为。
总结来说,Go语言中的布尔类型提供了一种简洁有效的方式来处理程序中的逻辑状态,它是实现复杂业务逻辑的基础构建块之一。
六、数字类型
在Go语言中,数字类型是其丰富数据类型的一部分,主要用于表示数值。
以下是Go语言中主要的数字类型详解:
1. 整数类型(Integer Types)
a) 固定长度整数:
-
有符号整数:
int8
:8位带符号整数,范围从-128到127。int16
:16位带符号整数,范围从-32,768到32,767。int32
:32位带符号整数,范围从-2,147,483,648到2,147,483,647。int64
:64位带符号整数,范围从-9,223,372,036,854,775,808到9,223,372,036,854,775,807。
-
无符号整数:
uint8
或byte
:8位无符号整数,范围从0到255。uint16
:16位无符号整数,范围从0到65,535。uint32
:32位无符号整数,范围从0到4,294,967,295。uint64
:64位无符号整数,范围从0到18,446,744,073,709,551,615。
b) 变长整数:
int
和uint
:长度取决于运行时平台,在32位系统上通常是32位,在64位系统上通常是64位。uintptr
:无符号整数类型,足够容纳指针值。它的大小同样依赖于目标架构。
2. 浮点数类型(Floating-Point Types)
float32
:遵循IEEE-754标准的32位浮点数,提供大约7个有效数字精度。float64
:遵循IEEE-754标准的64位浮点数,通常提供约15位有效数字精度,这是Go语言中最常用的浮点数类型。
3. 复数类型(Complex Number Types)
complex64
:由两个32位浮点数(实部和虚部)组成的复数,每个部分分别使用float32存储。complex128
:由两个64位浮点数(实部和虚部)组成的复数,每个部分分别使用float64存储。
4. 类型转换
不同类型的数字之间不能隐式转换,需要通过显式类型转换操作来完成,例如:
var i int32 = 100
var u uint64 = uint64(i)
5. 数字字面量
Go语言支持以十进制、八进制(前缀0o
或0O
)、十六进制(前缀0x
或0X
)等方式书写数字字面量。
6. 注意事项
在使用数字类型时,需要注意可能发生的溢出错误。Go语言不会阻止整数类型的溢出操作,而是采用无符号整数的模运算方式处理,这意味着当增加一个正数超过最大值或减少一个负数低于最小值时,数值会“绕回”到相应的另一端。对于防止溢出,程序员应自行确保计算过程的安全性。
实例
package main
import (
"fmt"
"math"
"unsafe"
)
func main() {
var i8 int8
var i16 int16
var i32 int32
var i64 int64
var ui8 uint8
var ui16 uint16
var ui32 uint32
var ui64 uint64
fmt.Printf("%T %dB %v~%v\n", i8, unsafe.Sizeof(i8), math.MinInt8, math.MaxInt8)
fmt.Printf("%T %dB %v~%v\n", i16, unsafe.Sizeof(i16), math.MinInt16, math.MaxInt16)
fmt.Printf("%T %dB %v~%v\n", i32, unsafe.Sizeof(i32), math.MinInt32, math.MaxInt32)
fmt.Printf("%T %dB %v~%v\n", i64, unsafe.Sizeof(i64), math.MinInt64, math.MaxInt64)
fmt.Printf("%T %dB %v~%v\n", ui8, unsafe.Sizeof(ui8), 0, math.MaxUint8)
fmt.Printf("%T %dB %v~%v\n", ui16, unsafe.Sizeof(ui16), 0, math.MaxUint16)
fmt.Printf("%T %dB %v~%v\n", ui32, unsafe.Sizeof(ui32), 0, math.MaxUint32)
fmt.Printf("%T %dB %v~%v\n", ui64, unsafe.Sizeof(ui64), 0, uint64(math.MaxUint64))
var f32 float32
var f64 float64
fmt.Printf("%T %dB %v~%v\n", f32, unsafe.Sizeof(f32), -math.MaxFloat32, math.MaxFloat32)
fmt.Printf("%T %dB %v~%v\n", f64, unsafe.Sizeof(f64), -math.MaxFloat64, math.MaxFloat64)
var ui uint
ui = uint(math.MaxUint64) //再+1会导致overflows错误
fmt.Printf("%T %dB %v~%v\n", ui, unsafe.Sizeof(ui), 0, ui)
var imax, imin int
imax = int(math.MaxInt64) //再+1会导致overflows错误
imin = int(math.MinInt64) //再-1会导致overflows错误
fmt.Printf("%T %dB %v~%v\n", imax, unsafe.Sizeof(imax), imin, imax)
}
运行结果:
int8 1B -128~127
int16 2B -32768~32767
int32 4B -2147483648~2147483647
int64 8B -9223372036854775808~9223372036854775807
uint8 1B 0~255
uint16 2B 0~65535
uint32 4B 0~4294967295
uint64 8B 0~18446744073709551615
float32 4B -3.4028234663852886e+38~3.4028234663852886e+38
float64 8B -1.7976931348623157e+308~1.7976931348623157e+308
uint 8B 0~18446744073709551615
int 8B -9223372036854775808~9223372036854775807
七、字符串类型
在Go语言中,字符串(string)是一种基本的数据类型,用于表示文本数据。它是一个不可变的字符序列,由UTF-8编码的字节组成,支持Unicode字符集。
-
定义:
- Go中的字符串是由双引号
"
包围的一系列字符。
var greeting string = "Hello, 世界"
- Go中的字符串是由双引号
-
内部实现:
- 在内存中,字符串实际上是通过一个字节数组(
[]byte
)来存储的,并且该数组的内容是只读的,因此字符串本身是不可修改的。 - 字符串的实际长度等于其包含的字节数,但它的有效字符数量取决于实际的UTF-8编码序列。
- 在内存中,字符串实际上是通过一个字节数组(
-
Unicode支持:
- Go语言原生支持Unicode字符,这意味着你可以直接在字符串中使用任何Unicode字符或代码点。
s := "😀😃😄" // 这是一个包含三个表情符号的字符串
-
操作与方法:
- 虽然字符串不可变,但可以通过函数和方法进行连接、复制、查找、替换等操作。
package main import ( "fmt" "strings" ) func main() { str1 := "Hello" str2 := "World" combined := str1 + " " + str2 // 字符串拼接 fmt.Println(combined) // 输出:Hello World lowerStr := strings.ToLower("Golang") // 转为小写 fmt.Println(lowerStr) // 输出:golang contains := strings.Contains(combined, "Wor") // 检查子串存在性 fmt.Println(contains) // 输出:true replaced := strings.Replace(combined, "World", "Universe", -1) // 替换子串 fmt.Println(replaced) // 输出:Hello Universe }
- 虽然字符串不可变,但可以通过函数和方法进行连接、复制、查找、替换等操作。
-
转换:
- 可以将字符串转换为字节切片(
[]byte
),反之亦然。str := "example" bytes := []byte(str) newStr := string(bytes)
- 可以将字符串转换为字节切片(
-
原始字符串(Raw String Literals):
- 原始字符串允许在字符串内容中直接包含换行符和反斜杠,而无需转义。
raw := `This is a multiline string. The backslash \ does not need to be escaped here.`
- 原始字符串允许在字符串内容中直接包含换行符和反斜杠,而无需转义。
-
空字符串:
- 空字符串用双引号包围的零长度字符序列表示:
""
。
- 空字符串用双引号包围的零长度字符序列表示:
总的来说,Go语言中的字符串设计旨在简化对Unicode文本的处理,同时提供了丰富的标准库函数来进行高效的操作和管理。
字符串类型使用率最高。