一、 golang面向对象介绍

1、golang也支持面向对象编程,但是和传统的面向对象编程有区别,并不是纯粹的面向对象语言。
2、golang没有类(class),golang语言的结合体(struct)和其它编程语言的类有同等的地位。
3、golang面向对象编程,去掉了传统语言面向对象的继承、方法重载、结构函数和析构函数、隐藏的this指针等。
4、goalng仍然有面向对象编程的继承,封装和多态的特性,。
5、golang面向接口编程非常重要

二、结构体创建注意事项

1、字段申明语法同变量
2、字段的类型可以为:基本类型、数组或应用类型
3、在创建一个结构体变量后,如果没有给字段赋值,都对应改类型的默认值(如bool为false,int为0,string为"")
4、不同结构体变量的字段是独立互不影响的,一个结构体变量字段的更改不会影响另一个结构体的值类型。

三、创建struct语法

type 结构体名称 struct{
field type
}

创建例子:

type stru struct{
a1 string
a2 int
a3 [5]float64
a4 []int //切片
a5 *int //指针
a6 map[string]string //map
}

  

使用例子:

package main
import "fmt" func main(){
type ss struct{
Name string
Age int
}
//1、直接申明
var ss1 ss
ss1.Name = "张三"
ss1.Age = 20
fmt.Println(ss1)
//2、使用{}
var ss2 ss = ss{"李四",22}
fmt.Println(ss2)
//3、&
var ss3 *ss = new(ss)
(*ss3).Name = "王五"
(*ss3).Age = 30
fmt.Println(ss3,*ss3)
//4、{}
var ss4 *ss = &ss{}
ss4.Name = "韩梅梅"
ss4.Age = 66
fmt.Println(ss4,*ss4) } ###结果###
{张三 20}
{李四 22}
&{王五 30} {王五 30}
&{韩梅梅 66} {韩梅梅 66}

  

四、结构体使用注意事项

1、结构体的所有字段在内存中是连续的

例子:

package main
import "fmt" type Point struct {
x int
y int
} type Test1 struct {
s1,s2 Point
} func main(){
a1 := Test1{Point{1,2},Point{3,4}}
//打印地址
fmt.Printf("%p,%p,%p,%p",&a1.s1.x,&a1.s1.y,&a1.s2.x,&a1.s2.y) } ##结果##
0xc4200141e0,0xc4200141e8,0xc4200141f0,0xc4200141f8

  

2、结构体是用户单独定义的类型,和其它类型进行转换时需要有完全相同的字段(名字、个数和类型

例子:

package main
import "fmt" type A struct {
x int
} type B struct {
x int
} func main(){
var a A
var b B
b.x = 2
a = A(b) //可以转换,但是结构体的字段和类型必须完全一样
fmt.Println(a,b)
} ###结果###
{2} {2}

  

3、结构体进行 type 重新定义(相当于取别名),Golang 认为是新的数据类型,但是相互间可以强转

例子:

package main
import "fmt" func main(){
type A struct {
x int
}
type B A
var s1 A
var s2 B
s2 = B(s1) //强转
fmt.Println(s1,s2) } ##结果##
{0} {0}

  

4、struct 的每个字段上,可以写上一个 tag, 该 tag 可以通过反射机制获取,常见的使用场景就是序列化和反序列化

序列化的使用场景:

例子:

package main
import (
"fmt"
"encoding/json"
)
type A struct {
Name string `json:"name"` //`json:"name"`就是struct的tag
Age int `json:"age"`
} func main(){
s1 := A{"张三",20}
//将s1变量序列化为json格式字符串
jsonStr,err := json.Marshal(s1)
if err != nil {
fmt.Println("json错误处理",err)
}
fmt.Println(string(jsonStr))
} ###结果###
{"name":"张三","age":20}

  

五、结构体的方法

方法的声明和调用
type A struct {
Num int
}
func (a A) test() {
fmt.Println(a.Num)
}
语法的说明
1) func (a A) test() {} 表示 A 结构体有一方法,方法名为 test
2) (a A) 体现 test 方法是和 A 类型绑定的

