28

Go语言教程之结构体

 4 years ago
source link: https://segmentfault.com/a/1190000021568628
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Hello,大家好,我是小栈君,最近因为工作的事情延误了一点分享的进度,但是我会尽量抽时间分享关于IT干货知识,还希望大家能够持续关注“IT干货栈”哦。

闲话不多说,今天给大家继续分享关于Go语言的教程知识之结构体。

对象

在介绍结构体之前,我们先讲讲编程语言中的对象的概念吧,因为在相关的程序开发过程中,我们通常是面向对象进行编程,就是将相关的属性和方法组合成一个整体来看待。

因为对于大多数人而言,程序的编码是一个非常抽象的东西,我们要实现的功能需要具现化,比如说我要用程序语言描述出车的概念,那么它必须具有相关的属性,比如车有相关的名字,车具有长度,宽度,轮子,颜色等等。

当然车还具有相关的方法,就是能开,能停,我们还可以根据我们自己的想法,营造出特别的车,比如能喷火,能上天,能变身等等,这些行为在程序语言中就代表这一种方法。

所以千万别小瞧程序员,在程序的语言中,我们可以无所不能的。这些属性和方法的集合我们在程序编写中会将他们看作是一个整体,即对象。

我们在面向对象编程的时候通常讲了几个要求,即抽象,继承,封装和多态。面向对象的方法就是利用抽象、封装等机制,借助于对象、类、继承、消息传递等概念进行软件系统构造的软件开发方法。

Go语言Struct

简单的介绍完对象和面向对象概念之后,我们在Go语言中使用struct关键字表示一个对象,它主要是的格式如图所示:

RnIjuiu.jpg!web

我们定一个车的结构体,它所具有的特征就是颜色,名称,长度,当然根据我们的需求,他还可以有更多的属性,这样的一个结构体。

我们可以看做是一个对象。它主要用于定义一个复杂的数据结构。在一个struct中我们可以包含许多字段(即属性),当然在我们定义的结构体中,我们不仅可以定义相关的属性,他还可以定义相应的方法。

nUFf2aM.jpg!web

例如上图所示,我们定义的车,就有两个方法,一个是跑,一个是飞。它定义的方法是和我们函数定义的方法有所有区别的,这里定义的方法就是我们车这个对象独享的。

之前定义的方法是所有满足条件的都可以使用。而且在图片中,小栈君也明确的标注了,在go语言中不管是方法还是对象还包括属性都是大小写敏感的。

大写表示公开,相当于java中的public。小写表示私有,相当于java中的private,而且使用指针和不使用指针,也是两个概念,Struct中是值类型。

NN7FRnb.jpg!web

例如上图中,我们给car定义了两个方法,一个使用指针,一个不使用指针。同样的是改变名字。

车最原始的名字,我们定义了一个两米的红色奔驰,使用changeName()方法,这个方法用的不是指针类型。

所以我们可以看到,车的名字在使用该方法后并没有改变成保时捷,依旧是奔驰,是这个方法不生效么?其实不是。

因为struct是值传递。所以当我们不使用指针的时候,这个方法只是在该方法体内生效,出了这个方法后,是什么样子就是什么样子。

meAvUnr.jpg!web

口说无凭,直接搬上例子说明。所以我们可以根据具体的需求,按需进行给我们的对象进行设置方法。[奔驰,宝马、保时捷,你们可以给我广告费啦~]。

继承

当然做过编程的同学可以知道,我们在其他编程语言中有父类的概念,也就是继承。而且在struct中是可以进行嵌套。

所以Go语言中并没有class类型,相对java,他的结构体只有struct类型,而且相比于java的继承,struct中并没有extends关键字。

2AfYneN.jpg!web

如上图所示,我们就已经完成了相关的继承。SmallCar已经完美的继承了关于Car的属性。

JzYv6bn.jpg!web

这里也可以看到我们对我们的smallCar进行赋值,其实赋值的方式有很多种,在之前的文章中有和大家聊过这个问题。除了继承了Car的属性之外也继承了car的方法。

Q3Mjymr.jpg!web

所以,在以后的项目或者实战中,我们可以很好的利用这个点进行我们基类的抽取,然后进行封装,以达到我们在软件编写中的封装性、高内聚。

Struct的内存布局

Go语言中的struct类型中,它的内存布局是连续性的

vMbmE37.jpg!web

就按照我们之前的Car举例子,我们定义的字段顺序,就是Go语言的内存布局中的顺序。

我们来进行验证一下,看看实际的效果

RvaQzqy.jpg!web

其他给大家介绍一下在结构体中的字段可以不需要定义名称,这样的字段就是匿名字段,当然一种字段类型只允许出现一次。

否则Go语言也不能判定出,你在赋值的时候到底指定的是谁。

其实想和大家聊点题外话,因为工作的原因,小栈君创作的原创确实不太容易,主要是时间不够,因为想分享的东西太多,对于我自身而言也是知识的归纳和总结,做程序的讲究的是开源精神和分享精神。

所以小栈君为了避免长期断更的情况下,尽量勤分享,但是可能说篇幅不会太大,一节一节分享,毕竟之前的分享基本上是两千字或是更多,可以说是干货满满。

但是这样的篇幅写下来确实是精力跟不上,所以我会拆成小点,进行小记分享。以后我们就进行我们的小记分享,小栈君也尽力做到两天一更或一天一更。

这样大家也可以每天花3到5分钟进行了解和提高。也非常感谢大家对小栈君的关注。你的关注就是我坚持的动力,我们明天见~拜了个拜~

package main

import "fmt"

// IT干货栈 定义一个结构体[大小写敏感]
type Car struct {
  Name   string  // 名称
  Color  string  // 颜色
  Length float32 // 长度
}

// 定义一个小车 结构
type SmallCar struct {
  Car            // 车
  Height float32 // 高度

}

func (car *Car) run() {
  fmt.Println(car.Name, "正在迅速行驶。。。。")
}

func (car *Car) fly() {
  fmt.Println(car.Name, "正在飞行。。。。")
}
func (car Car) changeName() {
  car.Name = "保时捷"
}
func (car *Car) realChangeName() {
  car.Name = "宝马"
}

// IT干货栈
func main() {
  var car Car
  car.Name = "小栈"
  car.Color = "red"
  car.Length = 2.0
  fmt.Println(car)
  fmt.Printf("Name: %p\n", &car.Name)
  fmt.Printf("Color: %p\n", &car.Color)
  fmt.Printf("Length: %p\n", &car.Length)

}

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK