快速学习GO语言总结

备注:本博客将自己初步学习GO的总结进行分享,希望大家通过本博客可以在短时间内快速掌握GO的基本程序编码能力,如有错误请留言指正,谢谢!

一、初步了解Go语言

(一)Go语言诞生的主要问题和目标

  1. 多核硬件架构: 随着计算机硬件的发展,多核处理器成为主流,使得并行计算变得普遍。然而,传统的编程语言在处理多核并行性时可能面临困难,因为它们缺乏合适的原生支持。Go语言通过引入轻量级的协程(goroutine)和通道(channel)机制,使得并发编程变得更加容易。开发者可以轻松地创建数千个并发执行的协程,而无需担心线程管理的复杂性。

  2. 超大规模分布式计算集群: 随着云计算和分布式系统的崛起,构建和维护超大规模的分布式计算集群变得越来越常见。这些集群需要能够高效处理大量的请求、数据共享和协调。Go语言的并发特性和通道机制使得编写分布式系统变得更加容易,开发者可以使用协程和通道来处理并发任务、消息传递和协调工作。

  3. Web模式导致的开发规模和更新速度增加: Web应用的兴起带来了前所未有的开发规模和持续更新的需求。传统的编程语言在开发大型Web应用时可能会面临可维护性、性能和开发效率等问题。Go语言通过其简洁的语法、高效的编译速度以及并发支持,使得开发者能够更快速地迭代和部署Web应用,同时也能够更好地处理高并发的网络请求。

综合来看,Go语言在诞生时确实着重解决了多核硬件架构、超大规模分布式计算集群和Web模式下的开发规模与速度等技术挑战。它的设计目标之一是提供一种适应现代软件开发需求的编程语言,使开发者能够更好地应对这些挑战。

(二)Go语言应用典型代表

Go语言在当下应用开发中已经得到广泛应用,许多知名公司和项目都使用Go语言来构建各种类型的应用。以下是一些代表性的产品和项目,它们使用了Go语言作为核心开发语言:

这些仅仅是Go语言应用的一小部分示例,实际上还有许多其他的项目和产品也在使用Go语言来构建高性能、可靠且易于维护的应用程序。这表明Go语言在现代应用开发中发挥了重要作用,特别是在分布式系统、云计算和高性能应用领域。

(三)Java、C++、C程序员在学习编写Go时存在的误区

当Java、C++、C等编程语言的程序员开始学习编写Go语言时,可能会遇到一些误区,因为Go在某些方面与这些传统语言有所不同。以下是一些常见的误区:

  1. 过度使用传统的并发模型: 传统的编程语言如Java、C++、C在处理并发时通常使用线程和锁来实现,但在Go中,使用协程(goroutine)和通道(channel)是更好的方式新学习Go的程序员可能会继续使用传统的并发模型,而不充分利用Go的轻量级协程和通道,从而失去了Go的并发优势。

  2. 过度使用指针: C和C++等语言强调指针的使用,但Go语言在设计时避免了过多的指针操作。新学习Go的程序员可能会过度使用指针,导致代码变得复杂。在Go中,尽量避免使用指针,除非真正需要对值进行修改。

  3. 忽视错误处理: Go鼓励显式地处理错误,而不是简单地忽略它们。这与一些其他语言的习惯不同,其中错误往往被忽略或简单地抛出。新学习Go的程序员可能会忽视错误处理,导致潜在的问题未被检测到。

  4. 过度使用全局变量: 在C和C++等语言中,全局变量可能是常见的做法。然而,在Go中,全局变量的使用被视为不良实践。Go鼓励使用局部变量和传递参数的方式来传递数据,以避免引入不必要的耦合和副作用。

  5. 不熟悉切片和映射: Go中的切片和映射是强大的数据结构,但对于其他语言的程序员来说可能不太熟悉。学习如何正确使用切片和映射是很重要的,因为它们在Go中广泛用于集合和数据处理。

  6. 错误的Go风格: 每种语言都有其独特的编码风格和惯例。新学习Go的程序员可能会在Go代码中应用其他语言的编码风格,这可能会使代码难以阅读和理解。了解和遵循Go的编码规范是很重要的。

为了避免这些误区,学习Go的程序员应该投入时间去理解Go语言的核心概念,包括并发模型、错误处理、数据结构等,同时积极参与Go社区,阅读Go的官方文档和示例代码,以便更好地适应Go的设计理念和最佳实践。