例子:

package main
import "fmt" type A struct {
Name string
}
//test方法只能公告A类型的变量类调用,不能直接调用,也不能使用其它类型变量来调用
func (a A) test(){ //将test方法绑定到A类型中,a的名字是随意指定的
fmt.Println("test()",a.Name)
} func (b A) add(n1,n2 int) int {
return n1 + n2
} func main(){
var x A
x.Name = "zhang"
x.test()
fmt.Println(x.add(1,2))
}
####结果####
test() zhang
3

  

六、golang面向对象的三大特性

1、封装

封装(encapsulation)就是把抽象出的字段和对字段的操作封装在一起,数据被保护在内部,程序的其它包只有通过被授权的操作(方法),才能对字段进行操作封装的好处

1、隐藏实现细节
2、提可以对数据进行验证,保证安全合理

2、封装的实现步骤

1) 将结构体、字段(属性)的首字母小写(不能导出了,其它包不能使用,类似 private)
2) 给结构体所在包提供一个工厂模式的函数,首字母大写。类似一个构造函数
3) 提供一个首字母大写的 Set 方法(类似其它语言的 public),用于对属性判断并赋值
func (var 结构体类型名) SetXxx(参数列表) (返回值列表) {
//加入数据验证的业务逻辑
var.字段 = 参数
}
4) 提供一个首字母大写的 Get 方法(类似其它语言的 public),用于获取属性的值func (var 结构体类型名) GetXxx() {return var.age

例子:

[root@localhostgo_test]#cat src/fz/fz.go
package fz
import "fmt" type T1 struct {
Name string
age int //开头是小写,其它包不能直接访问
} func Ss(name string) *T1 {
return &T1{
Name:name,
}
} func (a *T1) Getage() int {
fmt.Println(a.age)
return a.age
} [root@localhostgo_test]#cat class6.go
package main
import (
"fmt"
"fz"
) func main(){
x := fz.Ss("root")
fmt.Println(x)
x.Getage()
}
[root@localhostgo_test]#go run class6.go
&{root 0}
0

  

2、继承

继承可以解决代码复用,让我们的编程更加靠近人类思维。
当多个结构体存在相同的属性(字段)和方法时,可以从这些结构体中抽象出结构体,在该结构体中定义这些相同的属性和方法
在 Golang 中,如果一个 struct 嵌套了另一个匿名结构体,那么这个结构体可以直接访问匿名结构体的字段和方法,从而实现了继承特性

继承给编程带来的便利

1) 代码的复用性提高了
2) 代码的扩展性和维护性提

嵌套匿名结构体的基本语法
type Goods struct {
Name string
Price int
}
type Book struct {
Goods //这里就是嵌套匿名结构体 Goods
Writer string
}

例子:

package main
import "fmt" type A struct {
name string
age int
} func (p *A) Run() {
fmt.Println("Run...")
} type B struct {
A
b1 int
} type C struct {
A
} func (p *C) Crun() {
fmt.Println(p.name,p.age)
} func main(){
var q B
q.name = "qq"
q.age = 3
q.b1 = 20
q.Run()
fmt.Println(q)
fmt.Println("==========")
var w C
w.name = "ww"
w.age = 222
w.Run()
fmt.Println(&w) } ####结果######
Run...
{{qq 3} 20}
==========
Run...
&{{ww 222}}

  

3、多态(多态基于接口interface)

介绍:

变量(实例)具有多种形态。面向对象的第三大特征,在 Go 语言,多态特征是通过接口实现的。可以按照统一的接口来调用不同的实现。这时接口变量就呈现不同的形态

接口体现多态的两种形式

1、在下面interface的 Usb 接口案例,Usb usb ,即可以接收手机变量,又可以接收相机变量,就体现了Usb接口多态

2、多态数组

例子:给 Usb 数组中,存放 Phone 结构体 和 Camera 结构体变量

