golang中并没有明确的面向对象的说法,实在要扯上的话,可以将struct比作其它语言中的class。

类声明

  1. type Book struct {
  2. Title string
  3. Author string
  4. intro string
  5. }

  这样就声明了一个类,其中没有public、protected、private的的声明。golang用另外一种做法来实现属性的访问权限:属性的开头字母是大写的则在其它包中可以被访问,否则只能在本包中访问。类的声明和方法亦是如此。

类方法声明

  1. // 类方法声明-传递值对象
  2. func (b Book) B1() {
  3. b.Title = "Book001"
  4. b.Author = "ErWan"
  5. }
  6.  
  7. // 类方法声明-传递指针对象
  8. func (b *Book) B2() {
  9. b.Title = "Book002"
  10. b.Author = "Tinywan"
  11. }

  和其它语言不一样,golang声明方法和普通方法一致,只是在func后增加了b Book这样的声明。加和没有加*的区别在于一个是传递指针对象(加*),一个是传递值对象。

传递指针和对象的区别

  1. package main
  2.  
  3. import "fmt"
  4.  
  5. // 类声明
  6. type Book struct {
  7. Title string
  8. Author string
  9. DateTime string
  10. }
  11.  
  12. // 类方法声明-传递值对象
  13. func (b Book) B1() {
  14. b.Title = "Book001"
  15. b.Author = "ErWan"
  16. }
  17.  
  18. // 类方法声明-传递指针对象
  19. func (b *Book) B2() {
  20. b.Title = "Book002"
  21. b.Author = "Tinywan"
  22. }
  23.  
  24. func main() {
  25. /*声明一个 Book 类型的变量 b ,并调用 B1() 和 B2()*/
  26. b := Book{"Def-Book", "Def-Author", "Def-DateTime"}
  27.  
  28. fmt.Println("B1 调用前:", b.Title, b.Author, b.DateTime)
  29. b.B1()
  30. fmt.Println("B1 调用后:", b.Title)
  31.  
  32. fmt.Println("------------------\r\n")
  33. fmt.Println("B2 调用前:", b.Title)
  34. b.B2()
  35. fmt.Println("B2 调用后:", b.Title)
  36.  
  37. }

执行结果:

B1() 的接收者是值类型 Book, B2() 的接收者是值类型 *Book , 两个方法内都是改变Name值。

小结:

  1、接收者可以看作是函数的第一个参数,即这样的: func B1(b Book), func B2(b *Book)。 go不是面向对象的语言,所以用那种看起来像面向对象的语法来理解可能有偏差。

  2、当调用 b.B1() 时相当于 B1(b) ,实参和行参都是类型 Book,可以接受。此时在B1()中的b只是 "Def-Book" 的值拷贝,所以B1()的修改影响不到" Def-Book"。

  3、当调用 b.B2() => B2(b1),这是将 Book 类型传给了 *Book 类型,go可能会取 b 的地址传进去: B2(&b)。所以 B2() 的修改可以影响 b 。

例如在一个beego 框架中我们要修改一个action的值,是这么定义的(为了修改内部结构的值。而不是传递一下)

  1. func (this *InputController) InputGet(){
         // Get 方式接受
  2. name := this.GetString("name")
  3. // 不使用模版,直接用 this.Ctx.WriteString 输出字符串
  4. this.Ctx.WriteString(name)
  5. }

值类型不可以改变值,而指针类型则是可以的

匿名结构体

  1. p := struct {
  2. Name string
  3. Gender string
  4. Age uint8
  5. }{"Robert", "Male", 33}

匿名结构体最大的用处是在内部临时创建一个结构以封装数据,而不必正式为其声明相关规则。 

实例化对象

