goweb编程实战----面向对象编程(代码片段)

李元静 李元静     2022-12-01     764

关键词:

目录

前言

在Go语言中,并没有类的概念,但这并不意味着Go语言不支持面向对象编程,毕竟面向对象只是一种编程思想。

封装

属性

其实,学习过C语言都应该清楚,结构体是一个类类的结构,也就是说结构体是类的一种简化形式。所以,如果我们需要使用Go语言定义一个三角形类,可以这样写:

type Triangle struct 
	Bottom float32
	Height float32

方法

既然有了类,那类的方法如何定义呢?其实Go语言中,也有方法。

方法是作用在接收者上的一个函数,接收者是某种类型的变量。因此,方法是一种特殊类型的函数。示例如下:

//语法
func (recv recv_type)methodName(parameter_list)(return_value_list)
	//方法内容

//示例
type Triangle struct 
	Bottom float32
	Height float32


func (t *Triangle) Area() float32 
	return (t.Bottom * t.Height) / 2


func main() 
	r :=Triangle6,8
	fmt.Println(r.Area())

以上代码运行的结果为:24

访问权限

在许多面向对象的语言中,属性与方法都有私有与公有的区别,这就是访问权限。比如Java,可以用public、private来定义访问权限。

但Go语言肯定是没有public与private,它是通过字母大小写来控制访问权限的。大家也会发现,我们上面的Bottom与Height都是大写,所以大写是公有属性,小写是私有。

这里就不举例了,大家可以通过编译器试试,可以发现小写的,根本不会提示。强制写入代码运行,肯定也会报错。

另外,我们还常常在Java语言的实体类中,定义get与set方法。下面,我们来通过Go语言实现get与set方法:

type Triangle struct 
	bottom float32
	height float32


func (s *Triangle) GetBottom() float32  
	return s.bottom


func (s *Triangle) SetBottom(bottom float32)
	s.bottom=bottom


func main() 
	r :=Triangle6,8
	r.SetBottom(8)
	fmt.Println(r.GetBottom())
	fmt.Println(r.bottom,r.height)

继承

在Go语言中,同样也没有继承关键字extend,而是使用在结构体中内嵌匿名类型的方法来实现继承。例如,顶一个动物接口和一个老虎结构体,让老虎结构体包含一个动物接口的匿名字段。

type Animal interface 
	GetName()
	SetName()


type Tiger struct 
	Animal


func (t *Tiger) Working()  
	t.GetName()
	t.SetName()

多态

在面向对象中,多态的特征是不同对象中同种行为的不同实现方式。在Go语言中,可以使用接口实现这个特征。示例如下:

//三角形结构体
type Triangle struct 
	Bottom float32
	Height float32

//正方体结构体
type Cube struct 
	sideLen float32

//定义了一个包含Area()方法的接口Shape,让三角形与正方行都实现这个接口里的Area()方法。
type Shape interface 
	Area() float32


func (t *Triangle) Area() float32 
	return (t.Bottom * t.Height) / 2

func (c *Cube) Area() float32  
	return c.sideLen * c.sideLen


func main() 
	r :=&Triangle6,8
	c :=&Cube5
	s :=[]Shaper,c
	for n,_ :=range s
		fmt.Println("图形数据:",s[n])
		fmt.Println("图形面积",s[n].Area())
	

如上面代码所示,通过不同对象调用Area()方法,产生了不同的接口,间接实现的多态。

接口

使用了接口实现了多态与继承,我们也应该详细了解接口的使用方式。

接口(interface)类型是对其他类型行为的概括与抽象。接口定义了一组方法,但是不包含这些方法的具体实现。

本质上接口依旧是一个类型,确切的说,是指针类型。如果一个类型实现了某个接口,则所有使用这个接口的地方都支持这种类型的值。

需要注意的是,如果实现接口的类型支持相等运算,那么可以比较,否则会报错。示例如下:

func main() 
	var var1,var2 interface
	fmt.Println(var1==nil,var2==nil)
	var1,var2=6,8
	fmt.Println(var1==var2)
	var1,var2=map[string]string,map[string]string
	fmt.Println(var1==var2)

运行之后,大家会发现,空接口变量默认值是nil。也就是第一个输出肯定是两个true。而数值不相等,第二个输出false。第三个因为map类型不支持相等运算,所以报错。

接口的赋值

Go语言的接口不支持直接实例化,但支持赋值操作,从而快速实现接口与实现类的映射。

接口赋值在Go语言中分为如下两种情况:

  • 将实现接口的对象实例赋值给接口
  • 将一个接口赋值给另一个接口。

将实现接口的对象实例赋值给接口

将指定类型的对象实例赋值给接口,要求该对象对应的类实现了接口要求的所有方法,否则就不能算实现了该接口。

type Number int

func (x Number) Equal(i Number) bool 
	return x == i