package main
import ( "fmt"
)
//声明/定义一个接口
type Usb interface {
//声明了两个没有实现的方法
Start()
Stop()
}
type Phone struct {
name string
}
//让 Phone 实现 Usb 接口的方法
func (p Phone) Start() {
fmt.Println("手机开始工作。。。")
}
func (p Phone) Stop() {
fmt.Println("手机停止工作。。。")
}
type Camera struct {
name string
}
//让 Camera 实现 Usb 接口的方法
func (c Camera) Start() {
fmt.Println("相机开始工作。。。")
}
func (c Camera) Stop() {
fmt.Println("相机停止工作。。。")
}
func main() {
//定义一个 Usb 接口数组,可以存放 Phone 和 Camera 的结构体变量
//这里就体现出多态数组
var usbArr [3]Usb
usbArr[0] = Phone{"vivo"}
usbArr[1] = Phone{"小米"}
usbArr[2] = Camera{"尼康"}
fmt.Println(usbArr)
} #####结果#######
[{vivo} {小米} {尼康}]

  

七、接口interface

简介

1、interface 类型可以定义一组方法,但是这些不需要实现。并且 interface 不能包含任何变量。到某个自定义类型要使用的时候,在根据具体情况把这些方法写出来实现

2、 接口里的所有方法都没有方法体,即接口的方法都是没有实现的方法。接口体现了程序设计的多态和高内聚低偶合的思想。
3、 Golang 中的接口,不需要显式的实现。只要一个变量,含有接口类型中的所有方法,那么这个变量就实现这个接口。因此,Golang 中没有 implement 这样的关键字

基本语法

例子:

package main
import ( "fmt"
)
//声明/定义一个接口
type Usb interface {
//声明了两个没有实现的方法
Start()
Stop()
}
type Phone struct {
}
//让 Phone 实现 Usb 接口的方法
func (p Phone) Start() {
fmt.Println("手机开始工作。。。")
}
func (p Phone) Stop() {
fmt.Println("手机停止工作。。。")
}
type Camera struct {
}
//让 Camera 实现 Usb 接口的方法
func (c Camera) Start() {
fmt.Println("相机开始工作。。。")
}
func (c Camera) Stop() {
fmt.Println("相机停止工作。。。")
}
//计算机
type Computer struct {
}
//编写一个方法 Working 方法,接收一个 Usb 接口类型变量
//只要是实现了 Usb 接口 (所谓实现 Usb 接口,就是指实现了 Usb 接口声明所有方法)
func (c Computer) Working(usb Usb) { //usb 变量会根据传入的实参,来判断到底是 Phone,还是 Camera
//通过 usb 接口变量来调用 Start 和 Stop 方法
usb.Start()
usb.Stop()
}
func main() {
//测试
//先创建结构体变量
computer := Computer{}
phone := Phone{}
camera := Camera{}
//关键点
computer.Working(phone)
computer.Working(camera)
} #####结果####
手机开始工作。。。
手机停止工作。。。
相机开始工作。。。
相机停止工作。。。

  

使用接口注意事项

1、接口本身不能创建实例,但是可以指向一个实现了该接口的自定义类型的变量(实例)
2、接口中所有的方法都没有方法体,即都是没有实现的方法。
3、在 Golang 中,一个自定义类型需要将某个接口的所有方法都实现,我们说这个自定义类型实现了该接口。
4、一个自定义类型只有实现了某个接口,才能将该自定义类型的实例(变量)赋给接口类型
5、只要是自定义数据类型,就可以实现接口,不仅仅是结构体类型。
6、一个自定义类型可以实现多个接口
7、Golang 接口中不能有任何变量
8、一个接口(比如 A 接口)可以继承多个别的接口(比如 B,C 接口),这时如果要实现 A 接口,也必须将 B,C 接口的方法也全部实现。
9、interface 类型默认是一个指针(引用类型),如果没有对 interface 初始化就使用,那么会输出 nil
10、空接口 interface{} 没有任何方法,所以所有类型都实现了空接口, 即我们可以把任何一个变量赋给空接口

接口最佳实践例子:

