原文:https://www.jianshu.com/p/b6ae3f85c683

---------------------------------------------------------------------------------------

1. 定义

结构体是将另个或者多个任意类型的命名变量组合在一起的聚合数据类型。

2. 成员变量

  • 访问控制机制
    如果一个结构体的成员变量名称是首字母大些的,那么这个变量是可导出的(即在其他包可以访问到)。
    一个结构体可以同时包含可导出和不可导出的成员变量
type A struct {
Hour int //可导出
minute int //不可导出
}
  • 限制
    命名结构体类型s不可以定义一个拥有相同结构体类型s的成员变量,也就是一个聚合类型不可以包含它自己。但是s中可以定义一个s的指针类型,即*s。如下:
type B struct {
value int
//Next B //错误
Next *B //正确
}

3. 结构体比较

  1. 如果结构体的所有成员变量都可以比较,那么这个结构体是可以比较的。两个结构体的比较可以使用==或者!=。
type C struct {
A int
B string
}
c1 := C{A:1, B:"abc"}
c2 := C{A:1, B:"abc"}
c3 := C{A:2, B:"abc"}
fmt.Println(c1.A == c2.A && c1.B == c2.B) //true
fmt.Println(c1 == c2) //true 与上等价
fmt.Println(c1.A == c3.A && c1.B == c3.B) //false
fmt.Println(c1 == c3) //false 与上等价

2.和其他可比较的类型一样,可比较的结构体类型都可以作为map的键类型。

type C struct {
A int
B string
}
mp := make(map[C]int)
key := C{A:1, B:"abc"}
mp[key] = 9
fmt.Println(mp[C{A:1, B:"abc"}]) //9

4. 结构体嵌套和匿名成员

  1. go允许我们定义不带名称的结构体成员,只需要指定类型即可;这种结构体成员称作匿名成员。这个结构体成员的类型必须是一个命名类型或者指向命名类型的指针。正是因为有了这种结构体嵌套的功能,我们才能直接访问到我们需要的变量而不是指定一大串中间变量。
type Point struct {
X int
Y int
}
type Circle struct {
Point
}
var c Circle
c.X = 10 //等价于 c.Point.X = 10
c.Y = 10 //等价于 c.Point.Y = 10 type Wheel struct {
*Point
}
  1. 结构体字面量初始化没有快捷方式,必须遵循形状类型的定义。
type Point struct {
X int
Y int
}
type Circle struct {
Point
}
var c Circle
c = Circle{1,1} //错误
c = Circle{Point{1,1}} //正确
c = Circle{Point: Point{1,1}} //正确

3.因为“匿名成员”拥有隐式的名字,所以你不能在一个结构体里面定义两个相同类型的匿名成员,否则会引起冲突。由于匿名成员的名字是由它们的类型决定的,因此它们的可导出性也是由他们的的类型决定。在下面的例子中,point和circle这两个匿名成员是可导出的,即使这两个结构体是不可导出的(point和circle)。

type point struct {
X int
Y int
}
type circle struct {
point
} type Wheel struct {
circle
}
var w Wheel
w.X = 8 // 等价于 w.circle.point.X = 8, w.X是可导出的,w.circle.point.X是不可导出的

5. 结构体方法

  1. 定义
    方法的声明和普通函数的声明类似,知识在函数名字前面多加了一个参数。这个参数把这个方法绑定到这个参数对应的类型上。
    附加的参数p成为方法的接收者, 它源于早先的面向对象语言,用来描述主调方法向对象发送消息。
type Point struct {
X int
Y int
}
func (p Point) print() {
fmt.Println(p.X, p.Y)
}
  1. 方法定义限制
    go和许多其他面向对象的语言不同,它可以将方法绑定到除了指针类型和接口类型的任何类型上。可以很方便的为简单的类型(入整形、字符串、slice、map、甚至函数等)定义附加的行为。
