Go:基本变量与数据类型

news2024/11/13 16:01:59

目录

前言

前期准备

Hello World!

一、基本变量

1.1 声明变量

1.2 初始化变量

1.3 变量声明到初始化的过程

1.4 变量值交换

1.5 匿名变量

1.6 变量的作用域

二、数据类型

1.1 整型

1.2 浮点型

1.3 字符串

1.4 布尔类型

1.5 数据类型判断

1.6 数据类型转换

1.7 指针类型(Pointer)


前言

        欢迎你踏上学习Go编程语言的旅程!本章节将为你介绍Go语言的基本变量与数据类型,这是掌握Go编程的重要基础。Go语言以其简洁、高效和强大的特性而闻名。作为一个静态类型语言,Go在编译时就能捕获许多常见错误,这使得开发更加安全和高效。同时,Go的语法设计简洁明了,使得学习曲线相对平缓,非常适合初学者入门。

        在接下来的内容中,将深入探讨Go语言的基本变量类型,如整数、浮点数、布尔值和字符串等。你将学习如何声明变量、理解变量的作用域,以及如何在程序中使用这些基本类型。还会介绍Go语言特有的一些类型,帮助你全面了解Go的类型系统。理解并掌握这些基本概念对于你未来编写高质量的Go程序至关重要。它们是构建更复杂程序的基石,也是理解Go语言设计哲学的窗口。

        记住,编程是一项实践性很强的技能。在学习过程中,我强烈建议你动手实践每个概念,编写并运行示例代码。这不仅能帮助你更好地理解理论知识,还能培养你的编程直觉。

        让我们一起开始这段激动人心的Go语言学习之旅吧!相信通过本章节的学习,你将为成为一名优秀的Go程序员奠定坚实的基础。

前期准备

编辑器 Visual Studio Code

环境配置:

All releases - The Go Programming Language 下载地址,找到你要下载的版本和符合你操作系统的,配置环境等问题...不知道,下好就能用了(๑¯∀¯๑)

学习资源:BiliBili,菜鸟文档,书记,go官方文档,Blog

下面开始写你的第一个go代码

Hello World!

  • Go 程序结构:
    • package main 声明这是主程序包
    • import "fmt" 导入格式化输出的包
    • func main() { ... } 定义程序的入口函数
  • 程序内容:
    • fmt.Println("Hello, World!") 打印 "Hello, World!" 到控制台
package main

import "fmt"
/*
这是多行注释的演示,下面演示单行注释
*/

//注意 "{" 不能单独放在一行,代码在运行时会产生错误:
func main() {
	fmt.Println("Hello, World!")  //注意P要大写
}
  • 运行方式:
    • go run hello.go 直接编译并运行程序
$ go run hello.go 
Hello, World!
  • go build hello.go 编译生成可执行文件
  • ./hello.exe 运行编译后的可执行文件
$ go build hello.go 
$ ls
hello.exe    hello.go
$ ./hello.exe
Hello, World!

一、基本变量

变量是用来存储用户数据的,而不同的变量类型是用来存储不同的用户数据的。

编程语言中常见的数据类型有整型、浮点型、布尔型和结构体等。Go语言每个变量都有自己的类型,在使用它们前,必须经过声明。

Go 语言变量名由字母、数字、下划线组成,其中首个字符不能为数字。与大部分语言相似

但是你都可以拿汉字当变量,想知道为什么吗?往后学习吧

package main

import "fmt"

func main() {
	我 := "iron tom"
	fmt.Println(我)
}
//result
iron tom

1.1 声明变量

  • 一般格式:使用var关键字声明变量,后跟变量名和类型。如var a int
  • 批量格式:可以将多个变量声明组合在一起,提高可读性。
var (
    a int
    b string
    c bool
)

Go在声明变量时,会自动对每个变量的内存区域进行初始化,每个变量会有其对应默认值:

  • 未初始化的变量会被赋予零值(整型为0,字符串为"",布尔型为false)。
  • 切片、映射、函数和指针变量默认为nil。