package main
import ( "fmt"
"sort"
"math/rand"
)
//1.声明 Hero 结构体
type Hero struct{
Name string
Age int
}
//2.声明一个 Hero 结构体切片类型
type HeroSlice []Hero //3.实现 Interface 接口
func (hs HeroSlice) Len() int {
return len(hs)
}
//Less 方法就是决定你使用什么标准进行排序
//1. 按 Hero 的年龄从小到大排序!!
func (hs HeroSlice) Less(i, j int) bool {
return hs[i].Age < hs[j].Age
//修改成对 Name 排序
//return hs[i].Name < hs[j].Name
}
func (hs HeroSlice) Swap(i, j int) {
//交换
hs[i], hs[j] = hs[j], hs[i]
}
//1.声明 Student 结构体
type Student struct{
Name string
Age int
Score float64
}
//将 Student 的切片,安 Score 从大到小排序!!
func main() {
//先定义一个数组/切片
var intSlice = []int{0, -1, 10, 7, 90}
//要求对 intSlice 切片进行排序
//1. 冒泡排序...
sort.Ints(intSlice)
fmt.Println(intSlice)
//测试看看我们是否可以对结构体切片进行排序
var heroes HeroSlice
for i := 0; i < 10 ; i++ {
hero := Hero{
Name : fmt.Sprintf("英雄|%d", rand.Intn(100)), Age : rand.Intn(100), }
//将 hero append 到 heroes 切片
heroes = append(heroes, hero)
}
//看看排序前的顺序
for _ , v := range heroes {
fmt.Println(v)
}
sort.Sort(heroes)
fmt.Println("-----------排序后------------")
//看看排序后的顺序
for _ , v := range heroes {
fmt.Println(v)
}
i := 10
j := 20
i, j = j, i
fmt.Println("i=", i, "j=", j) // i=20 j = 10
} ######运行结果######
[-1 0 7 10 90]
{英雄|81 87}
{英雄|47 59}
{英雄|81 18}
{英雄|25 40}
{英雄|56 0}
{英雄|94 11}
{英雄|62 89}
{英雄|28 74}
{英雄|11 45}
{英雄|37 6}
-----------排序后------------
{英雄|56 0}
{英雄|37 6}
{英雄|94 11}
{英雄|81 18}
{英雄|25 40}
{英雄|11 45}
{英雄|47 59}
{英雄|28 74}
{英雄|81 87}
{英雄|62 89}
i= 20 j= 10

  

golang面向对象和interface接口的更多相关文章

  1. 【GoLang】golang 面向对象编程 & 面向接口编程

    005.面向对象&接口编程 1 面向函数编程 1.1 将数据作为参数传递到函数入参 1.2 对象与函数是分离的 2 面向对象编程 2.1 使用者看起来函数作为对象的属性而非参数 2.2 函数属 ...

  2. PHP面向对象(OOP):PHP5接口技术(interface)

    PHP与大多数面向对象编程语言一样,不支持多重继承.也就是说每个类只能继承一个父类.为了解决这个问题,PHP引入了接口,接口的思想是指定了一个实现了该接口的类必须实现的一系列方法.接口是一种特殊的抽象 ...

  3. Golang 入门系列(四)如何理解interface接口

    前面讲了很多Go 语言的基础知识,包括go环境的安装,go语言的语法等,感兴趣的朋友,可以先看看之前的文章.https://www.cnblogs.com/zhangweizhong/category ...

  4. Golang基础(8):go interface接口

    一:接口概要 接口是一种重要的类型,他是一组确定的方法集合. 一个接口变量可以存储任何实现了接口方法的具体值.一个重要的例子就是io.Reader和io.Writer type Reader inte ...

  5. java 面向对象(二十四):interface:接口

    interface:接口1.使用说明: 1.接口使用interface来定义 * 2.Java中,接口和类是并列的两个结构 * 3.如何定义接口:定义接口中的成员 * * 3.1 JDK7及以前:只能 ...

  6. Java面向对象之 接口: [修饰符] interface 接口名 {...};子接口:[修饰符] interface 接口名 extends 父接口,父接口2...{...}

    1.什么是接口? 类比抽象类,把功能或者特性类似的一类 抽象的更彻底,可以提炼出更加特殊的"抽象类"----接口 2.如何定义接口 语法:  [修饰符] interface 接口名 ...

  7. GoLang之方法与接口

    GoLang之方法与接口 Go语言没有沿袭传统面向对象编程中的诸多概念,比如继承.虚函数.构造函数和析构函数.隐藏的this指针等. 方法 Go 语言中同时有函数和方法.方法就是一个包含了接受者的函数 ...

  8. golang 面向对象编程

    概述 Golang语言的面向对象与c++,py等语言有所不同,是由于Golang不支持继承:与上述支持聚合和继承的面向对象的语言不同,Golang只支持聚合(也叫做组合)和嵌入.聚合和嵌入的区别: t ...

  9. go interface接口

    一:接口概要 接口是一种重要的类型,他是一组确定的方法集合. 一个接口变量可以存储任何实现了接口方法的具体值.一个重要的例子就是io.Reader和io.Writer type Reader inte ...