//整形
type III int
func (i III) print() {
fmt.Println(i)
} //函数
func Test() {
fmt.Println("test")
}
type FunT func()
func (f FunT) Print() {
fmt.Println(f)
}
func main() {
var f FunT
f = Test
f.Print()
}
  1. 指针接收者的方法
    由于主调函数会复制每一个实参变量,或者如果一个实参太大而我们希望避免复制整个实参,因此我们必须使用指针来传递变量的地址。这也同样适用于更新接收者我们将它绑定到指针类型。在调用方法的时候,编译器会对变量进行隐式转换。
    总结一下结构体方法可以成功调用的条件:
  • 实参接收者和形参接收者是同一类型,比如都是T或者都是*T。(1,4,5,7)
  • 实参接收者是T类型的变量而形参接收者是*T类型,编译器会隐式的获取变量的地址(3)。
  • 实参接收者是T类型而形参接收者是T类型,编译器会隐式的获取实际的取值。(2,6)
    其中8编译过程报错的原因是:编译器对T类型转化为
    T类型的隐式转化,只有实参接收者是变量才可以成功,因为无法获取临时变量的地址。
type Point struct {
X int
Y int
}
func (p Point) Print() {
fmt.Println(p.X, p.Y)
}
func (p *Point) ScaleBy(factor int) {
p.X *= factor
p.Y *= factor
}
func main() {
p := Point{1,1}
ptr := &p
p.Print() //1. 正确
ptr.Print() //2. 正确
p.ScaleBy(2) //3. 正确
ptr.ScaleBy(2) //4. 正确
Point{1,1}.Print() //5. 正确
(&Point{1,1}).Print() //6. 正确
(&Point{1,1}).ScaleBy( 2) //7. 正确
Point{1,1}.ScaleBy( 2) //8. 错误
}
  • nil是一个合法的接收者:就像一些函数允许nil指针作为实参,方法的接收者允许是nil指针
type A struct {
Data int
}
func (a *A) FunPtrA() {
fmt.Println("FunPtrA")
}
func main() {
var ptrA *A
ptrA = nil
ptrA.FunPtrA() //FunPtrA
}

4. 通过结构体内嵌组成类型
这里主要讨论内嵌结构体和结构体指针后,对于源结构体定义函数的访问权限。

type A struct {
Data int
}
func (a A) FunA() {
fmt.Println(a.Data)
}
func (a *A) FunPtrA1() {
fmt.Println("FunPtrA1")
}
func (a *A) FunPtrA2() {
fmt.Println("FunPtrA2")
fmt.Println(a.Data)
} type B struct {
A
}
type C struct {
*A
}
func main() {
var b B
b.FunA() //可以访问
b.FunPtrA1() //可以访问
b.FunPtrA2() //可以访问 var c C
//c.FunA() //不可访问
c.FunPtrA1() //可以访问
//c.FunPtrA2() //不可访问 c.A = &A{}
c.FunA() //可以访问
c.FunPtrA1() //可以访问
c.FunPtrA2() //可以访问
}

对于以上内容有疑问,欢迎留言讨论或者私信。转载请注明出处

作者:中电科苏云龙
链接:https://www.jianshu.com/p/b6ae3f85c683
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