nil相当于其他语言中的null、None、NULL等,指代零值。

1.2 初始化变量

可以在声明时或之后给变量赋值。

  • 一般格式:var 变量名 变量类型 = 表达式,如:var a int = 1。
  • 短变量声明:使用:=可以同时声明和初始化变量,如d := 20.5
  • 多变量声明:可以一次声明多个变量,如var e, f int = 30, 40
  • 类型推断:在初始化时可以省略类型。(最后会与数据类型例子结合展示)
package main

import "fmt"

func main() {
	var name string
	name := "Tom"
	fmt.Println(name)
}

在开发中,短变量声明是使用最为普遍的,但是在使用的过程中需要注意变量重复声明问题

//result
# command-line-arguments
.\demo.go:9:7: no new variables on left side of :=

1.3 变量声明到初始化的过程

  • 变量声明的核心目的是在内存中分配空间并为这个空间创建一个引用。
  • 变量初始化是在声明后(有时与声明同时)为变量赋予初始值的过程。

package main

import (
    "fmt"
    "unsafe"
)

func main() {
    // 变量声明
    var a int

    // 打印a的内存地址和初始(零)值
    fmt.Printf("After declaration:\n")
    fmt.Printf("a's address: %p\n", &a)
    fmt.Printf("a's value: %d\n", a)
    fmt.Printf("a's size in bytes: %d\n\n", unsafe.Sizeof(a))

    // 变量初始化
    a = 42

    // 再次打印a的内存地址和新值
    fmt.Printf("After initialization:\n")
    fmt.Printf("a's address: %p\n", &a)
    fmt.Printf("a's value: %d\n", a)
}

变量声明后,内存已分配(我们可以打印地址),并且被初始化为零值。
初始化改变了内存位置的内容,但地址保持不变。
我们可以看到分配给int类型变量的内存大小。

After declaration:
a's address: 0xc00000a0b8
a's value: 0
a's size in bytes: 8

After initialization:
a's address: 0xc00000a0b8
a's value: 42

1.4 变量值交换

  • 通过中间值交换
package main

import "fmt"

func main() {
	// 声明并初始化两个变量
	a := 5
	b := 10
	// 打印原始值
	fmt.Println("Before swap: a =", a, "b =", b)
	// 使用多重赋值语句交换两个变量的值
	a, b = b, a
	// 打印交换后的值
	fmt.Println("After swap: a =", a, "b =", b)
}
//result
Before swap: a = 5 b = 10
After swap: a = 10 b = 5
  • 直接交换
package main

import "fmt"

func main() {
	// 声明并初始化两个变量
	a := 5
	b := 10
	// 打印原始值
	fmt.Println("Before swap: a =", a, "b =", b)
	// 使用多重赋值语句交换两个变量的值
	a, b = b, a
	// 打印交换后的值
	fmt.Println("After swap: a =", a, "b =", b)
}
//result
Before swap: a = 5 b = 10
After swap: a = 10 b = 5

1.5 匿名变量

在赋值给多个变量时,如果存在不需要接受值的变量,可以使用匿名变量来代替。

由于匿名不占用匿名空间,也不会分配系统内存,匿名变量与匿名变量之间不会因为多次声明而无法使用。

package main

import "fmt"

// 函数返回两个整数值
func ReturnData() (int, int) {
	return 1, 2
}

func main() {
	a, _ := ReturnData() //a 接受第一个返回值,匿名变量接受第二个返回值
	_, b := ReturnData() //匿名变量接受第一个返回值,b 接受第二个返回值
	fmt.Println(a, b)
}
//result
1, 2

1.6 变量的作用域

变量的作用域是指变量在程序中可以被访问的范围。在Go语言中,变量的作用域主要分为以下几种:局部作用域(函数内部)、包级作用域、全局作用域

  • 包级作用域
    • packageVar 是在函数外声明的,属于包级作用域。
    • 它可以在整个包(这个例子中就是 main 包)的任何地方被访问。
  • 局部作用域(函数级):
    • localVar 是在 main 函数内声明的,只能在 main 函数内访问。
    • funcVar 是在 exampleFunction 内声明的,只能在该函数内访问。
  • 代码块作用域
    • blockVar 是在 main 函数内的一个代码块中声明的,只能在该代码块内访问。