随机推荐

  1. Node.js 命令行工具的编写

    日常开发中,编写 Node.js 命令行工具来完成一些小任务是很常见的操作.其编写也不难,和日常编写 Node.js 代码并无二致. package.json 中的 bin 字段 一个 npm 模块, ...

  2. 【activity任务栈】浅析

    背景知识 Activity四种启动模式 标准模式 standard 栈顶复用模式 singleTop 栈内复用模式 singleTask 单例模式 singleInstance 任务栈 Activit ...

  3. 系列文章|OKR与敏捷(三):赋予团队自主权

    OKR与敏捷开发的原理有着相似之处,但已经使用敏捷的团队再用OKR感觉会显得多余.这种误解的根源就在于对这两种模式不够了解,运用得当的情况下,OKR和敏捷可以形成强强联合的效果,他们可以创造出以价值为 ...

  4. python学习第九讲,python中的数据类型,字符串的使用与介绍

    目录 python学习第九讲,python中的数据类型,字符串的使用与介绍 一丶字符串 1.字符串的定义 2.字符串的常见操作 3.字符串操作 len count index操作 4.判断空白字符,判 ...

  5. Java设计模式系列-装饰器模式

    原创文章,转载请标注出处:<Java设计模式系列-装饰器模式> 一.概述 装饰器模式作用是针对目标方法进行增强,提供新的功能或者额外的功能. 不同于适配器模式和桥接模式,装饰器模式涉及的是 ...

  6. JAVA WEB快速入门之从编写一个基于SpringBoot+Mybatis快速创建的REST API项目了解SpringBoot、SpringMVC REST API、Mybatis等相关知识

    JAVA WEB快速入门系列之前的相关文章如下:(文章全部本人[梦在旅途原创],文中内容可能部份图片.代码参照网上资源) 第一篇:JAVA WEB快速入门之环境搭建 第二篇:JAVA WEB快速入门之 ...

  7. Springboot 系列(十二)使用 Mybatis 集成 pagehelper 分页插件和 mapper 插件

    前言 在 Springboot 系列文章第十一篇里(使用 Mybatis(自动生成插件) 访问数据库),实验了 Springboot 结合 Mybatis 以及 Mybatis-generator 生 ...

  8. c# aes,des,md5加密等解密算法

    一:可逆加密,即是能加密也能解密 对称可逆加密:加密后能解密回原文,加密key和解密key是一个 加密算法都是公开的,密钥是保密的, 即使拿到密文 你是推算不了密钥 也推算不了原文 加密解密的速度快, ...

  9. 在java中如何实现字符串的反转

    如 "abcdt" 反转之后是 "tdcba" 思路1: 运用递归的方法进行反转 假设反转方法为 reverseString(String str)1)当字符串 ...

  10. JavaScript中的typeof

    js中的 typeof 操作符返回一个字符串,表示未经计算的操作数的类型. 其中null.字符串对象.数字对象.布尔对象.日期.数组.正则返回结果都为object,可见typeof返回结果并不精确 测 ...