Golang学习笔记

Go语言学习

前提条件

默认编译环境已经安装,vscode已经配置完成

结构示例

在这里插入图片描述

新建模块hello包为main,注意main函数应当在main包中,main.go为测试,go.mod为当前项目模块配置。

一. 基础语法

1.1 Go语言中的25个关键字及其功能描述

关键字功能介绍
break用于中断当前循环或跳出选择结构。
default在switch语句中表示默认情况。
func用于声明函数或方法。
interface用于声明接口类型。
select用于在多个通道操作中进行选择。
case在switch语句中表示某种情况。
defer用于延迟执行函数调用,一般用于资源释放等操作。
go用于启动一个新的goroutine并发执行。
map用于声明和操作映射类型。
struct用于声明和操作结构体类型。
chan用于声明和操作通道类型。
else在if语句中表示条件不成立时的分支。
goto用于无条件跳转到指定的标签。
package用于声明包并定义包级别的变量、函数和类型。
switch用于根据不同的条件执行不同的分支。
const用于声明常量。
fallthrough在switch语句中用于执行下一个case的代码块。
if用于条件判断并执行相应的分支。
range用于迭代数组、切片、字符串、映射或通道中的元素。
type用于声明自定义类型。
continue在循环语句中用于跳过当前迭代并开始下一次迭代。
for用于循环执行代码块。
import用于导入其他包。
return用于从函数中返回值并结束函数的执行。
var用于声明变量。

1.2 Go语言中36个预定义标识符的功能描述

预定义标识符描述
append用于将元素追加到切片(slice)或连接两个切片。
cap返回切片、数组或通道的容量。
close用于在发送操作完成后关闭通道。
complex用于创建复数。
copy用于将元素从一个切片复制到另一个切片。
delete用于从映射(map)中删除键值对。
imag返回复数的实部。
len返回字符串、切片、数组、映射或通道的长度。
make用于创建切片、映射或通道。
new用于创建指向指定类型的指针,并返回该指针。
panic触发运行时错误,导致程序中断。
print将指定的值打印到标准输出。
println将指定的值打印到标准输出并换行。
real返回复数的虚部。
recover用于从panic状态中恢复,使程序可以继续执行。
byte无符号8位整数类型。
complex64表示具有float32实部和虚部的复数类型。
complex128表示具有float64实部和虚部的复数类型。
error预定义的错误类型,表示某种错误值。
false表示布尔类型的假值。
float32表示32位浮点数类型。
float64表示64位浮点数类型。
int表示带符号整数类型,大小根据平台而变化。
int8表示带符号8位整数类型。
int16表示带符号16位整数类型。
int32表示带符号32位整数类型。
int64表示带符号64位整数类型。
rune表示Unicode字符类型,等同于int32。
string表示字符串类型。
true表示布尔类型的真值。
uint表示无符号整数类型,大小根据平台而变化。
uint8表示无符号8位整数类型。
uint16表示无符号16位整数类型。
uint32表示无符号32位整数类型。
uint64表示无符号64位整数类型。
uintptr表示可以容纳指针值的整数类型。

二. 数据类型

2.1基本类型

类型描述示例
bool布尔类型true, false
int整数类型10, -5
float64浮点数类型3.14, -0.5
string字符串类型“Hello”, “”

2.2 聚合类型

类型描述示例
array数组类型[1, 2, 3], [“apple”, “banana”]
slice切片类型[]int{1, 2, 3}, []string{“a”, “b”}
map映射类型map[string]int{“apple”: 1}
struct结构体类型type Person struct {name string}

2.3引用类型

类型描述示例
pointer指针类型&x(x 是某个变量的地址)
slice切片类型[]int{1, 2, 3}
map映射类型map[string]int{“apple”: 1}
channel通道类型make(chan int)

2.4 接口类型

类型描述示例
interface接口类型type Writer interface {Write([]byte) (int, error)}

2.5 函数类型

类型描述示例
function函数类型func add(a, b int) int {…}

三. 基础使用