二、环境准备(以Mac说明)

(一)环境设置

在macOS上设置Go语言开发环境非常简单,您可以按照以下步骤进行操作:

  1. 使用Homebrew安装: 如果您使用Homebrew包管理器,这是最方便的方法。打开终端,并运行以下命令来安装Go语言:

    brew install go
  2. 手动安装: 如果您希望手动安装Go语言,可以按照以下步骤操作:

    a. 访问官方网站下载安装包`goX.X.X.darwin-amd64.pkg

    b. 双击下载的安装包,按照指示运行安装程序。按照默认设置即可,安装路径通常是/usr/local/go

  3. 设置环境变量: 一旦安装完成,您需要将Go语言的二进制路径添加到您的终端配置文件中的PATH环境变量中。这样您就可以在终端中直接运行Go命令。

    a. 打开终端,并使用文本编辑器(如nano、vim或任何您喜欢的编辑器)编辑您的终端配置文件。例如:

    nano ~/.bash_profile

    b. 在文件中添加以下行(根据您的安装路径进行调整),然后保存并退出编辑器:

    export PATH=$PATH:/usr/local/go/bin

    c. 使配置生效,可以运行以下命令或者重启终端:

    source ~/.bash_profile
  4. 验证安装: 打开终端,输入以下命令来验证Go是否已正确安装:

    go version

    如果您看到了Go的版本号,表示安装成功。

(二)IDE选择说明

我个人使用的GoLand,直接官网下载后,上网购买破解版即可,这里不在多说!

三、Go语言程序学习

创建自己的工程目录/Users/zyf/zyfcodes/go/go-learning,新建src目录。

(一)第一个Go语言编写

src目录下创建chapter1/hello目录,新建hello.go文件,编写代码如下:

package mainimport ("fmt""os"
)/*** @author zhangyanfeng* @description 第一个godaima* @date 2023/8/20  23:45* @param* @return**/
func main() {if len(os.Args) > 1 {fmt.Println("Hello World", os.Args[1])}
}

这段代码是一个简单的Go语言程序,它接受命令行参数并打印出一条带参数的 "Hello World" 消息。下面是对代码的逐行分析:

  1. package main: 声明这个文件属于名为 "main" 的包,这是一个Go程序的入口包名。

  2. import ("fmt" "os"): 引入了两个标准库包,分别是 "fmt" 用于格式化输出,和 "os" 用于与操作系统交互。

  3. func main() { ... }: 这是程序的入口函数,它会在程序运行时首先被调用。

  4. if len(os.Args) > 1 { ... }: 这个条件语句检查命令行参数的数量是否大于1,也就是判断是否有参数传递给程序。os.Args 是一个字符串切片,它包含了所有的命令行参数,第一个参数是程序的名称。

  5. fmt.Println("Hello World", os.Args[1]): 如果有参数传递给程序,就会执行这行代码。它使用 fmt.Println 函数打印一条消息,消息由字符串 "Hello World" 和 os.Args[1] 组成,os.Args[1] 表示传递给程序的第一个参数。

综上所述,这段代码涵盖了以下知识点:

  1. 包导入和使用标准库:通过 import 关键字导入 "fmt" 和 "os" 包,然后在代码中使用这些包提供的函数和类型。

  2. 命令行参数获取:使用 os.Args 获取命令行参数。

  3. 条件语句:使用 if 条件语句来判断是否有命令行参数传递给程序。

  4. 字符串操作:使用字符串连接操作将 "Hello World" 与命令行参数拼接在一起。

  5. 格式化输出:使用 fmt.Println 函数将消息输出到标准输出。

注意:如果没有传递参数给程序,那么这段代码不会打印任何消息。如果传递了多个参数,代码只会使用第一个参数并忽略其他参数。

在该目录下执行“go run hello.go ZYF”,运行结果为“Hello World ZYF”。

(二)基本程序结构编写学习

src目录下创建chapter2

1.变量

前提:chapter2目录下创建variables,学习总结如下:

  1. 变量声明: 使用var关键字声明一个变量,例如:var x int
  2. 类型推断: 可以使用:=操作符进行变量声明和赋值,Go会根据右侧的值自动推断变量类型,例如:y := 5
  3. 变量赋值: 使用赋值操作符=给变量赋值,例如:x = 10
  4. 多变量声明: 可以同时声明多个变量,例如:var a, b, c int
  5. 变量初始化: 变量可以在声明时进行初始化,例如:var name string = "John"
  6. 零值: 未初始化的变量会被赋予零值,数字类型为0,布尔类型为false,字符串类型为空字符串等。
  7. 短变量声明: 在函数内部,可以使用短变量声明方式,例如:count := 10

新建fib_test.go,背景:简单实用斐波那契数列进行练习

package variablesimport "testing"func TestFibList(t *testing.T) {a := 1b := 1t.Log(a)for i := 0; i < 5; i++ {t.Log(" ", b)tmp := aa = bb = tmp + a}
}func TestExchange(t *testing.T) {a := 1b := 2// tmp := a// a = b// b = tmpa, b = b, at.Log(a, b)
}

下面逐个解释代码中涉及的知识点:

  1. package variables: 声明了一个名为 "variables" 的包,这是一个用于测试的包名。

  2. import "testing": 导入了Go语言的测试框架 "testing" 包,用于编写和运行测试函数。

  3. func TestFibList(t *testing.T) { ... }: 定义了一个测试函数 "TestFibList",该函数用于测试斐波那契数列生成逻辑。这是一个测试函数的标准命名,以 "Test" 开头,接着是被测试的函数名。

    • 在测试函数内部,声明了两个整数变量 ab,并将它们初始化为 1,这是斐波那契数列的前两个数。
    • 使用 t.Log(a) 打印变量 a 的值到测试日志中。
    • 使用循环来生成斐波那契数列的前 5 个数,每次迭代都会将 b 的值打印到测试日志,并更新 ab 的值以生成下一个数。
  4. func TestExchange(t *testing.T) { ... }: 定义了另一个测试函数 "TestExchange",该函数用于测试变量交换的逻辑。

    • 在测试函数内部,声明了两个整数变量 ab,并分别将它们初始化为 1 和 2。
    • 使用注释的方式展示了一种变量交换的写法(通过中间变量),但实际上被注释掉了。然后使用 a, b = b, a 这一行代码来实现 ab 的交换,这是Go语言中的一种特有的交换方式,不需要额外的中间变量。
    • 使用 t.Log(a, b) 打印交换后的变量值到测试日志中。

2.常量

前提:chapter2目录下创建constant,学习总结如下:

  1. 常量声明: 使用const关键字声明一个常量,例如:const pi = 3.14159
  2. 常量赋值: 常量的值在声明时必须被赋值,一旦赋值后不可修改。
  3. 枚举常量: 可以使用一组常量来模拟枚举,例如:
    const (Monday = 1Tuesday = 2// ...
    )
  4. 类型指定: 常量的类型也可以被指定,例如:const speed int = 300000
  5. 常量表达式: 常量可使用表达式计算,例如:const secondsInHour = 60 * 60
  6. 无类型常量: 常量可以是无类型的,根据上下文自动推断类型。例如,const x = 5会被推断为整数类型。

新建constant_test.go,写代码如下:

package constantimport "testing"const (Monday = 1 + iotaTuesdayWednesday
)const (Readable = 1 << iotaWritableExecutable
)func TestConstant1(t *testing.T) {t.Log(Monday, Tuesday)
}func TestConstant2(t *testing.T) {a := 1 //0001t.Log(a&Readable == Readable, a&Writable == Writable, a&Executable == Executable)
}

下面逐个解释代码中涉及的知识点:

  1. package constant: 声明了一个名为 "constant" 的包,这是一个用于测试的包名。

  2. import "testing": 导入了Go语言的测试框架 "testing" 包,用于编写和运行测试函数。

  3. const (...): 定义了两个常量块。

    • 第一个常量块中,使用了 iota 常量生成器来定义了一系列从 1 开始递增的常量。在这个例子中,Monday 被赋值为 1,Tuesday 被赋值为 2,Wednesday 被赋值为 3。iota 在常量块中每次被使用时会递增一次,因此后续的常量会依次递增。

    • 第二个常量块中,使用了 iota 来定义了一系列按位左移的常量。在这个例子中,Readable 被赋值为 1,Writable 被赋值为 2(二进制中的 10),Executable 被赋值为 4(二进制中的 100)。位运算中,左移操作可以将二进制数向左移动指定的位数。

  4. func TestConstant1(t *testing.T) { ... }: 定义了一个测试函数 "TestConstant1",用于测试第一个常量块中定义的常量。

    • 使用 t.Log(Monday, Tuesday) 打印常量 MondayTuesday 的值到测试日志中。
  5. func TestConstant2(t *testing.T) { ... }: 定义了另一个测试函数 "TestConstant2",用于测试位运算和常量的使用。

    • 在测试函数内部,声明了一个整数变量 a,并将其初始化为 1,即二进制中的 0001。
    • 使用位运算和按位与操作来检查变量 a 是否具有 ReadableWritableExecutable 属性。例如,a&Readable == Readable 表达式检查 a 的二进制表示是否含有 Readable 标志位。
    • 使用 t.Log() 打印三个表达式的结果到测试日志中。

3.数据类型

前提:chapter2目录下创建 type,学习总结如下:

主要数据类型说明

Go语言具有丰富的内置数据类型,这些数据类型用于表示不同类型的值和数据。以下是对Go语言中一些主要数据类型的总结分析:

  1. 整数类型(Integer Types):Go语言提供不同大小的整数类型,如intint8int16int32int64。无符号整数类型有uintuint8uint16uint32uint64。整数类型的大小取决于计算机的架构,例如32位或64位。

  2. 浮点数类型(Floating-Point Types):Go语言提供float32float64两种浮点数类型,分别对应单精度和双精度浮点数。

  3. 复数类型(Complex Types):Go语言提供complex64complex128两种复数类型,分别对应由两个浮点数构成的复数。

  4. 布尔类型(Boolean Type):布尔类型用于表示真(true)和假(false)的值,用于条件判断和逻辑运算。

  5. 字符串类型(String Type):字符串类型表示一系列字符。字符串是不可变的,可以使用双引号"或反引号`来定义。

  6. 字符类型(Rune Type):字符类型rune用于表示Unicode字符,它是int32的别名。通常使用单引号'来表示字符,如'A'

  7. 数组类型(Array Types):数组是具有固定大小的同类型元素集合。声明数组时需要指定元素类型和大小。

  8. 切片类型(Slice Types):切片是对数组的一层封装,是动态长度的可变序列。切片不保存元素,只是引用底层数组的一部分。

  9. 映射类型(Map Types):映射是键值对的无序集合,用于存储和检索数据。键和值可以是任意类型,但键必须是可比较的。

  10. 结构体类型(Struct Types):结构体是一种用户定义的复合数据类型,可以包含不同类型的字段,每个字段有一个名字和类型。

  11. 接口类型(Interface Types):接口是一种抽象类型,用于定义一组方法。类型实现了接口的方法集合即为实现了该接口。

  12. 函数类型(Function Types):函数类型表示函数的签名,包括参数和返回值类型。函数可以作为参数传递和返回。

  13. 通道类型(Channel Types):通道是用于在协程之间进行通信和同步的一种机制。通道有发送和接收操作。

  14. 指针类型(Pointer Types):指针类型表示变量的内存地址。通过指针可以直接访问和修改变量的值。