【转】golang 结构体和方法的更多相关文章

  1. 六、golang中的结构体和方法、接口

    结构体: 1.用来自定义复杂数据结构 2.struct里面可以包含多个字段(属性) 3.struct类型可以定义方法,注意和函数的区分 4.strucr类型是值类型 5.struct类型可以嵌套 6. ...

  2. GO开发[五]:golang结构体struct

    Go结构体struct Go语言的结构体(struct)和其他语言的类(class)有同等的地位,但Go语言放弃了包括继承在内的大量面向对象特性,只保留了组合(composition)这个最基础的特性 ...

  3. golang结构体json格式化的时间格式

    golang结构体json格式化的时间格式 在我们开发中,经常会解析time.Time 往往前台传过来的时候,是个string 但是我们希望在结构体转成time.Time type Param str ...

  4. Golang结构体值的交换

    Golang结构体值的交换 一.添加结构体,多if暴力 最先遇到这个问题是在比编写PUT方法的接口时遇到. (我公司编写http put方法,是先解析json至StudentInput结构体中,通过i ...

  5. golang 结构体中的匿名接口

    golang 结构体中的匿名接口 代码示例 golang 中,可以给结构体增加匿名field,可参考 unknwon 大神的书. 匿名字段和内嵌结构体 但,golang同时也可以给结构体定义一个匿名i ...

  6. Go part 5 结构体,方法与接收器

    结构体 结构体定义 结构体的定义只是一种内存布局的描述(相当于是一个模板),只有当结构体实例化时,才会真正分配内存空间 结构体是一种复合的基本类型,通过关键字 type 定义为 自定义 类型后,使结构 ...

  7. go结构体的方法和普通函数

    package main import ( "fmt" "math" ) type vertex struct { X, Y float64 } //值接收者是 ...

  8. go 结构体与方法

    go 结构体与方法   go 结构体相当于 python 中类的概念,结构体用来定义复杂的数据结构,存储很多相同的字段属性 结构体的定义 1.结构体的定义以及简单实用 package main imp ...

  9. go结构体与方法

    go结构体相当于python中类的概念 结构体用来定义复杂的数据结构,存储很多相同的字段属性 1.结构体的定义以及简单实用 package main import ( "fmt" ...

随机推荐

  1. 最新 同程java校招面经 (含整理过的面试题大全)

    从6月到10月,经过4个月努力和坚持,自己有幸拿到了网易雷火.京东.去哪儿.同程等10家互联网公司的校招Offer,因为某些自身原因最终选择了同程.6.7月主要是做系统复习.项目复盘.LeetCode ...

  2. 异构平台mysql-oracle(ogg)安装部署

      如图所示:源端采用Mysql库,目标端采用Oracle库 一.OGG安装配置(源端) 1.OGG下载 https://edelivery.oracle.com/EPD/Download/get_f ...

  3. Neo4j

    Neo4j是一个高性能的,NOSQL图形数据库,它将结构化数据存储在网络上而不是表中.它是一个嵌入式的.基于磁盘的.具备完全的事务特性的Java持久化引擎,但是它将结构化数据存储在网络(从数学角度叫做 ...

  4. Linux 安装MySQL流程

    1. yum -y install wegt 2. yum -y install vim 3. 下载MySQL的repo源 1. wget http://repo.mysql.com/mysql-co ...

  5. 第十一章 ZYNQ-MIZ701 PS读写PL端BRAM

      本篇文章目的是使用Block Memory进行PS和PL的数据交互或者数据共享,通过zynq PS端的Master GP0端口向BRAM写数据,然后再通过PS端的Mater GP1把数据读出来,将 ...

  6. 怎样理解Cookie

    一. 什么是Cookie Cookie是服务器保存在浏览器里的一小段文本信息, 大小一般不超过4KB, 浏览器每次向服务器发起HTTP请求时就会自动附带上这段信息. 二. Cookie 的主要作用 1 ...

  7. C# WebForm 屏蔽输入框的验证

    按钮做界面跳转时,屏蔽输入框的验证可添加属性:  CausesValidation="FALSE" <form runat="server"> &l ...

  8. gperftools源码分析和项目应用 - CPU Profiler

    gperftools源码分析和项目应用 - CPU Profiler 原文:https://blog.csdn.net/yubo112002/article/details/81076821 原文链接 ...

  9. javabean转成json字符首字母大写

    今天写接口的时候有个需求将接口返回的json字符串首字母大写:{"SN":"","Result":""}格式, 只需要在 ...

  10. asp.net core 中hangfire面板的配置及使用

    1.定义校验授权类DyDashboardAuthorizationFilter /// <summary> /// Hangfire仪表盘配置授权 /// </summary> ...