原文: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. 【计算机视觉】深度相机(四)--Realsense概览

    本文参考下文,做一点个人使用补充. http://blog.csdn.net/app_12062011/article/details/52662143 转自: http://blog.csdn. ...

  2. Zookeeper概述、特点、数据模型

    Zookeeper 1.Zookeeper概述 Zookeeper是一个工具,可以实现集群中的分布式协调服务. 所谓的分布式协调服务,就是在集群的节点中进行可靠的消息传递,来协调集群的工作.   Zo ...

  3. 数字麦克风PDM信号采集与STM32 I2S接口应用--笔记目录

    数字麦克风采用MEMS技术,将声波信号转换为数字采样信号,由单芯片实现采样量化编码,一般而言数字麦克风的输出有PDM麦克风和PCM麦克风,由于PDM麦克风结构.工艺简单而大量应用,在使用中要注意这二者 ...

  4. [转帖]龙芯服务器部署WEB服务的体验和详细步骤

    龙芯服务器部署WEB服务的体验和详细步骤 2019年01月02日 18:40:34 weixin_40065369 阅读数 1733   版权声明:本文为博主原创文章,遵循CC 4.0 by-sa版权 ...

  5. Java操作Excle(基于Poi)

    有一次有个同事问我会不会有java操作Excle,回答当然是不会了!感觉被嘲讽了,于是开始寻找度娘,找到个小例子,结果越写越有意思,最后就成就了这个工具类. import java.io.Buffer ...

  6. Windows Eclipse Scala的入门HelloWorld

    [学习笔记] Windows Eclipse Scala的入门HelloWorld 有关带scala版本的eclipse4.7的下载, 你可以直接去: http://scala-ide.org/dow ...

  7. Pebbles HDU 2167

    Pebbles HDU 2167 大意:给定一个N*N的方格,让你在里面取出一些数使其和最大,要求每一个数不能与其相邻的8个数同时取出. 思路:和炮兵阵地那一题有点像,但我们只需要考虑上一行的情况,这 ...

  8. Numbers(CodeForces-128D)【思维/list】

    题目链接:https://vjudge.net/problem/CodeForces-128D 题意:给出一组数,要求将这些数排列成一个环,满足每相邻两个数的差值为1,问能否完成. 思路:先取出最小的 ...

  9. python--关于正则表达式的学习小结

    python中提供了re这个模块提供对正则表达式的支持. 一.正则表达式常用到的一些语法(并非全部): . 匹配任意单个字符 [...] 匹配单个字符集 \w 匹配单词字符,即[a-zA-Z0-9] ...

  10. golang数据基本数据类型和string类型的转换

    基本类型之间的转换 golang在不同类型的变量之间赋值时需要显式转换,也就是说golang中数据类型不能自动转换. 表达式T(v)将值v转换为类型T 1.数据类型的转换可以是从范围小——>范围 ...