Go语言的数据类型具有清晰的语法和语义,支持丰富的内置功能。合理选择和使用不同的数据类型可以提高程序的效率和可读性。

具体代码展开分析

package mainimport "fmt"type Person struct {FirstName stringLastName  stringAge       int
}type Shape interface {Area() float64
}type Circle struct {Radius float64
}func (c Circle) Area() float64 {return 3.14 * c.Radius * c.Radius
}func add(a, b int) int {return a + b
}func subtract(a, b int) int {return a - b
}type Operation func(int, int) intfunc main() {fmt.Println("整数类型(Integer Types)")var x int = 10var y int64 = 100fmt.Println(x)fmt.Println(y)fmt.Println("浮点数类型(Floating-Point Types)")var a float32 = 3.14var b float64 = 3.14159265359fmt.Println(a)fmt.Println(b)fmt.Println("布尔类型(Boolean Type)")var isTrue bool = truevar isFalse bool = falsefmt.Println(isTrue)fmt.Println(isFalse)fmt.Println("字符串类型(String Type)")str1 := "Hello, "str2 := "Go!"concatenated := str1 + str2fmt.Println(concatenated)fmt.Println("切片类型(Slice Types)")numbers := []int{1, 2, 3, 4, 5}fmt.Println(numbers)// 修改切片元素numbers[0] = 10fmt.Println(numbers)// 切片操作subSlice := numbers[1:4]fmt.Println(subSlice)fmt.Println("映射类型(Map Types)")ages := map[string]int{"Alice": 25,"Bob":   30,"Eve":   28,}fmt.Println(ages)fmt.Println("Alice's age:", ages["Alice"])// 添加新的键值对ages["Charlie"] = 22fmt.Println(ages)fmt.Println("结构体类型(Struct Types)")person := Person{FirstName: "John",LastName:  "Doe",Age:       30,}fmt.Println(person)fmt.Println("Name:", person.FirstName, person.LastName)fmt.Println("接口类型(Interface Types)")var shape Shapecircle := Circle{Radius: 5}shape = circlefmt.Println("Circle Area:", shape.Area())fmt.Println("函数类型(Function Types)")var op Operationop = addresult := op(10, 5)fmt.Println("Addition:", result)op = subtractresult = op(10, 5)fmt.Println("Subtraction:", result)fmt.Println("通道类型(Channel Types)")messages := make(chan string)go func() {messages <- "Hello, Go!"}()msg := <-messagesfmt.Println(msg)fmt.Println("指针类型(Pointer Types)")x = 10var ptr *intptr = &xfmt.Println("Value of x:", x)fmt.Println("Value stored in pointer:", *ptr)*ptr = 20fmt.Println("Updated value of x:", x)
}