3.1 变量使用

// 使用 var 关键字声明变量
var age int              // 声明一个整数类型的变量 age
var name string          // 声明一个字符串类型的变量 name
var score float64        // 声明一个浮点数类型的变量 score
var isPassed bool        // 声明一个布尔类型的变量 isPassed

age = 20                // 变量赋值
name = "John"           // 变量赋值
score = 95.5            // 变量赋值
isPassed = true         // 变量赋值

fmt.Println(age)        // 打印变量 age 的值,输出:20
fmt.Println(name)       // 打印变量 name 的值,输出:"John"
fmt.Println(score)      // 打印变量 score 的值,输出:95.5
fmt.Println(isPassed)   // 打印变量 isPassed 的值,输出:true

// 使用简短声明声明变量
age := 20               // 简短声明并初始化整数类型的变量 age
name := "John"          // 简短声明并初始化字符串类型的变量 name
score := 95.5          // 简短声明并初始化浮点数类型的变量 score
isPassed := true        // 简短声明并初始化布尔类型的变量 isPassed

fmt.Println(age)        // 打印变量 age 的值,输出:20
fmt.Println(name)       // 打印变量 name 的值,输出:"John"
fmt.Println(score)      // 打印变量 score 的值,输出:95.5
fmt.Println(isPassed)   // 打印变量 isPassed 的值,输出:true

3.2 常量使用

// 使用 const 关键字声明常量
const pi = 3.14159          // 声明一个浮点数类型的常量 pi
const (
    daysOfWeek = 7          // 声明一个整数类型的常量 daysOfWeek
    appName   = "MyApp"     // 声明一个字符串类型的常量 appName
)

fmt.Println(pi)             // 打印常量 pi 的值,输出:3.14159
fmt.Println(daysOfWeek)     // 打印常量 daysOfWeek 的值,输出:7
fmt.Println(appName)        // 打印常量 appName 的值,输出:"MyApp"

// 常量可以用于各种表达式中
const radius = 5.0
const circumference = 2 * pi * radius   // 通过计算得到圆的周长常量

fmt.Println(circumference)   // 打印圆的周长,输出:31.4159

3.2 iota使用

iota 是一种特殊的常量生成器,用于简化枚举类型的定义。当使用 const 关键字定义一系列常量时,可以使用 iota 来自动生成连续的值

package main

import "fmt"

func main() {
	const (
		Monday    = iota + 1 // iota 的初始值为 0,可以通过加上偏移量来设置起始值
		Tuesday              // 没有显式赋值时,默认按照 iota 自增规则生成值
		Wednesday
		Thursday
		Friday
		Saturday
		Sunday
	)

	fmt.Println(Monday)    // 输出:1
	fmt.Println(Tuesday)   // 输出:2
	fmt.Println(Wednesday) // 输出:3
	fmt.Println(Thursday)  // 输出:4
	fmt.Println(Friday)    // 输出:5
	fmt.Println(Saturday)  // 输出:6
	fmt.Println(Sunday)    // 输出:7
}

示例中,使用 iota 定义了一组代表星期的常量,通过逐行增加 iota 的使用,每个常量都会递增生成一个连续的值。需要注意的是,当遇到新的 const 声明块时,iota 会重置为 0。

3.3 运算符