package main

import "fmt"

// 包级变量,在整个包内可访问
var packageVar = "我是包级变量"

func main() {
	// 局部变量,只在main函数内可访问
	localVar := "我是局部变量"

	fmt.Println(packageVar) // 可以访问包级变量
	fmt.Println(localVar)   // 可以访问局部变量

	// 演示代码块作用域
	{
		blockVar := "我是代码块变量"
		fmt.Println(blockVar)
	}
	// fmt.Println(blockVar) // 这行如果取消注释会报错,因为blockVar在这里不可访问

	demo()
	// fmt.Println(funcVar) // 这行如果取消注释会报错,因为funcVar只在exampleFunction中可访问
}

func demo() {
	funcVar := "我是函数内的变量"
	fmt.Println(funcVar)
	fmt.Println(packageVar) // 可以访问包级变量
	// fmt.Println(localVar) // 这行如果取消注释会报错,因为localVar只在main函数中可访问
}
//result
我是包级变量
我是局部变量
我是代码块变量
我是函数内的变量
我是包级变量

需要注意的几点:

  1. 在Go中,花括号 {} 定义了一个新的作用域。
  2. 内部作用域可以访问外部作用域的变量,但外部作用域不能访问内部作用域的变量。
  3. 如果在不同作用域中声明了同名变量,内部作用域的变量会"遮蔽"外部作用域的变量。
  4. Go语言不支持全局变量的概念,但包级变量在很多情况下可以起到类似的作用。
  5. 使用 := 声明的变量只能在函数内部使用,不能用于声明包级变量。

二、数据类型

Go语言的数据类型十分丰富,常见的包括整型、浮点型、字符串和布尔型等。Go语言特有的数据类型包括接口和通道等。

1.1 整型

  • 有符号整型:
    • int: 依据系统架构,在32位系统上为32位,在64位系统上为64位
    • 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
  • 无符号整型:
    • uint: 依据系统架构,在32位系统上为32位,在64位系统上为64位
    • uint8: 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
  • 特殊整型:
    • byte: uint8 的别名,用于强调值是一个原始的字节
    • rune: int32 的别名,用于表示一个 Unicode 码点
    • uintptr: 无符号整型,大小足以存储指针值的未解释位
package main

import "fmt"

func main() {
	a := 3
	b := 2
	c := a / b
	fmt.Println(c)
}
//result
1

注意:在Go语言中,对于两个整型变量的除法运算,小数部分将会直接被截取,只取整数部分,不会存在四舍五入的情况。

1.2 浮点型

Go语言提供了两种浮点数类型:float32 和 float64。这两种类型遵循 IEEE-754 标准,分别为单精度和双精度浮点数。

  • float32(单精度浮点数):
    • 32位,4字节
    • 精度大约为6-9位十进制数字
    • 范围大约为 ±1.18 × 10^-38 到 ±3.4 × 10^38
  • float64(双精度浮点数):
    • 64位,8字节
    • 精度大约为15-17位十进制数字
    • 范围大约为 ±2.23 × 10^-308 到 ±1.80 × 10^308
package main

import (
	"fmt"
	"reflect"
)

func main() {
	a := 3.0
	b := 2.0
	c := a / b
	fmt.Println(c)
	fmt.Println(reflect.TypeOf(c))
	fmt.Println(reflect.TypeOf(a))
	fmt.Println(reflect.TypeOf(b))
}
//result
1.5
float64
float64
float64

1.3 字符串

字符&转义字符

在Go中,单个字符通常用rune (int32)类型表示,用于表示一个 Unicode 码点(可以说对任何字符转ASCII码,汉字也是可以的)。而转义字符则是用来在字符串中表示特殊字符或不可打印字符的方式。

  • 常用转义字符:
    • \n: 换行
    • \t: 制表符
    • \r: 回车
    • \": 双引号
    • \\: 反斜杠