下面逐个解释代码中涉及的知识点:

  1. type Person struct { ... }: 定义了一个结构体类型 Person,表示一个人的信息,包括 FirstNameLastNameAge 字段。

  2. type Shape interface { ... }: 定义了一个接口类型 Shape,该接口要求实现一个方法 Area() 返回一个 float64 类型。

  3. type Circle struct { ... }: 定义了一个结构体类型 Circle,表示一个圆的半径。

    func (c Circle) Area() float64 { ... }:为 Circle 类型实现了 Shape 接口的 Area() 方法,用于计算圆的面积。
  4. func add(a, b int) int { ... }: 定义了一个函数 add,用于执行整数相加操作。

  5. func subtract(a, b int) int { ... }: 定义了一个函数 subtract,用于执行整数相减操作。

  6. type Operation func(int, int) int: 定义了一个函数类型 Operation,它接受两个整数参数并返回一个整数结果。

  7. main() { ... }: 程序的入口函数。

  • 定义了多种不同类型的变量,包括整数、浮点数、布尔、字符串、切片、映射、结构体、接口、函数、通道和指针类型。
  • 演示了不同类型变量的初始化、赋值、访问以及基本操作。
  • 使用切片操作提取部分切片。
  • 演示了映射的使用,包括添加新的键值对和访问键值对。
  • 演示了结构体的定义和初始化,并访问结构体字段。
  • 展示了接口的使用,将 Circle 类型赋值给 Shape 类型变量,并调用接口方法。
  • 演示了函数类型的定义和使用,将不同函数赋值给 Operation 类型变量,并进行调用。
  • 使用通道来实现并发通信,通过匿名函数在 goroutine 中发送和接收消息。
  • 演示了指针的使用,包括创建指针变量、通过指针修改变量的值等操作。