运算符类型运算符示例含义描述
算术运算符+a + b = 15执行加法运算,将 a 和 b 相加
-a - b = 5执行减法运算,将 a 和 b 相减
*a * b = 50执行乘法运算,将 a 和 b 相乘
/a / b = 2执行除法运算,将 a 除以 b
%a % b = 0执行取模运算,计算 a 对 b 的取余
比较运算符==a == b -> false判断 a 是否等于 b,返回布尔值 false 或 true
!=a != b -> true判断 a 是否不等于 b,返回布尔值 true 或 false
>a > b -> true判断 a 是否大于 b,返回布尔值 true 或 false
<a < b -> false判断 a 是否小于 b,返回布尔值 false 或 true
>=a >= b -> true判断 a 是否大于或等于 b,返回布尔值 true 或 false
<=a <= b -> false判断 a 是否小于或等于 b,返回布尔值 false 或 true
逻辑运算符&&x && y -> false执行逻辑与运算,判断 x 和 y 是否都为真,返回布尔值 false
||x || y -> true执行逻辑或运算,判断 x 和 y 是否有一个为真,返回布尔值 true
!!x -> false执行逻辑非运算,对 x 进行取反操作,返回布尔值 false
位运算符&a & b = 1执行位与运算,对 a 和 b 进行按位与操作
|a | b = 7执行位或运算,对 a 和 b 进行按位或操作
^a ^ b = 6执行位异或运算,对 a 和 b 进行按位异或操作
<<a << 2 = 20执行左移运算,将 a 的二进制表示向左移动指定的位数
>>a >> 1 = 2执行右移运算,将 a 的二进制表示向右移动指定的位数

3.4 条件与循环使用

以下是以 Markdown 表格形式展示的 Go 语言条件语句和循环语句的使用示例及其含义描述:

