🐇明明跟你说过:个人主页
🏅个人专栏:《Go语言探索之旅》🏅
🔖行路有良友,便是天堂🔖
一、引言
1、Go语言简介
Go语言,又称Golang,是由Google公司开发的一种现代编程语言。它起源于2007年,并在2009年正式对外发布。Go语言旨在提高软件开发的效率、可靠性和可维护性,特别在处理并发性方面表现出色。
2、Go语言特点
- 并发性支持:Go语言内置并发性支持,允许开发者构建高度并发和可扩展的应用。它提供了goroutine(轻量级线程)和channel(通信管道)等功能,简化了并发编程。
- 垃圾回收:Go语言拥有高效的垃圾回收机制,自动释放不再使用的内存。这减轻了开发者管理内存的负担,提高了程序的稳定性和可靠性。
- 类型安全:Go语言是一种强类型语言,提供了严格的类型检查机制。这有助于捕获类型错误,确保代码的可靠性。
- 跨平台性:Go语言编译成可执行文件后,可以在不同的操作系统(如Linux、Windows、macOS)上运行,无需进行重新编译。
- 高性能:Go语言编译器生成高度优化的机器代码,使程序运行速度快且资源消耗低。它特别适合处理高并发和数据密集型应用。
二、变量
1、变量的声明与初始化
1. 使用 var 关键字声明变量
使用 var 关键字声明变量是最基本的形式。可以声明一个或多个变量,并分别初始化它们:
var (
x int // 声明一个 int 类型的变量 x
y string // 声明一个 string 类型的变量 y
z float64 // 声明一个 float64 类型的变量 z
)
// 初始化变量
x = 10
y = "hello"
z = 3.14
2. 使用 := 简化声明和初始化
如果想要在声明的同时初始化变量,可以使用 := 运算符,这种方式被称为“简短变量声明”。这种方式只在函数内部有效:
a := 10 // 声明并初始化一个 int 类型的变量 a
b := "world" // 声明并初始化一个 string 类型的变量 b
c := 2.718 // 声明并初始化一个 float64 类型的变量 c
3. 同时声明多个变量
可以在一行中声明并初始化多个变量:
var (
d int = 100 // 声明并初始化一个 int 类型的变量 d
e string = "Go" // 声明并初始化一个 string 类型的变量 e
f float64 = 1.618 // 声明并初始化一个 float64 类型的变量 f
)
或者使用简短声明:
g, h, i := 1000, "Programming", 3.14159
4. 使用 new 函数
new 函数可以用来为变量分配内存,并返回指向该内存的指针:
j := new(int) // 分配 int 类型的内存,并返回指向该内存的指针
*k := 1000 // 给指针 k 所指向的 int 类型内存赋值
5. 使用 make 函数
对于某些类型(如切片、映射和通道),需要使用 make 函数来初始化:
slice := make([]int, 5) // 创建一个长度为 5 的 int 类型切片
mapVar := make(map[string]int) // 创建一个 string 到 int 的映射
channel := make(chan int) // 创建一个 int 类型的通道
6. 匿名变量
在某些情况下,可能会使用匿名变量(通常写作 _),主要用于忽略不需要的返回值:
_, err := os.Open("file.txt") // 忽略第一个返回值
if err != nil {
log.Fatal(err)
}
7. 初始化复合类型
可以一次性初始化数组、切片、映射等复合类型:
// 数组
arr := [3]int{1, 2, 3}
// 切片
slice := []int{1, 2, 3}
// 映射
mapVar := map[string]int{"one": 1, "two": 2, "three": 3}
2、变量的作用域
在 Go 语言中,变量的作用域决定了变量的可见性和生命周期。作用域的定义有助于避免命名冲突,并确保变量在适当的时候被创建和销毁。Go 语言中的变量作用域主要有以下几种:
1. 包级变量(Package-Level Variables)
包级变量在整个包内可见,并且在整个程序运行期间存在。这类变量通常用于在包内共享状态。
package main
var globalVar int // 包级变量
func main() {
globalVar = 10
fmt.Println(globalVar)
}
2. 函数级变量(Function-Level Variables)
函数级变量在一个函数的范围内可见,并且在函数被调用时创建,在函数返回时销毁。
package main
import "fmt"
func main() {
funcLevelVar := 10 // 函数级变量
fmt.Println(funcLevelVar)
}
3. 块级变量(Block-Level Variables)
块级变量在一个代码块(由 {} 围绕的部分)内可见,并且在进入该代码块时创建,在离开该代码块时销毁。
package main
import "fmt"
func main() {
if true {
blockLevelVar := 10 // 块级变量
fmt.Println(blockLevelVar)
}
// blockLevelVar 不可见
}
4. 形参(Function Parameters)
函数的形参在函数调用时创建,并在函数返回时销毁。形参的作用域限于函数体内。
package main
import "fmt"
func printSum(a, b int) { // 形参 a 和 b
sum := a + b
fmt.Println(sum)
}
func main() {
printSum(3, 4)
}
5. 循环变量
在循环中声明的变量在循环体内可见,并且在每次迭代时创建,在迭代结束后销毁。
package main
import "fmt"
func main() {
for i := 0; i < 5; i++ { // 循环变量 i
fmt.Println(i)
}
// i 在循环外部不可见
}
6. 闭包中的外部变量
在闭包中,闭包可以访问定义在其外围作用域中的变量。这些变量的作用域扩展到了闭包的生命周期内。
package main
import "fmt"
func main() {
x := 10 // 外围作用域中的变量
f := func() {
fmt.Println(x)
}
f() // 输出 x 的值
}
7. 匿名变量
匿名变量(通常写作 _)用于忽略不需要的返回值或变量。
package main
import (
"fmt"
"os"
)
func main() {
_, err := os.Open("file.txt")
if err != nil {
fmt.Println("Error opening file:", err)
}
}
三、数据类型
1、基本数据类型
1. 整数类型(int,uint,byte等)
整数类型用于表示整数值,包括有符号整数和无符号整数。
有符号整数类型
- int:默认的整数类型,其大小取决于操作系统(32位或64位)。
- int8:8位有符号整数,范围为 -128 到 127。
- int16:16位有符号整数,范围为 -32768 到 32767。
- int32:32位有符号整数,范围为 -2^31 到 2^31-1。
- int64:64位有符号整数,范围为 -2^63 到 2^63-1。
无符号整数类型
- uint:默认的无符号整数类型,其大小取决于操作系统(32位或64位)。
- uint8:8位无符号整数,范围为 0 到 255。
- byte:别名类型,等同于 uint8。
- uint16:16位无符号整数,范围为 0 到 65535。
- uint32:32位无符号整数,范围为 0 到 2^32-1。
- uint64:64位无符号整数,范围为 0 到 2^64-1。
- uintptr:用于存储指针地址的整数类型,其大小取决于操作系统(32位或64位)。
2. 浮点类型
浮点类型用于表示带有小数部分的数字。
- float32:32位浮点数,约7位精度。
- float64:64位浮点数,约15位精度。
3. 布尔类型
布尔类型用于表示真或假的值。
- bool:布尔值,可以是 true 或 false。
4. 字符串类型
字符串类型用于表示文本。
- string:用于表示文本的字符串类型。
5. 复数类型
复数类型用于表示具有实部和虚部的数值。
- complex64:包含实部和虚部的32位复数。
- complex128:包含实部和虚部的64位复数。
示例代码
package main
import (
"fmt"
)
func main() {
// 整数类型
var intVar int = 42
var int8Var int8 = -128
var int16Var int16 = 32767
var int32Var int32 = 2147483647
var int64Var int64 = 9223372036854775807
var uintVar uint = 42
var uint8Var uint8 = 255
var uint16Var uint16 = 65535
var uint32Var uint32 = 4294967295
var uint64Var uint64 = 18446744073709551615
var byteVar byte = 'A' // 等同于 uint8
var uintptrVar uintptr = 12345
// 浮点类型
var float32Var float32 = 3.14
var float64Var float64 = 3.1415926535
// 布尔类型
var boolVar bool = true
// 字符串类型
var stringVar string = "Hello, World!"
// 复数类型
var complex64Var complex64 = 3 + 4i
var complex128Var complex128 = 3 + 4i
// 输出变量的值
fmt.Printf("intVar = %d\n", intVar)
fmt.Printf("int8Var = %d\n", int8Var)
fmt.Printf("int16Var = %d\n", int16Var)
fmt.Printf("int32Var = %d\n", int32Var)
fmt.Printf("int64Var = %d\n", int64Var)
fmt.Printf("uintVar = %d\n", uintVar)
fmt.Printf("uint8Var = %d\n", uint8Var)
fmt.Printf("uint16Var = %d\n", uint16Var)
fmt.Printf("uint32Var = %d\n", uint32Var)
fmt.Printf("uint64Var = %d\n", uint64Var)
fmt.Printf("byteVar = %c\n", byteVar)
fmt.Printf("uintptrVar = %d\n", uintptrVar)
fmt.Printf("float32Var = %f\n", float32Var)
fmt.Printf("float64Var = %f\n", float64Var)
fmt.Printf("boolVar = %t\n", boolVar)
fmt.Printf("stringVar = %s\n", stringVar)
fmt.Printf("complex64Var = %v\n", complex64Var)
fmt.Printf("complex128Var = %v\n", complex128Var)
}
2、复合数据类型
Go 语言提供了多种复合数据类型来处理更复杂的数据结构。以下是一些常见的复合数据类型及其描述:
1. 数组(Array)
数组是一种固定大小的序列类型,用于存储相同类型的元素。数组的长度在声明时确定,并且不可改变。
package main
import "fmt"
func main() {
// 声明并初始化数组
var numbers [5]int = [5]int{1, 2, 3, 4, 5}
// 访问数组元素
fmt.Println("numbers[0] =", numbers[0])
fmt.Println("numbers[4] =", numbers[4])
// 遍历数组
for i := range numbers {
fmt.Println("numbers[", i, "] =", numbers[i])
}
// 声明并初始化不同类型的数组
var letters = [5]string{"a", "b", "c", "d", "e"}
var floats = [5]float64{1.1, 2.2, 3.3, 4.4, 5.5}
// 打印数组
fmt.Println("letters =", letters)
fmt.Println("floats =", floats)
}
- 切片(Slice)
切片是基于数组的一种动态数据结构,它可以动态地增长和缩减。切片提供了一种灵活的方式来管理序列数据。
package main
import "fmt"
func main() {
// 声明并初始化切片
var numbers = []int{1, 2, 3, 4, 5}
// 访问切片元素
fmt.Println("numbers[0] =", numbers[0])
fmt.Println("numbers[4] =", numbers[4])
// 遍历切片
for i, v := range numbers {
fmt.Println("numbers[", i, "] =", v)
}
// 修改切片
numbers[0] = 10
fmt.Println("Modified numbers =", numbers)
// 切片的追加
numbers = append(numbers, 6)
fmt.Println("Appended numbers =", numbers)
// 切片的切分
subSlice := numbers[1:4]
fmt.Println("Subslice =", subSlice)
}
- 映射(Map)
映射是一种关联类型,它通过键值对来存储数据。键必须是可比较的类型(如 int、string、struct 等),值可以是任意类型。
package main
import "fmt"
func main() {
// 声明并初始化映射
var ageMap = map[string]int{
"Alice": 30,
"Bob": 25,
"Charlie": 22,
}
// 访问映射元素
fmt.Println("ageMap[Alice] =", ageMap["Alice"])
fmt.Println("ageMap[Bob] =", ageMap["Bob"])
// 遍历映射
for key, value := range ageMap {
fmt.Println("key =", key, "value =", value)
}
// 修改映射
ageMap["Alice"] = 31
fmt.Println("Updated ageMap =", ageMap)
// 添加新的键值对
ageMap["David"] = 28
fmt.Println("Updated ageMap =", ageMap)
// 删除映射中的键值对
delete(ageMap, "Charlie")
fmt.Println("Updated ageMap =", ageMap)
}
- 结构体(Struct)
结构体是一种自定义的数据类型,它允许你组合不同的数据类型来形成新的类型。
package main
import "fmt"
type Person struct {
Name string
Age int
Address Address
}
type Address struct {
Street string
City string
}
func main() {
// 声明并初始化结构体
var person = Person{
Name: "Alice",
Age: 30,
Address: Address{
Street: "123 Main St",
City: "Anytown",
},
}
// 访问结构体成员
fmt.Println("person.Name =", person.Name)
fmt.Println("person.Age =", person.Age)
fmt.Println("person.Address.Street =", person.Address.Street)
fmt.Println("person.Address.City =", person.Address.City)
}
3、类型转换
在 Go 语言中,类型转换是指将一个变量或表达式的类型转换为另一种类型。类型转换在某些情况下是必要的,尤其是在需要将一种类型的数据作为另一种类型来处理时。
基本类型转换
1. 整数类型转换
将整数类型从一种转换为另一种类型,例如从 int 转换为 int32。
import "fmt"
func main() {
var i int = 10
var i32 int32 = int32(i) // 类型转换
fmt.Printf("Original integer: %d, Converted integer: %d\n", i, i32)
}
- 浮点数类型转换
将浮点数类型从一种转换为另一种类型,例如从 float32 转换为 float64。
package main
import "fmt"
func main() {
var f32 float32 = 3.14
var f64 float64 = float64(f32) // 类型转换
fmt.Printf("Original float32: %f, Converted float64: %f\n", f32, f64)
}
- 字符串到整数类型转换
将字符串类型转换为整数类型,例如从 string 转换为 int。
package main
import (
"fmt"
"strconv"
)
func main() {
s := "123"
i, err := strconv.Atoi(s) // 字符串转整数
if err == nil {
fmt.Printf("Converted integer: %d\n", i)
} else {
fmt.Println("Conversion error:", err)
}
}
4. 整数到字符串类型转换
将整数类型转换为字符串类型,例如从 int 转换为 string。
package main
import (
"fmt"
"strconv"
)
func main() {
i := 123
s := strconv.Itoa(i) // 整数转字符串
fmt.Printf("Converted string: %s\n", s)
}
复合类型转换
5. 切片到数组类型转换
将切片转换为数组,需要注意的是,切片和数组的长度必须相等。
package main
import "fmt"
func main() {
s := []int{1, 2, 3}
var a [3]int
copy(a[:], s) // 切片转数组
fmt.Printf("Converted array: %v\n", a)
}
- 数组到切片类型转换
将数组转换为切片,可以通过切片操作来实现。
package main
import "fmt"
func main() {
a := [3]int{1, 2, 3}
s := a[:] // 数组转切片
fmt.Printf("Converted slice: %v\n", s)
}
7. 映射(Map)相关的类型转换
在映射中,键和值的类型转换通常在插入或检索时进行。
package main
import "fmt"
func main() {
m := map[string]int{
"one": 1,
"two": 2,
"three": 3,
}
val, ok := m["one"]
if ok {
strVal := strconv.Itoa(val) // 将整数转换为字符串
fmt.Printf("Converted value: %s\n", strVal)
}
}
- 结构体类型转换
在某些情况下,可能需要将结构体转换为另一种类型,例如将一个结构体嵌入另一个结构体。
package main
import "fmt"
type Point struct {
X int
Y int
}
type Circle struct {
Point
Radius int
}
func main() {
p := Point{X: 10, Y: 20}
c := Circle{Point: p, Radius: 5} // 结构体嵌入
fmt.Printf("Circle: %+v\n", c)
}
- 类型断言
类型断言用于从接口(interface)中提取具体的类型值。
package main
import (
"fmt"
)
func main() {
var i interface{} = "hello"
if str, ok := i.(string); ok {
fmt.Println("String value:", str)
}
}
💕💕💕每一次的分享都是一次成长的旅程,感谢您的陪伴和关注。希望这些关于Go语言的文章能陪伴您走过技术的一段旅程,共同见证成长和进步!😺😺😺
🧨🧨🧨让我们一起在技术的海洋中探索前行,共同书写美好的未来!!!
版权归原作者 明明跟你说过 所有, 如有侵权,请联系我们删除。