Go语言中类型转换说明

Go语言支持类型转换,但需要注意一些规则和限制。类型转换用于将一个数据类型的值转换为另一个数据类型,以便在不同的上下文中使用。以下是有关Go语言中类型转换的一些重要信息:

  1. 基本类型之间的转换: 可以在基本数据类型之间进行转换,但是必须注意类型的兼容性和可能导致的数据丢失。例如,从intfloat64的转换是安全的,但从float64int可能导致小数部分被截断。

  2. 显示类型转换: 在Go中,使用强制类型转换来显式指定将一个值转换为另一个类型。语法是:destinationType(expression)。例如:float64(10)

  3. 非兼容类型之间的转换: 对于不兼容的类型,编译器不会自动进行转换。例如,不能直接将一个string类型转换为int类型。

  4. 类型别名的转换: 如果有类型别名(Type Alias),在转换时需要注意使用别名的兼容性。

以下是一些示例来展示类型转换:

package mainimport "fmt"func main() {// 显式类型转换var x int = 10var y float64 = float64(x)fmt.Println(y)// 类型别名的转换type Celsius float64type Fahrenheit float64c := Celsius(25)f := Fahrenheit(c*9/5 + 32)fmt.Println(f)
}

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

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

相关文章

iOS17 widget Content margin