实例化对象有好几种方式:

  1. package main
  2.  
  3. // 类声明
  4. type Person struct {
  5. Name string
  6. Age int
  7. Doc []string // slice切片
  8. }
  9.  
  10. // 类方法声明-传递值对象
  11. func (p *Person) P1() {
  12. p.Name = "Tinywan"
  13. p.Age = 24
  14. }
  15.  
  16. // 类方法声明-传递指针对象
  17. func (p *Person) P2() {
  18. p.Name = "Tinyaiai"
  19. p.Age = 22
  20. }
  21.  
  22. func main() {
  23.  
  24. // 实例化对象 实例化的时候可以初始化属性值,如果没有指明则默认为系统默认值
  25. p1 := &Person{}
  26. p1.Name = "ShaoBo Wan"
  27. p1.Age = 20
  28.  
  29. p2 := &Person{Name:"HaHa"}
  30.  
  31. p3 := new(Person)
  32. p3.Name = "New Name"
  33.  
  34. p4 := Person{}
  35. p4.Name = "Name 001"
  36. p4.Age = 26
  37.  
  38. p5 := Person{Name:"Name 002",Age:28}
  39.  
  40. // 使用中如果包含数组(动态数组 slice切片),结构体的实例化需要加上类型如上如果intro的类型是[]string
  41. p6 := &Person{
  42. "zhangsan",
  43. 25,
  44. []string{"lisi", "wangwu"},
  45. }
  46. }

注意,最后一个实例化

  1. p6 := &Person{
  2. "zhangsan",
  3. 25,
  4. []string{"lisi", "wangwu"},
  5. }

小结:

  1、使用中如果包含数组,结构体的实例化需要加上类型如上如果Doc的类型是[]string。  

  2、实例化的时候可以初始化属性值,如果没有指明则默认为系统默认值。

  3、加&符号和new的是指针对象,没有的则是值对象,这点和php、java不一致,在传递对象的时候要根据实际情况来决定是要传递指针还是值

  4、当对象比较小的时候传递指针并不划算。

继承

确切的说golang中叫做组合(composition)

1、先初始化为空再赋值

  1. // 先初始化为空再赋值
  2. s1 := &Student{}
  3. s1.schoole = "QiHua"

2、直接赋值

  1. // 直接赋值
  2. s2 := &Student{
  3. Persons: Persons{
  4. Name:"Tinywan",
  5. Age:24,
  6. Doc:[]string{"H1","h2"},
  7. },
  8. schoole:"BeiJin Schoole",
  9. }

3、完整代码

  1. package main
  2.  
  3. import (
  4. "fmt"
  5. )
  6.  
  7. // 类声明
  8. type Persons struct {
  9. Name string
  10. Age int
  11. Doc []string // slice切片
  12. }
  13.  
  14. // 获取Name
  15. func (p *Persons) getName() {
  16. fmt.Println("Name is ",p.Name)
  17. }
  18.  
  19. type Student struct {
  20. // Student 属性中声明了 Persons,表示组合了Persons 的属性和方法(属性和方法都会被继承)
  21. Persons
  22. Name string
  23. schoole string
  24. }
  25.  
  26. func main() {
  27.  
  28. // 先初始化为空再赋值
  29. s1 := &Student{}
  30. // 当访问Name的时候默认为ProsePoem的 Name,如果需要访问Persons 的 Name 属性可以使用 s1.Persons.Name 来访问方法同理。
  31. s1.Name = "Tinywan"
  32. s1.Persons.Name = "Persons Name"
  33. s1.schoole = "QiHua"
  34. fmt.Println("s1 = ",s1)
  35. fmt.Println("\r\n")
  36.  
  37. // 直接赋值
  38. s2 := &Student{
  39. Persons: Persons{
  40. Name:"Tinywan",
  41. Age:24,
  42. Doc:[]string{"s2-Doc","s2-Doc"},
  43. },
  44. Name:"ErWan",
  45. schoole:"BeiJin-Schoole",
  46. }
  47. fmt.Println("s2 = ",s2)
  48. }

方法的继承和属性一致

  

参考

1、https://segmentfault.com/a/1190000012325027

2、 

