文章目录
1.golang 通过接口实现ocp设计原则
- 介绍
- OCP(Open-Closed Principle,开闭原则)是SOLID原则中的一个重要原则,它指出:“软件实体应该对扩展开放,对修改关闭”。简单来说,就是在不修改原有代码的基础上,通过扩展新的代码来满足需求变化
package main
import "fmt"
type Pet interface {
fly()
sleep()
}
type Fish struct {
}
func (fish Fish) fly() {
fmt.Printf("Fly....\n")
}
func (fish Fish) sleep() {
fmt.Printf("Sleep...\n")
}
type Dog struct {
}
func (dog Dog) fly() {
fmt.Printf("fly..\n")
}
func (dog Dog) sleep() {
fmt.Printf("sleep..\n")
}
type Person struct {
}
func (person Person) care(pet Pet) {
pet.fly()
pet.sleep()
}
func main() {
dog := Dog{}
fish := Fish{}
person := Person{}
person.care(dog)
person.care(fish)
}
2.golang 如何模拟OOP里的属性和方法
- 什么是OOP
- OOP是指面向对象编程(Object-Oriented Programming)。它是一种计算机编程的范式
- go语言没有面对对象的编程,但我们可以通过结构体和函数绑定模拟OOP的属性和方法,也就是接收者方法
Go语言虽然是一种面向过程的编程语言,但也可以通过结构体和方法来实现类似于OOP中的属性和方法。
首先,我们可以使用Go语言中的结构体(struct)来定义一个包含属性的自定义类型。例如:
type Person struct {
Name string
Age int
}
上述代码定义了一个Person类型,包含了两个属性:Name和Age。使用时可以通过“.”操作符访问该结构体内的字段。
接下来,我们可以为这个结构体添加方法,来实现类似于OOP中的方法。Go语言中的方法也需要依赖于结构体来实现,因此在定义方法时,需要将其绑定在某个结构体类型上。例如:
func (p *Person) SayHello() {
fmt.Printf("Hi, my name is %s and I'm %d years old.\n", p.Name, p.Age)
}
上述代码定义了一个SayHello()方法,它接收一个指向Person类型的指针作为接收者(receiver),并输出该Person对象的属性信息.
通过以上方式,我们就可以在Go语言中模拟出类似于OOP中的属性和方法。同时,由于Go语言的特性,还可以通过接口(interface)、匿名结构体(anonymous struct)等其他方式来达到更加灵活的编程效果,并且不失去Go语言本身的简洁性和高效性。
3.golang 继承
- go语言没有OOP嵌套,但可以通过结构体嵌套实现继承
- 当内嵌的结构体中存在同名字段或方法时,外层结构体会优先使用自身的字段或方法。
package main
import "fmt"
type Action interface {//定义接口
eat()
sleep()
}
type Animal struct {//定义结构体
name string
age int
}
type Dog struct {
A Animal//继承方法
color string
}
type Cat struct {
Animal//继承方法,即可以不用Cat声明调用接口
color string
}
//声明接口函数
func (animal Animal) eat() {
fmt.Printf("%v eat...\n", animal.name)
}
func (animal Animal) sleep() {
fmt.Printf("%v sleep...\n", animal.name)
}
func main() {
dog := Dog{
A: Animal{"Tom", 12},
color: "Red",
}
cat := Cat{
Animal{"Mike", 45},
"Blue",
}
//使用继承
dog.A.eat()
dog.A.sleep()
cat.eat()
cat.sleep()
fmt.Printf("%v\n", dog.A.name)
}
4.golang 构造函数
- Go语言中没有像其他面向对象编程语言那样的构造函数(Constructor),但是我们可以使用结构体(struct)类型的工厂函数来模拟构造函数的行为。
- 工厂函数
- 需要初始化一个变量,常常通过定义一个返回该类型的函数
- 我们可以模拟出类似构造函数的行为,以方便我们初始化自定义类型的变量。
- 目的:便于初始化
5.golang 的包
- 介绍
- 包可以区分命令空间(一个文件中不能有两个同名文件),也可以更好的管理项目.go中创建一个包,一般是创建一个文件夹,该文件夹里面的go文件中,使用
package
关键字声明包名称,通常,文件夹名称和包名称相同,并且,同一个文件下面只有一个包
- 包可以区分命令空间(一个文件中不能有两个同名文件),也可以更好的管理项目.go中创建一个包,一般是创建一个文件夹,该文件夹里面的go文件中,使用
- 注意事项
- 一个文件夹下只能有一个
package
import
后面的其实是GOPATH
开始相对目录路径,包括最后一段.但是由于一个目录下只能有一个package,所以import
一个路径就等于是import
了这个路径下的包
- 比如你实现了一个机算器package,名叫
calc
,位于calc
目录下;但又想给别人使用一个1使用范例,于是在calc
下可以创建一个example子目录,这个子目录里面有个example.go(calc/example/example.go),此时,example.go可以是main包,里面还可以有个main函数 - 一个package的文件不能在多个文件夹下
- 如果一个go文件需要同时使用不同目录下的同名package,
1.import
这些目录时为每个目录指定一个package地别名;import ( p1 "github.com/username/repo/pkg1" p2 "github.com/username/otherrepo/pkg1" )
,在后续代码中可以分别使用p1.Func()
和p2.Func()
来调用两个不同的函数。
- 2.使用绝对路径导入
- 如果一个go文件需要同时使用不同目录下的同名package,
- 一个文件夹下只能有一个
- 关键:
- 如何扩充系统类型或者别人的类型
- 1.定义别名
- 2.使用组合或内嵌
- 使用组合或内嵌
-
扩展别人包的类型可以通过组合或嵌入的方式实现。具体来说,如果你想要扩展一个包中的类型,可以创建一个新的结构体类型,然后将原始类型作为字段嵌入到新的结构体类型中。
-
例如,假设你想扩展一个名为"mypackage"的包中的类型"Foo",你可以按照以下步骤进行操作:
-
在你的代码中导入"mypackage"包。
import "mypackage"
创建一个新的结构体类型,将"mypackage.Foo"作为一个嵌入字段。
type MyFoo struct { mypackage.Foo }
在你的代码中使用新的结构体类型来扩展"mypackage.Foo"类型。
var myFoo MyFoo myFoo.Bar() // 调用"mypackage.Foo"类型中的"Bar"方法 myFoo.MyMethod() // 调用扩展类型中新增的"MyMethod"方法
1.需要注意的是,如果你想要扩展的类型是私有的(即首字母小写),则只能在同一个包中进行扩展,无法在外部包中扩展。
2.需要注意的是,当你使用组合或嵌入的方式来扩展类型时,如果新增了同名的方法或字段,那么它们会覆盖原始类型中的同名方法或字段.因此,在命名新的方法或字段时需要特别小心,以避免意外的行为。package main import "fmt" type Person struct { Name string Age int } func (p *Person) SayHello() { fmt.Printf("Hello, my name is %s and I'm %d years old.\n", p.Name, p.Age) } type Employee struct { Person // 嵌入"Person"类型(使用了语法糖,也可以写成 person Person,给一个变量名,但是会增加代码量) Department string } func (e *Employee) Work() { fmt.Printf("%s is working in %s department.\n", e.Name, e.Department) } func main() { e := Employee{ Person: Person{ Name: "John Doe", Age: 30, }, Department: "Sales", } e.SayHello() // 调用"Person"类型中的"SayHello"方法 e.Work() // 调用"Employee"类型中新增的"Work"方法 }
-
- 定义别名(无法拓展类型)
- 如何扩充系统类型或者别人的类型
6.golang的依赖管理
-
关键
go mod
(常用也好用)(自己写得不太明白,自己去看视频)Go mod 是 Go 语言官方提供的模块化开发工具,用于管理 Go 项目的依赖关系和版本控制。 使用 Go mod 可以方便地创建和管理模块,同时自动解决依赖关系和版本控制。下面是 Go mod 的使用方式: 初始化模块 在项目根目录下执行以下命令,将当前目录设为一个新的模块: go mod init <module-name> 其中,<module-name> 是模块的名称,通常是一个域名或者一个 GitHub 仓库地址。 例如,如果要将当前目录设为名为 "example.com/hello" 的模块,可以使用以下命令: go mod init example.com/hello 执行该命令后,Go 会为该模块创建一个 go.mod 文件,用于记录模块的名称、版本和依赖关系。 添加依赖 使用以下命令来添加依赖: go get <package-path> 例如,如果要添加依赖于 github.com/gin-gonic/gin 的包,可以使用以下命令: go get github.com/gin-gonic/gin Go 会自动下载并安装该包,并将其添加到 go.mod 文件中。 更新依赖 使用以下命令来更新依赖: go get -u <package-path> 例如,如果要更新依赖于 github.com/gin-gonic/gin 的包,可以使用以下命令: go get -u github.com/gin-gonic/gin Go 会自动下载并安装最新版本的该包,并将其更新到 go.mod 文件中。 删除依赖 使用以下命令来删除依赖: go mod tidy 执行该命令后,Go 会自动删除未使用的依赖,并更新 go.mod 文件。 构建项目 使用以下命令来构建项目: go build Go 会自动解决依赖关系,并编译项目。 以上就是 Go mod 的基本使用方式,更多高级用法可以参考 Go 官方文档。