iOS17小组件有4个新的地方可以放置分别是&#xff1a;Mac桌面、iPad锁屏界面、 iPhone Standby模式、watch的smart stack Transition to content margins iOS17中苹果为widget新增了Content margin, 使widget的内容能够距离边缘有一定的间隙&#xff0c;确保内容显示完整。这…

学习设计模式之适配器模式,但是宝可梦

前言 作者在准备秋招中&#xff0c;学习设计模式&#xff0c;做点小笔记&#xff0c;用宝可梦为场景举例&#xff0c;有错误欢迎指出。 适配器模式 意图&#xff1a;将一个类的接口转换成客户希望的另一个接口 主要解决&#xff1a;把现有对象放到新环境里&#xff0c;而新…

IDEA 如何制作代码补丁?IDEA 生成 patch 和使用 patch

什么是升级补丁&#xff1f; 比如你本地修复的 bug&#xff0c;需要把增量文件发给客户&#xff0c;很多场景下大家都需要手工整理修改的文件&#xff0c;并整理好目录&#xff0c;这个很麻烦。那有没有简单的技巧呢&#xff1f;看看 IDEA 生成 patch 和使用 patch 的使用。 介…

一、Kafka概述

目录 1.3 Kafka的基础架构 1.3 Kafka的基础架构 Producer&#xff1a;消息生产者&#xff0c;就是向 Kafka broker 发消息的客户端Consumer&#xff1a;消息消费者&#xff0c;向 Kafka broker 取消息的客户端。Consumer Group&#xff08;CG&#xff09;&#xff1a;消费者组&…

PyTorch学习笔记(十六)——利用GPU训练

一、方式一 网络模型、损失函数、数据&#xff08;包括输入、标注&#xff09; 找到以上三种变量&#xff0c;调用它们的.cuda()&#xff0c;再返回即可 if torch.cuda.is_available():mynn mynn.cuda() if torch.cuda.is_available():loss_function loss_function.cuda(…

SpringMVC之@RequestMapping注解

文章目录 前言一、RequestMapping介绍二、详解&#xff08;末尾附源码&#xff0c;自行测试&#xff09;1.RequestMapping注解的位置2.RequestMapping注解的value属性3.RequestMapping注解的method属性4.RequestMapping注解的params属性&#xff08;了解&#xff09;5.RequestM…

华为ENSP网络设备配置实战6(简单的链路聚合)

题目要求 1、创建聚合组&#xff0c;添加端口成员 2、PC1网段为vlan10&#xff0c;PC2网段为vlan20 3、LSW1为核心网关设备&#xff0c;正确配置PC网关 4、PC1与PC2互通 解题过程 1.1、 按照拓扑图&#xff0c;各个设备起名 sys &#xff08;进入系统视图&#xff09; sy…

TCP协议报文结构

TCP是什么 TCP&#xff08;传输控制协议&#xff09;是一种面向连接的、可靠的、全双工的传输协议。它使用头部&#xff08;Header&#xff09;和数据&#xff08;Data&#xff09;来组织数据包&#xff0c;确保数据的可靠传输和按序传递。 TCP协议报文结构 下面详细阐述TCP…

FRP内网穿透,配置本地电脑作为服务器

FRP内网穿透&#xff0c;配置本地电脑作为服务器 下载FRP服务端客户端 参考链接&#xff1a; https://www.it235.com/实用工具/内网穿透/pierce.html https://www.cnblogs.com/007sx/p/17469301.html 由于没有公网ip&#xff0c;所以尝试内网穿透将本地电脑作为服务器&#xff…

【Mariadb高可用MHA】

目录 一、概述 1.概念 2.组成 3.特点 4.工作原理 二、案例介绍 1.192.168.42.3 2.192.168.42.4 3.192.168.42.5 4.192.168.42.6 三、实际构建MHA 1.ssh免密登录 1.1 所有节点配置hosts 1.2 192.168.42.3 1.3 192.168.42.4 1.4 192.168.42.5 1.5 192.168.42.6 …