Golang入门教程(十四)结构体和类详解的更多相关文章

  1. Golang入门教程(十三)延迟函数defer详解

    前言 大家都知道go语言的defer功能很强大,对于资源管理非常方便,但是如果没用好,也会有陷阱哦.Go 语言中延迟函数 defer 充当着 try...catch 的重任,使用起来也非常简便,然而在 ...

  2. RabbitMQ入门教程(十四):RabbitMQ单机集群搭建

    原文:RabbitMQ入门教程(十四):RabbitMQ单机集群搭建 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://b ...

  3. 无废话ExtJs 入门教程十四[文本编辑器:Editor]

    无废话ExtJs 入门教程十四[文本编辑器:Editor] extjs技术交流,欢迎加群(201926085) ExtJs自带的编辑器没有图片上传的功能,大部分时候能够满足我们的需要. 但有时候这个功 ...

  4. “全栈2019”Java第九十四章:局部内部类详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  5. VS2010/MFC编程入门之三十八(状态栏的使用详解)

    上一节中鸡啄米讲了工具栏的创建.停靠与使用,本节来讲解状态栏的知识. 状态栏简介 状态栏相信大家在很多窗口中都能见到,它总是用来显示各种状态.状态栏实际上也是一个窗口,一般分为几个窗格,每个窗格分别用 ...

  6. Linux C Socket编程发送结构体、文件详解及实例

    利用Socket发送文件.结构体.数字等,是在Socket编程中经常需要用到的.由于Socket只能发送字符串,所以可以使用发送字符串的方式发送文件.结构体.数字等等. 本文:http://www.c ...

  7. C/C++结构体字节对齐详解

    结构体的sizeof先看一个结构体:struct S1{    char c;    int i;}; sizeof(S1)在VC6中按默认设置得到的结果为8.我们先看看sizeof的定义——size ...

  8. Golang入门教程(四)变量声明

    Go 语言变量名由字母.数字.下划线组成,其中首个字母不能为数字. 一.Go的语言结构 1.Go的语言基础部分由这几个部分组成 包声明 引入包 函数 变量 语句&表达式 注释 比如下面这个简单 ...

  9. SpringBoot入门教程(十四)导出Excel

    用JavaPOI导出Excel时,我们会考虑到Excel版本及数据量的问题.针对不同的Excel版本,要采用不同的工具类.HSSFWorkbook:是操作Excel2003以前(包括2003)的版本, ...

随机推荐

  1. CODEFORCES掉RATING记 #4

    比赛:Codeforces Round #427 (Div. 2) 时间:2017.7.31晚 开场发现有6道题,都是水题(可能我只会做水题) A:比较\(2t_1+sv_1\)与\(2t_2+sv_ ...

  2. Django的Hello World

    Django安装 yum -y install python #安装python yum -y install epel-release #安装扩展源 yum -y install python-pi ...

  3. Finding Lines UVALive - 6955(随机)

    给出n个点,问你有没有可能存在一条直线,这n个点中存在百分号p以上点在这条直线上. 两个点确定一条直线,所以可以随机枚举两个点,然后用这条直线去判断其他的点是不是在这条直线上,如果在这个直线上的点超过 ...

  4. 【php】php实现数组反转

    php里面有个函数可以反转数组,工作中也经常用到,非常方便.今天来自己实现这样的功能. $arr = [2,5,6,1,8,16,12]; function reverse($arr){ $left ...

  5. gradle配置统一管理

    配置全局参数 根目录build.gradle文件: 主要关注ext部分 // Top-level build file where you can add configuration options ...

  6. Java collection 容器

    http://www.codeceo.com/article/java-container-brief-introduction.html Java实用类库提供了一套相当完整的容器来帮助我们解决很多具 ...

  7. jQuery ajax读取本地json文件

    jQuery ajax读取本地json文件 json文件 { "first":[ {"name":"张三","sex": ...

  8. poj2054 Color a Tree

    神题.这题是巨毒瘤... 自己写真可谓是: 排空驭气奔如电,上天入地求之遍 上穷碧落下黄泉,两处茫茫皆不见 由于我们知道:不是树形时,不停选值最大的节点可以得到最小代价. 那么我们就能想出一个错误的贪 ...

  9. Spring 学习笔记一

    1.IOC,DI. 2.装配bean基于xml(实例化,声明周期,后处理bean,属性注入).3.装配bean基于注解 1       spring框架概述 1.1   什么是spring l  Sp ...

  10. Solr7.1--- 单机Linux环境搭建

    应网友的要求,写个关于Linux单机的 首先,把MySQL驱动包和solr7.1安装包上传到服务器,我上传到了自定义的目录/mysoft 执行服务安装脚本 1. 先切换到root用户 2. 解压出脚本 ...