package main

import "fmt"

func main() {
	str1 := '我'
	str2 := 'w'
	fmt.Println(str1, str2)
}
//result
25105 105

注意:单引号与双引号的区别,单引号只能输入一个字符且返还的结果是对应的ASCII码。

  • 基本定义:
    • 在Go中,字符串是一个不可变的字节序列。
    • 字符串可以包含任意数据,包括字节值0,但通常用于存储人类可读的文本。
    • UTF-8 编码:Go字符串默认使用UTF-8编码,可以方便地处理Unicode字符。(这就是为什么变量都可以使用汉字的原因了)
  • 声明和初始化:
    • 可以使用双引号 "" 或反引号 ``(多行表示) 来创建字符串。
    • 双引号创建的字符串可以包含转义字符。
    • 反引号创建的字符串是原始字面量,不处理任何转义字符,可以跨多行。
package main

import "fmt"

func main() {
	// ``示例
	str := `这是第一行
这是第二行
这是第三行`
	fmt.Println(str)
}
//result
这是第一行
这是第二行
这是第三行
  • 字符串连接:可以使用 + 运算符
package main

import "fmt"

func main() {
	str1 := "Hello, "
	str2 := "World!"
	fmt.Println(str1 + str2)
}
//result
Hello, World!

  • 字符串查找和替换
package main

import (
    "fmt"
    "strings"
)

func main() {
    str := "Go语言是一个高效的编程语言"
    
    // 查找子串
    index := strings.Index(str, "高效")
    fmt.Printf("'高效' 的索引位置: %d\n", index)
    
    // 替换子串
    newStr := strings.Replace(str, "高效", "强大", 1)
    fmt.Printf("替换后的字符串: %s\n", newStr)
    
    // 统计子串出现次数
    count := strings.Count(str, "语言")
    fmt.Printf("'语言' 出现的次数: %d\n", count)
}
//result
'高效' 的索引位置: 11
替换后的字符串: Go语言是一个强大的编程语言
'语言' 出现的次数: 2
  • 字符串分割和连接
package main

import (
    "fmt"
    "strings"
)

func main() {
    // 分割字符串
    str := "Go,Python,Java,C++"
    languages := strings.Split(str, ",")
    fmt.Println("分割后的切片:")
    for i, lang := range languages {
        fmt.Printf("%d: %s\n", i, lang)
    }
    
    // 连接字符串
    newStr := strings.Join(languages, " | ")
    fmt.Printf("连接后的字符串: %s\n", newStr)
    
    // 去除首尾空白
    spaceStr := "  Go language  "
    trimmed := strings.TrimSpace(spaceStr)
    fmt.Printf("去除空白后: '%s'\n", trimmed)
}
//result
分割后的切片:
0: Go
1: Python
2: Java
3: C++
连接后的字符串: Go | Python | Java | C++
去除空白后: 'Go language'

1.4 布尔类型

布尔型是最简单的数据类型,只有两个值:false(假)和true(真)。

package main

import "fmt"

func main() {
	var a bool
	fmt.Println(a)
	a = true
	fmt.Println(a)
}
//result
false
true

1.5 数据类型判断

如果我们需要判断变量的类型,可以使用Go语言标准库中的reflect包,通过将变量传入此包的 TypeOf()方法,得到变量的数据类型。

package main

import (
	"fmt"
	"reflect"
)

func main() {
	a := 1
	b := "test"
	c := true
    //TypeOf()方法直接返回传入变量的类型,通过Println()方法打印到控制台。
	fmt.Println(reflect.TypeOf(a))
	fmt.Println(reflect.TypeOf(b))
	fmt.Println(reflect.TypeOf(c))
}
//result
int
string
bool

1.6 数据类型转换

Go是静态类型的,变量在声明时就确定了类型。Go语言常见的数据类型之间能够互相进行类型转换,通过使用类型前置加小括号的方式进行。

package main

import "fmt"