(二)结构型模式:7、享元模式(Flyweight Pattern)(C++实例)

目录 1、享元模式&#xff08;Flyweight Pattern&#xff09;含义 2、享元模式的UML图学习 3、享元模式的应用场景 4、享元模式的优缺点 5、C实现享元模式的简单实例 1、享元模式&#xff08;Flyweight Pattern&#xff09;含义 享元模式&#xff08;Flyweight&#xff09…

OpenCV笔记之solvePnP函数和calibrateCamera函数对比

OpenCV笔记之solvePnP函数和calibrateCamera函数对比 文章目录 OpenCV笔记之solvePnP函数和calibrateCamera函数对比1.cv::solvePnP2.cv::solvePnP函数的用途和工作原理3.cv::solvePnP背后的数学方程式4.cv::SOLVEPNP_ITERATIVE、cv::SOLVEPNP_EPNP、cv::SOLVEPNP_P3P5.一个固定…

为什么需要单元测试?

为什么需要单元测试&#xff1f; 从产品角度而言&#xff0c;常规的功能测试、系统测试都是站在产品局部或全局功能进行测试&#xff0c;能够很好地与用户的需要相结合&#xff0c;但是缺乏了对产品研发细节&#xff08;特别是代码细节的理解&#xff09;。 从测试人员角度而言…

Qt应用开发(基础篇)——纯文本编辑窗口 QPlainTextEdit

一、前言 QPlainTextEdit类继承于QAbstractScrollArea&#xff0c;QAbstractScrollArea继承于QFrame&#xff0c;是Qt用来显示和编辑纯文本的窗口。 滚屏区域基类https://blog.csdn.net/u014491932/article/details/132245486?spm1001.2014.3001.5501框架类QFramehttps://blo…

Elasticsearch复合查询之Boosting Query

前言 ES 里面有 5 种复合查询&#xff0c;分别是&#xff1a; Boolean QueryBoosting QueryConstant Score QueryDisjunction Max QueryFunction Score Query Boolean Query在之前已经介绍过了&#xff0c;今天来看一下 Boosting Query 用法&#xff0c;其实也非常简单&…

Chapter 15: Object-Oriented Programming | Python for Everybody 讲义笔记_En

文章目录 Python for Everybody课程简介Object-oriented programmingManaging larger programsGetting startedUsing objectsStarting with programsSubdividing a problemOur first Python objectClasses as typesObject lifecycleMultiple instancesInheritanceSummaryGlossa…

python基础5——正则、数据库操作

文章目录 一、数据库编程1.1 connect()函数1.2 命令参数1.3 常用语句 二、正则表达式2.1 匹配方式2.2 字符匹配2.3 数量匹配2.4 边界匹配2.5 分组匹配2.6 贪婪模式&非贪婪模式2.7 标志位 一、数据库编程 可以使用python脚本对数据库进行操作&#xff0c;比如获取数据库数据…

Docker 搭建 LNMP + Wordpress(详细步骤)

目录 一、项目模拟 1. 项目环境 2. 服务器环境 3.任务需求 二、Linux 系统基础镜像 三、Nginx 1. 建立工作目录 2. 编写 Dockerfile 脚本 3. 准备 nginx.conf 配置文件 4. 生成镜像 5. 创建自定义网络 6. 启动镜像容器 7. 验证 nginx 四、Mysql 1.…

申请部署阿里云SSL免费证书

使用宝塔自动创建的证书有时候会报NET::ERR_CERT_COMMON_NAME_INVALID&#xff0c;并且每次只能三个月&#xff0c;需要点击续期非常麻烦&#xff0c;容易遗忘。 阿里云免费SSL证书 前往阿里云管理控制台【数字证书管理服务】【SSL证书】&#xff0c;每年20个额度&#xff0c;一…

springBoot 配置文件 flyway 插件相关参数说明

在Spring Boot应用中使用Flyway插件进行数据库迁移时&#xff0c;可以在应用的配置文件中配置相关参数。下面是常用的Flyway配置参数及其说明&#xff1a; flyway.enabled: 是否启用Flyway插件&#xff0c;默认为true&#xff0c;表示启用Flyway插件进行数据库迁移。flyway.ur…