func (x Number) LessThan(i Number) bool 
	return x < i

func (x Number) MoreThan(i Number) bool 
	return x > i

func (x *Number) Multiple(i Number) 
	*x = *x * i

func (x *Number) Divide(i Number) 
	*x = *x / i


type NumberI interface 
	Equal(i Number) bool
	LessThan(i Number) bool
	MoreThan(i Number) bool
	Multiple(x Number)
	Divide(x Number)


func main() 
	var x Number = 8
	var y NumberI = &x
	fmt.Println(x)
	fmt.Println(y)

这里,我们先定义了一个Number类型以及相关方法。按照Go语言的约定,Number类型实现了NumberI接口,接下来就可以将Num类型对应的对象实例赋值给Number接口。

为什么要将&x的指针赋值给接口变量呢?这是因为Go语言会根据下面这样的非指针成员方法:

func (x Number) Equal(i Number) bool

自动生成一个新的与之对应的指针成员方法:

func (x *Number) Equal(i Number) bool
	return (*x).Equal(i)

这样一来,类型*Number就存在所有NumberI接口中声明的方法了。

将接口赋值给接口

在Go语言中,只要两个接口拥有相同的方法列表,则它们就是等同的,可以互相赋值。这里,我们直接将前面的三角形修改一下。

type Triangle struct 
	Bottom float32
	Height float32


type Area1 interface 
	Area(x,y float32) float32

type Area2 interface 
	Area(x,y float32) float32


func (a Triangle) Area(x,y float32) float32 
	return x*y


func main() 
	f1 :=Triangle2,3
	var f2 Area1=f1
	var f3 Area2=f2
	fmt.Println(f3)

如果接口Area1的方法列表是接口Area2 的方法列表的子集,则接口Area2可以赋值给接口Area1 。修改为:

type Area2 interface 
	Area(x, y float32) float32
	Sum(x, y float32) float32

func (a Triangle) Sum(x, y float32) float32 
	return x + y

func main() 
	f1 := Triangle2, 3
	var f2 Area2 = f1
	var f3 Area1 = f2
	fmt.Println(f3)

接口查询

接口查询是在程序运行时进行的,查询是否成功,也要在运行时才能够确定。示例如下:

//语法
if filew,ok:=fileWriter.(*File);ok
	//...

//示例
func main() 
	slice := make([]int, 0)
	slice = append(slice, 6, 7, 8)
	var I interface = slice
	if res, ok := I.([]int); ok 
		fmt.Println(res)
		fmt.Println(ok)
	

上面代码中的if语句会判断接口I所指向的对象是否是[]int类型,如果是,则输出切片中的元素。

通过使用”接口类型.(type)“形式,加上switch-case语句,可以判断接口存储的类型。示例如下:

func Len(array interface) int 
	var length int
	if array == nil 
		length = 0
	
	switch array.(type) 
	case []int:
		length = len(array.([]int))
	case []string:
		length = len(array.([]string))
	case []float32:
		length = len(array.([]float32))
	default:
		length = 0
	
	fmt.Println(length)
	return length


func main() 
	slice := make([]int, 0)
	slice = append(slice, 6, 7, 8)
	var I interface = slice
	Len(I)

接口的组合

在Go语言中,不仅结构体与结构体之间可以嵌套,接口与接口之间也可以嵌套创造出新的接口。一个接口可以包含一个或多个其他的接口,这相当于直接将这些内嵌接口的方法列举在外层接口中一样。

如果接口的所有方法被实现,则这个接口中的所有嵌套接口的方法均可以被调用。接口的组合很简单,直接将接口名写入接口内部即可。另外,还可以在接口内部再定义自己的接口方法。示例如下:

type interface1 interface 
	PrintlnStr(s string)(a string)

type interface2 interface 
	PrintlnInt(s int)(a int)

type interface3 interface 
	interface1
	interface2
 

goweb编程实战----面向对象编程(代码片段)

...有类的概念,但这并不意味着Go语言不支持面向对象编程,毕竟面向对象只是一种编程思想。封装属性其实,学习过C语言都应该清楚,结构体是一个类类的结构,也就是说结构体是类的一种简化形式。所以ÿ... 查看详情

goweb编程实战----面向对象编程(代码片段)

...有类的概念,但这并不意味着Go语言不支持面向对象编程,毕竟面向对象只是一种编程思想。封装属性其实,学习过C语言都应该清楚,结构体是一个类类的结构,也就是说结构体是类的一种简化形式。所以ÿ... 查看详情

goweb编程实战----反射(代码片段)

目录反射反射的3大原则“接口类型变量”转换为“反射类型对象”“反射类型对象”转换为“接口类型变量”“反射类型对象”修改(值必“可写的”)反射与其他语言一样,Go语言的反射同样是指,计算机程序... 查看详情