func main() {
	// 整数与浮点数之间的转换
	var f float64 = 3.14
	var i int32 = 100
	i = int32(f)
	fmt.Printf("float64 to int32: %v (%T)\n", i, i)
}
//result
float64 to int32: 3 (int32)

 静态类型语言 VS 动态类型语言 

静态类型语言动态类型语言
类型错误在编译时就能被发现变量类型可以在运行时改变
通常运行速度更快更加灵活,开发速度可能更快
代码通常更易于理解和维护某些类型错误只能在运行时被发现

静态类型语言在编译时进行类型检查。这意味着变量的类型在编译时就已经确定,并且不能在运行时改变。例子:Go、Java、C++、Rust

// Go (静态类型)
package main

import "fmt"

func main() {
    var x int = 5
    // x = "hello"  // 编译错误:不能将string类型赋值给int类型
    fmt.Println(x)
    
    // y := 10  // 类型推断
    // y = "world"  // 编译错误:不能将string类型赋值给int类型
}

与静态类型相对,动态类型语言在运行时进行类型检查。例子:Python、JavaScript、Ruby

# Python (动态类型)
x = 5
print(x)
x = "hello"  # 正常运行:x的类型从int变为str
print(x)

y = 10
y = "world"  # 正常运行:y的类型从int变为str
print(y)

Go 倾向于明确和类型安全,而 python 提供了更大的灵活性,但代价是可能出现意外的行为。

显式 vs 隐式

  • Go 要求大多数类型转换是显式的,如 int64(i)strconv.Atoi(s)
  • JavaScript 允许许多隐式转换,如 "3" + 2"3" - 2

1.7 指针类型(Pointer)

        谈及指针,很多人可能马上会联想到C/C++中的指针,指针的存在是C/C++强大的根本所在, 但同时也带来很多安全问题,相比之下Go语言的指针则更加高效和安全。

  • 声明指针

指针是一种地址值,这个地址值代表着计算机内存空间中的某个位置。指针变量就是存放地 址值的变量,指针变量的声明格式如下:

var 变量名 *int

一般情况下,我们将指针变量的类型声明为*int,变量名为“p”开头(指代“point”)的单 词,如“p”或“ptr”。

package main

import "fmt"

func main() {
	var p *int
	fmt.Println(p)
}
//result
<nil> //由于指针变量未指向任何地址,所以打印值为nil。
  • 取变量地址 :Go语言中,使用操作符“&”取变量地址,取得的地址值可以赋给指针变量。由于指针变量本身也是变量,因此指针变量在计算机内存中也有自己的地址。
  • 获取指针所指向的内容:指针变量存储的值为地址值,通过在指针变量前面加上“*”符号可以获取指针所指向地址值 的内容。
package main

import "fmt"

func main() {
	num := 1
	var p *int
	p = &num
	fmt.Println("num变量的地址", p)
	fmt.Println("指针变量p的值", &p)
    fmt.Println("指针变量p所指向的值", *p)
}
//result
num变量的地址 0xc00000a0b8
指针变量p的值 0xc00006c028
指针变量p所指向的值 1

注意:p指针声明后其值为nil,这时如果获取指针p指向的地址内容,则会出错

package main

import "fmt"

func main() {
	var p *int
	fmt.Println("指针变量p指向的地址为:", p)
	fmt.Println("指针变量p所指向的内容:", *p)
}
//result
指针变量p指向的地址为: <nil>
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xc0000005 code=0x0 addr=0x0 pc=0xbb95cb]
  • 使用指针修改值

在指针变量有实际指向的地址值后,可以通过如下格式直接修改指针所指向内存地址的内容:

*变量名 = 修改值

package main

import "fmt"

func main() {
	num := 1
	var p *int
	p = &num
	fmt.Println("指针变量p所指向的内容:", *p)
	*p = 10
	fmt.Println("指针变量p所指向的内容:", *p)
}
//result
指针变量p所指向的内容: 1
指针变量p所指向的内容: 10

也可使用new()函数来给指针分配地址并初始化地址对应的值

package main

import "fmt"