类型示例含义描述
条件语句if condition {<br> // code to be executed<br>}如果条件为真,则执行指定代码块
if condition {<br> // code to be executed<br>} else {<br> // code to be executed<br>}如果条件为真,则执行第一个代码块,否则执行第二个代码块
if condition1 {<br> // code to be executed<br>} else if condition2 {<br> // code to be executed<br>} else {<br> // code to be executed<br>}如果条件1为真,则执行第一个代码块;如果条件1为假且条件2为真,则执行第二个代码块;否则执行最后一个代码块
循环语句for initialization; condition; post {<br> // code to be executed<br>}初始化变量;如果条件为真,则执行指定代码块;执行后续操作
for condition {<br> // code to be executed<br>}如果条件为真,则执行指定代码块,无需初始化或后续操作
for {<br> // code to be executed<br>}无限循环,会持续执行指定代码块
for index, value := range iterable {<br> // code to be executed<br>}遍历可迭代对象,并将索引和值赋给相应的变量,执行指定代码块
3.4.1 条件语句select使用
package main

import (
	"fmt"
	"time"
)

func main() {
	ch1 := make(chan int)
	ch2 := make(chan string)

	go func() {
		time.Sleep(2 * time.Second)
		ch1 <- 100
	}()

	go func() {
		time.Sleep(1 * time.Second)
		ch2 <- "Hello, Golang!"
	}()

	select {
	case num := <-ch1:
		fmt.Println("Received from ch1:", num)
	case str := <-ch2:
		fmt.Println("Received from ch2:", str)
	default:
		fmt.Println("No channel is ready")
	}
}

在这里插入图片描述

上面的示例中,创建了两个通道 ch1 和 ch2,分别用于接收整数和字符串类型的数据。然后启动两个线程分别向通道发送数据,但它们具有不同的等待时间。通过使用 select 语句,我们可以同时监听多个通道的操作。在这个例子中,select 会等待并尝试从 ch1 和 ch2 中接收数据。如果有可用的数据,将会执行相应的 case 语句;如果没有任何通道准备好,则会执行 default 语句块。
请注意,select 语句只会选择其中一个 case 执行,即使多个 case 同时准备好。这使得我们可以根据情况选择不同的操作路径。

3.5 函数使用与作用域

1:全局作用域和局部作用域

package main

import "fmt"

// 全局变量,可以在整个包内被访问
var globalVariable = "Global"

func main() {
	// 局部变量,只能在 main 函数内部被访问
	var localVariable = "Local"
	
	fmt.Println(globalVariable) // 输出: Global
	fmt.Println(localVariable)  // 输出: Local
	
	anotherFunction()
}

func anotherFunction() {
	fmt.Println(globalVariable) // 输出: Global
	// fmt.Println(localVariable)  // 编译错误,无法访问局部变量
}

解释:

  • 在上述示例中,globalVariable 是一个全局变量,它可以在整个包内任何函数中被访问。
  • localVariable 是一个局部变量,在 main 函数内部声明,并且只能在该函数内部被访问。
  • main 函数中可以访问全局变量和局部变量,因为它们都在其作用域范围内。
  • anotherFunction 函数中只能访问全局变量,无法访问 main 函数内的局部变量。

2:块级作用域

package main

import "fmt"

func main() {
	if true {
		// 在 if 语句块中声明的变量,只能在该语句块内部被访问
		var blockVariable = "Block"
		fmt.Println(blockVariable) // 输出: Block
	}
	
	// fmt.Println(blockVariable)  // 编译错误,无法访问块级作用域内的变量
}

解释:

  • 在这个示例中,blockVariable 是在 if 语句块内部声明的变量,它只能在该语句块内部被访问。
  • 出了 if 语句块之后,无法访问 blockVariable 变量,因为它已经超出了其作用域范围。

通过使用全局变量、局部变量和块级作用域,可以根据需求灵活地管理变量的可见性和生命周期,在不同的代码块中使用不同的变量。

3: 数组使用
在 Go 语言中,数组是一个固定长度且类型相同的数据序列。以下是一个示例,演示如何声明、初始化和使用数组。

package main

import "fmt"

func main() {
	// 声明一个包含5个整数的数组
	var numbers [5]int

	// 通过索引位置赋值
	numbers[0] = 10
	numbers[1] = 20
	numbers[2] = 30
	numbers[3] = 40
	numbers[4] = 50

	// 打印整个数组
	fmt.Println(numbers) // 输出: [10 20 30 40 50]

	// 获取数组长度
	fmt.Println(len(numbers)) // 输出: 5

	// 通过索引位置访问数组元素
	fmt.Println(numbers[2]) // 输出: 30

	// 声明并初始化一个数组
	fruits := [3]string{"Apple", "Banana", "Orange"}
	fmt.Println(fruits) // 输出: [Apple Banana Orange]

	// 使用循环遍历数组
	for i := 0; i < len(fruits); i++ {
		fmt.Println(fruits[i])
	}
}

解释:

  • 在示例中,我们首先声明了一个包含 5 个整数的数组 numbers
  • 通过将值分配给索引位置,我们设置了数组的每个元素的值。
  • 要打印整个数组,可以使用 fmt.Println(numbers)
  • 使用 len(numbers) 获取数组的长度,这里输出为 5。
  • 可以通过索引位置访问数组的特定元素,例如 numbers[2] 输出为 30。
  • 我们还展示了声明、初始化和打印字符串数组 fruits 的方法。
  • 使用 for 循环遍历数组,并使用索引对应的值进行操作。

3.6 指针使用

指针是一个变量,它存储了另一个变量的内存地址。通过指针,可以间接地访问或修改变量的值

  1. 定义指针:可以使用 * 符号声明指针类型。
var ptr *int   // 声明一个整型指针
var ptr2 *string  // 声明一个字符串指针
  1. 获取变量的指针:可以使用 & 符号获取变量的内存地址。
x := 10
ptr := &x  // 获取变量 x 的指针
  1. 访问指针指向的变量:可以使用 * 符号解引用指针来访问它所指向的变量。
x := 10
ptr := &x
fmt.Println(*ptr)  // 输出: 10
  1. 修改指针指向的变量的值:可以通过指针解引用的方式修改指向的变量的值。
x := 10
ptr := &x
*ptr = 20  // 修改指针指向的变量的值
fmt.Println(x)  // 输出: 20

完整示例代码:

package main

import "fmt"

func main() {
	x := 10
	ptr := &x    // 获取变量 x 的指针

	fmt.Println(*ptr)  // 输出: 10

	*ptr = 20   // 修改指针指向的变量的值
	fmt.Println(x)    // 输出: 20

	y := 5
	ptr = &y    // 可以将指针重新指向另一个变量
	fmt.Println(*ptr)  // 输出: 5
}

解释:

  • 声明了一个整型变量 x,然后通过 &x 获取了它的指针,并将其赋值给 ptr
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值