Golang入门教程(十四)结构体和类详解
golang中并没有明确的面向对象的说法,实在要扯上的话,可以将struct比作其它语言中的class。
类声明
type Book struct {
Title string
Author string
intro string
}
这样就声明了一个类,其中没有public、protected、private的的声明。golang用另外一种做法来实现属性的访问权限:属性的开头字母是大写的则在其它包中可以被访问,否则只能在本包中访问。类的声明和方法亦是如此。
类方法声明
// 类方法声明-传递值对象
func (b Book) B1() {
b.Title = "Book001"
b.Author = "ErWan"
} // 类方法声明-传递指针对象
func (b *Book) B2() {
b.Title = "Book002"
b.Author = "Tinywan"
}
和其它语言不一样,golang声明方法和普通方法一致,只是在func后增加了b Book这样的声明。加和没有加*的区别在于一个是传递指针对象(加*),一个是传递值对象。
传递指针和对象的区别
package main import "fmt" // 类声明
type Book struct {
Title string
Author string
DateTime string
} // 类方法声明-传递值对象
func (b Book) B1() {
b.Title = "Book001"
b.Author = "ErWan"
} // 类方法声明-传递指针对象
func (b *Book) B2() {
b.Title = "Book002"
b.Author = "Tinywan"
} func main() {
/*声明一个 Book 类型的变量 b ,并调用 B1() 和 B2()*/
b := Book{"Def-Book", "Def-Author", "Def-DateTime"} fmt.Println("B1 调用前:", b.Title, b.Author, b.DateTime)
b.B1()
fmt.Println("B1 调用后:", b.Title) fmt.Println("------------------\r\n")
fmt.Println("B2 调用前:", b.Title)
b.B2()
fmt.Println("B2 调用后:", b.Title) }
执行结果:
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的值,是这么定义的(为了修改内部结构的值。而不是传递一下)
func (this *InputController) InputGet(){
// Get 方式接受
name := this.GetString("name")
// 不使用模版,直接用 this.Ctx.WriteString 输出字符串
this.Ctx.WriteString(name)
}
值类型不可以改变值,而指针类型则是可以的
匿名结构体
p := struct {
Name string
Gender string
Age uint8
}{"Robert", "Male", 33}
匿名结构体最大的用处是在内部临时创建一个结构以封装数据,而不必正式为其声明相关规则。
实例化对象
实例化对象有好几种方式:
package main // 类声明
type Person struct {
Name string
Age int
Doc []string // slice切片
} // 类方法声明-传递值对象
func (p *Person) P1() {
p.Name = "Tinywan"
p.Age = 24
} // 类方法声明-传递指针对象
func (p *Person) P2() {
p.Name = "Tinyaiai"
p.Age = 22
} func main() { // 实例化对象 实例化的时候可以初始化属性值,如果没有指明则默认为系统默认值
p1 := &Person{}
p1.Name = "ShaoBo Wan"
p1.Age = 20 p2 := &Person{Name:"HaHa"} p3 := new(Person)
p3.Name = "New Name" p4 := Person{}
p4.Name = "Name 001"
p4.Age = 26 p5 := Person{Name:"Name 002",Age:28} // 使用中如果包含数组(动态数组 slice切片),结构体的实例化需要加上类型如上如果intro的类型是[]string
p6 := &Person{
"zhangsan",
25,
[]string{"lisi", "wangwu"},
}
}
注意,最后一个实例化
p6 := &Person{
"zhangsan",
25,
[]string{"lisi", "wangwu"},
}
小结:
1、使用中如果包含数组,结构体的实例化需要加上类型如上如果Doc的类型是[]string。
2、实例化的时候可以初始化属性值,如果没有指明则默认为系统默认值。
3、加&符号和new的是指针对象,没有的则是值对象,这点和php、java不一致,在传递对象的时候要根据实际情况来决定是要传递指针还是值。
4、当对象比较小的时候传递指针并不划算。
继承
确切的说golang中叫做组合(composition)
1、先初始化为空再赋值
// 先初始化为空再赋值
s1 := &Student{}
s1.schoole = "QiHua"
2、直接赋值
// 直接赋值
s2 := &Student{
Persons: Persons{
Name:"Tinywan",
Age:24,
Doc:[]string{"H1","h2"},
},
schoole:"BeiJin Schoole",
}
3、完整代码
package main import (
"fmt"
) // 类声明
type Persons struct {
Name string
Age int
Doc []string // slice切片
} // 获取Name
func (p *Persons) getName() {
fmt.Println("Name is ",p.Name)
} type Student struct {
// Student 属性中声明了 Persons,表示组合了Persons 的属性和方法(属性和方法都会被继承)
Persons
Name string
schoole string
} func main() { // 先初始化为空再赋值
s1 := &Student{}
// 当访问Name的时候默认为ProsePoem的 Name,如果需要访问Persons 的 Name 属性可以使用 s1.Persons.Name 来访问方法同理。
s1.Name = "Tinywan"
s1.Persons.Name = "Persons Name"
s1.schoole = "QiHua"
fmt.Println("s1 = ",s1)
fmt.Println("\r\n") // 直接赋值
s2 := &Student{
Persons: Persons{
Name:"Tinywan",
Age:24,
Doc:[]string{"s2-Doc","s2-Doc"},
},
Name:"ErWan",
schoole:"BeiJin-Schoole",
}
fmt.Println("s2 = ",s2)
}
方法的继承和属性一致
参考
1、https://segmentfault.com/a/1190000012325027
2、
Golang入门教程(十四)结构体和类详解的更多相关文章
- Golang入门教程(十三)延迟函数defer详解
前言 大家都知道go语言的defer功能很强大,对于资源管理非常方便,但是如果没用好,也会有陷阱哦.Go 语言中延迟函数 defer 充当着 try...catch 的重任,使用起来也非常简便,然而在 ...
- RabbitMQ入门教程(十四):RabbitMQ单机集群搭建
原文:RabbitMQ入门教程(十四):RabbitMQ单机集群搭建 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://b ...
- 无废话ExtJs 入门教程十四[文本编辑器:Editor]
无废话ExtJs 入门教程十四[文本编辑器:Editor] extjs技术交流,欢迎加群(201926085) ExtJs自带的编辑器没有图片上传的功能,大部分时候能够满足我们的需要. 但有时候这个功 ...
- “全栈2019”Java第九十四章:局部内部类详解
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...
- VS2010/MFC编程入门之三十八(状态栏的使用详解)
上一节中鸡啄米讲了工具栏的创建.停靠与使用,本节来讲解状态栏的知识. 状态栏简介 状态栏相信大家在很多窗口中都能见到,它总是用来显示各种状态.状态栏实际上也是一个窗口,一般分为几个窗格,每个窗格分别用 ...
- Linux C Socket编程发送结构体、文件详解及实例
利用Socket发送文件.结构体.数字等,是在Socket编程中经常需要用到的.由于Socket只能发送字符串,所以可以使用发送字符串的方式发送文件.结构体.数字等等. 本文:http://www.c ...
- C/C++结构体字节对齐详解
结构体的sizeof先看一个结构体:struct S1{ char c; int i;}; sizeof(S1)在VC6中按默认设置得到的结果为8.我们先看看sizeof的定义——size ...
- Golang入门教程(四)变量声明
Go 语言变量名由字母.数字.下划线组成,其中首个字母不能为数字. 一.Go的语言结构 1.Go的语言基础部分由这几个部分组成 包声明 引入包 函数 变量 语句&表达式 注释 比如下面这个简单 ...
- SpringBoot入门教程(十四)导出Excel
用JavaPOI导出Excel时,我们会考虑到Excel版本及数据量的问题.针对不同的Excel版本,要采用不同的工具类.HSSFWorkbook:是操作Excel2003以前(包括2003)的版本, ...
随机推荐
- 【BZOJ3132】【TYVJ1716】上帝造题的七分钟 二维树状数组
题目大意 维护一个\(n\times m\)的矩阵,有两种操作: \(1~x_1~y_1~x_2~y_2~v\):把\((a,b),(c,d)\)为顶点的矩形区域内的所有数字加上\(v\). \(2~ ...
- JeeSite4.x 搭建并部署到服务器
1.下载地址:https://gitee.com/thinkgem/jeesite4 2.文档地址:http://jeesite4.mydoc.io/?t=267354 2.1一定要看,都很清晰,没废 ...
- 自学Python4.2-装饰器
自学Python之路-Python基础+模块+面向对象自学Python之路-Python网络编程自学Python之路-Python并发编程+数据库+前端自学Python之路-django 自学Pyth ...
- 【BZOJ5339】[TJOI2018]教科书般的亵渎(斯特林数)
[BZOJ5339][TJOI2018]教科书般的亵渎(斯特林数) 题面 BZOJ 洛谷 题解 显然交亵渎的次数是\(m+1\). 那么这题的本质就是让你求\(\sum_{i=1}^n i^{m+1} ...
- 「浙大ACM」图森未来杯游记一篇以及简易口胡题解
前言 蒟蒻有参加了ACM比赛,这一次有适合HY和慕容宝宝大佬一起比的,他们好巨啊,把我带飞了. 又是窝掌机,QAQ,他们仗着自己巨,就欺负窝... 我又打了\(4\)个小时的代码,而且那个键盘太恶心了 ...
- BUG关闭原因
已解决:缺陷已经修复. 重复缺陷:是指在系统里相同原因的缺陷已经被其他人报告.在此缺陷被作为重复缺陷返回时,先不要立即取消.必须等到核查修复后,才在系统里取消.这是因为有些缺陷被误认为是重复缺陷,实际 ...
- table用模板生成的问题
在使用<template></template>存放HTML模板标记时,发现一个烦人的问题,表格不行. <template> <table> <t ...
- 生命不息,折腾不止 ~ 旧PC改造之家庭影音
前言引入 之前把在校园陪伴多年的旧电脑由Win装成了Linux,的确不卡了,基本上日常办公也够了(大项目还是吃不消,日常捣鼓倒是够了),然后把真正的工作游戏本也改成了Linux,那么旧电脑又变成闲置机 ...
- linux复制文件到一个不存在的文件夹
复制文件到一个不存在的文件夹时,会报错 cp -f aaa /home/admin/.m2/cp: 无法创建普通文件"/home/admin/.m2/": 是一个目录 解决的方式: ...
- 数位DP+其他
参考资料: [1]:数位dp总结 之 从入门到模板 [2]:浅谈数位DP 题目一览表 来源 考察知识点 A 4352 "XHXJ's LIS" hdu 数位DP+状压DP+LIS ...