func main() {
	var p *int
	p = new(int)
	fmt.Println("指针变量p所指向的内容:", *p)
	*p = 10
	fmt.Println("指针变量p所指向的内容:", *p)
}
//result
指针变量p所指向的内容: 0
指针变量p所指向的内容: 10

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1926543.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

STM32 BootLoader 刷新项目 (四) 通信协议

STM32 BootLoader 刷新项目 (四) 通信协议 文章目录 STM32 BootLoader 刷新项目 (四) 通信协议1. 通信流程2. 支持指令3. 通信流程4. 指令结构5. 操作演示 前面几章节&#xff0c;我们已经介绍了BootLoader的整体程序框架&#xff0c;方案设计&#xff0c;以及STM32CubdeMX的配…

51单片机6(P0P1P2P3结构框架图)

一、GPIO结构框架图与工作原理 1、接下来我们介绍一下这个GPIO结构框图和工作原理&#xff0c;我们使用51单片机的GPIO分为了P0&#xff0c;P1&#xff0c;P2&#xff0c;P3这四组端口&#xff0c;下面我们就分别来介绍这四组端口它的一个内部结构&#xff0c;只有了解了内部的…

Python爬虫入门篇学习记录

免责声明 本文的爬虫知识仅用于合法和合理的数据收集&#xff0c;使用者需遵守相关法律法规及目标网站的爬取规则&#xff0c;尊重数据隐私&#xff0c;合理设置访问频率&#xff0c;不得用于非法目的或侵犯他人权益。因使用网络爬虫产生的任何法律纠纷或损失&#xff0c;由使用…

MySQl高级篇-事务、锁机制、MVCC

存储引擎的选择 在选择存储引擎时&#xff0c;应该根据应用系统的特点选择合适的存储引擎。对于复杂的应用系统&#xff0c;还可以根据实际情况选择多种存储引擎进行组合。 InnoDB&#xff1a;是Mysql的默认存储引擎&#xff0c;支持事务、外键。如果应用对事务的完整性有比较…

C++知识要点总结笔记

文章目录 前言一、c基础1.指针和引用指针和引用的区别 2.数据类型整型 short int long 和 long long无符号类型 3.关键字conststaticconst和static的区别define 和 typedef 的区别define 和 inline 的区别const和define的区别new 和 malloc的区别constexprvolatileextern前置与…

用Speedtest-Tracker跟踪上网速度(续)

什么是 Speedtest Tracker ? Speedtest Tracker 是一款自托管互联网性能跟踪应用程序&#xff0c;可针对 Ookla 的 Speedtest 服务运行速度测试检查。 之前老苏介绍的另一个 https://github.com/henrywhitaker3/Speedtest-Tracker 已被放弃。现在这个是积极维护的替代品&#…

repo sync同步出错解决

当出现下面提示时 e list of known hosts. Fetching: 100% (1167/1167), done in 44.619s info: A new version of repo is available warning: repo is not tracking a remote branch, so it will not receive updates Repo command failed: RepoUnhandledExceptionError …

element UI时间组件两种使用方式

加油&#xff0c;新时代打工&#xff01; 组件官网&#xff1a;https://element.eleme.cn/#/zh-CN/component/date-picker 先上效果图&#xff0c;如下&#xff1a; 第一种实现方式 <div class"app-container"><el-formref"submitForm":model&q…

Zabbix6.0监控Freeswitch状态

一、前提环境说明 1、最终实现Freeswitch监控指标信息&#xff1a; 2、环境需求&#xff1a; &#xff08;1&#xff09;需要使用Zabbix6.0及以上 &#xff08;2&#xff09;需要使用zabbix_agent2 二、实现步骤 1、zabbix_agent2添加监控键值 cat /etc/zabbix/conf.d/fr…

Git代码管理工具 — 3 Git基本操作指令详解

目录 1 获取本地仓库 2 基础操作指令 2.1 基础操作指令框架 2.2 git status查看修改的状态 2.3 git add添加工作区到暂存区 2.4 提交暂存区到本地仓库 2.5 git log查看提交日志 2.6 git reflog查看已经删除的记录 2.7 git reset版本回退 2.8 添加文件至忽略列表 1 获…