goweb编程实战----反射(代码片段)

目录反射反射的3大原则“接口类型变量”转换为“反射类型对象”“反射类型对象”转换为“接口类型变量”“反射类型对象”修改(值必“可写的”)反射与其他语言一样,Go语言的反射同样是指,计算机程序... 查看详情

goweb编程实战----函数(代码片段)

目录前言声明与使用函数返回多个值return可以为空函数参数参数值传递引用传递可选函数匿名函数匿名函数的定义匿名函数的调用回调函数defer延迟语句defer与return的执行顺序defer常用场景前言本篇博文主要介绍Go语言的函数定义... 查看详情

goweb编程实战----函数(代码片段)

目录前言声明与使用函数返回多个值return可以为空函数参数参数值传递引用传递可选函数匿名函数匿名函数的定义匿名函数的调用回调函数defer延迟语句defer与return的执行顺序defer常用场景前言本篇博文主要介绍Go语言的函数定义... 查看详情

goweb编程实战----数据类型(代码片段)

...类型、切片类型、Map类型以及结构体类型。布尔型与其他编程语言一样,Go语言的布尔型只可以是tr 查看详情

goweb编程实战----流程控制语句(代码片段)

目录流程控制语句if-else语句for循环语句用for循环实现do-while用for循环实现whilebreak指定跳出循环continue语句for-range循环遍历数组遍历字符串遍历map遍历通道(channel)switch-case语句一个分支多个值分支表达式goto语句流程控制... 查看详情

goweb编程实战----流程控制语句(代码片段)

目录流程控制语句if-else语句for循环语句用for循环实现do-while用for循环实现whilebreak指定跳出循环continue语句for-range循环遍历数组遍历字符串遍历map遍历通道(channel)switch-case语句一个分支多个值分支表达式goto语句流程控制... 查看详情

goweb编程实战----并发goroutine(代码片段)

目录什么是goroutine?使用方式什么是goroutine?在Go语言中,每一个并发执行的活动被称为goroutine。使用go关键字可以创建goroutine,其完整定义如下:gofunc_name()其中,go是关键字,需要放在一个需要调用的函数之前&#... 查看详情

goweb编程实战----并发goroutine(代码片段)

目录什么是goroutine?使用方式什么是goroutine?在Go语言中,每一个并发执行的活动被称为goroutine。使用go关键字可以创建goroutine,其完整定义如下:gofunc_name()其中,go是关键字,需要放在一个需要调用的函数之前&#... 查看详情

goweb编程实战----并发goroutine(代码片段)

目录什么是goroutine?使用方式什么是goroutine?在Go语言中,每一个并发执行的活动被称为goroutine。使用go关键字可以创建goroutine,其完整定义如下:gofunc_name()其中,go是关键字,需要放在一个需要调用的函数之前&#... 查看详情

goweb编程实战----创建客户端(代码片段)

目录创建一个客户端Get()请求Post()请求请求头设置创建一个客户端在Go语言的net/http包中,还提供了一个被称为Client的结构体。该结构体提供了Get()、Post()两个请求函数。下面,我们来分别使用代码实现这些请求。Get()请求... 查看详情

goweb编程实战----go语言的基础语法(代码片段)

目录前言HelloWorld包的声明与导入运行程序方式基础语法注释标识符变量常量运算符前言很高兴能够一起和大家学习Go语言,对于它的场景其实很多,包括云计算、容器虚拟化、分布式存储、网络爬虫、运维开发、Web开发... 查看详情

goweb编程实战----go语言的基础语法(代码片段)

目录前言HelloWorld包的声明与导入运行程序方式基础语法注释标识符变量常量运算符前言很高兴能够一起和大家学习Go语言,对于它的场景其实很多,包括云计算、容器虚拟化、分布式存储、网络爬虫、运维开发、Web开发... 查看详情

goweb编程实战----创建http与https服务器端(代码片段)

目录创建一个HTTP服务端ListenAndServe()ServeHTTP()方法的使用示例定义Refer结构体实现ServeHTTP()方法创建一个HTTPS服务端创建证书与私钥创建HTTPS服务端创建一个HTTP服务端其实Go语言创建一个简单的HTTP服务器程序,与JavaWeb的servlet差... 查看详情

goweb编程实战(10)----模板引擎库text/template包的使用(代码片段)

目录前言模板引擎定义模板文件解析模板文件渲染模板实战使用模板创建.tmpl文件创建文件用于解析与渲染模板前言在Go语言中,模板引擎库text/template包主要用于处理任意格式的文本内容,同时还提供了html/template包,... 查看详情

day861.actor模型-java并发编程实战(代码片段)

...内容。上学的时候,有门计算机专业课叫做面向对象编程,学这门课的时候有个问题困扰,按照面向对象编程的理论,对象之间通信需要依靠消息,而实际上,像C& 查看详情