2.有限状态机

1. 标准三段式写法&#xff1a; 1.一段代表当前状态赋值&#xff1b; 2.一段代表下一个状态如何跳变 3.一段代表输出控制 一定要带上复位 前两段模板集合一样&#xff0c;第三段取决于具体需求 parameter IDLE_ST 4b0000&#xff1b; parameter TEST_ST 4b0001; ... re…

C++中链表的底层迭代器实现

大家都知道在C的学习中迭代器是必不可少的&#xff0c;今天我们学习的是C中的链表的底层迭代器的实现&#xff0c;首先我们应该先知道链表的底层迭代器和顺序表的底层迭代器在实现上有什么区别&#xff0c;为什么顺序表的底层迭代器更加容易实现&#xff0c;而链表的底层迭代器…

Ubuntu20.04 编译安装FFmpeg,出错分析以及解决方案

最近工程上需要对FFmpeg底层源码进行修改&#xff0c;需要重新编译&#xff0c;遇见不少坑&#xff0c;出篇教程记录一下。 文章目录 1.FFmpeg源码下载地址2.编译环境配置3.编译FFmpeg4.配置FFmpeg运行环境 1.FFmpeg源码下载地址 官方下载地址:Index of /releases (ffmpeg.or…

使用MovaXterm连接VMware的centos

一、确认局域网ip 检查虚拟机分配的网段是否一致 二、确认centos的ip 输入 ip addr 获得设备ip为192.168.153.130 三、用MovaXterm建立ssh连接 有同行可能会问&#xff0c;直接使用VMware操作centos系统不行吗&#xff1f;为什么要再多一步。 理由&#xff1a;1、测试环境c…

Zabbix6.0使用自带模板(MySQL by Zabbix agent 2)监控MySQL数据库

注意&#xff1a;Zabbix6.0使用MySQL by Zabbix agent 2 模板可直接监控MySQL数据库&#xff0c;只需要创建监控用户&#xff0c;模板宏中填写数据库账号信息即可&#xff0c;只需要3步&#xff0c;特简单&#xff01; 1、MySQL创建用户&#xff0c;用于收集数据库信息 creat…

HarmonyOS 界面开发基础篇

一、布局思路 ArkUI(方舟开发框架)是一套 构建 鸿蒙应用 界面 的框架。 构建页面的最小单位就是“组件”。 组件分类 基础组件&#xff1a;界面呈现的基础元素。 如&#xff1a;文字、图片、按钮等。容器组件&#xff1a;控制布局排布。 如&#xff1a;Row行、Column列等。…

MySQL篇:日志

前言 MySQL中常见的日志&#xff1a; 重做日志&#xff08;Redo Log&#xff09;&#xff1a; 用途&#xff1a; 保证事务的持久性&#xff0c;记录事务对数据库所做的所有修改。 内容&#xff1a; 记录事务对数据页的物理修改&#xff0c;而不是逻辑修改。 配置&#xff1a; …

一款IM即时通讯聊天系统源码,包含app和后台源码

一款IM即时通讯聊天系统源码 聊天APP 附APP&#xff0c;后端是基于spring boot开发的。 这是一款独立服务器部署的即时通讯解决方案&#xff0c;可以帮助你快速拥有一套自己的移动社交、 企业办公、多功能业务产品。可以 独立部署&#xff01;加密通道&#xff01;牢牢掌握通…

《C专家编程》杂谈

库函数调用和系统调用的区别 系统调用比函数调用要慢很多&#xff0c;因为还要切换到内核模式。

防火墙综合实验之NAT和智能选路

目录 前言&#xff1a; 一、实验题目 二、实验操作 需求一 需求二 需求三 需求四、需求五 需求六 需求七 ​编辑 需求八 需求九 需求十 需求十一 三、需求测试 前言&#xff1a; 本篇文章是延续上一篇文章&#xff0c;简单来说就是防火墙实验的完善和延续&#…