#### Go 面向对象之结构体
最近有四天没更新公众号,有一些事情耽误了,生活就是这样,总会一些事情让人措不及防;
***山浓水浅,坐看流年***

1. Go 也支持面向对象编程(OOP) 但是它和传统的面向对象编程还是有一些区别,并不是纯粹的面向对象编程;
2. Go 中没有类(class), Go 中struct 和其它编程语言中的类有同等地位,所以我们可以理解Go 是基于struct 来实现OOP;
3. Go 面向对象很简洁,没有传统OOP 的继承,方法重载,构造函数等等;
4. Go 面向对象仍有继承,封装,多态的特性,只是它的实现与传统的OOP语言不同;
##### 结构体与结构体变量(实例/对象)的关系图

 
---
说明:
1. 将一类事物的特性提取出来(比如猫类),形成一个新的数据类型就是一个结构体;
2. 通过这个结构体,可以创建多个变量(实例/对象);
3. 事物可以是猫类,也可以是其它的类...;
案例:
package main

import "fmt"

// 定义一个结构体,类似于类
// 将Cat 的各个字段/属性,放入到结构体中
type Cat struct {
Name string
Age uint
Color string
Hobby string
}
func main(){
// 声明一个Cat 变量,也就是实例
var a1 Cat
a1.Name = "小花"
a1.Age = 2
a1.Color = "black"
a1.Hobby = "老鼠"
fmt.Println(a1)
fmt.Printf("name=%s\n",a1.Name)
fmt.Printf("age=%d\n",a1.Age)
fmt.Printf("color=%s\n",a1.Color)
fmt.Printf("hobby=%s\n",a1.Hobby)
}

  


---
结构体与结构体变量(实例)的区别
1. 结构体是自定义的数据类型,代表一类事物;
2. 结构体变量是具体的,实际的,代表一个具体的变量;
---
##### 结构体变量在内存中的布局

  

##### 如何声明结构体
基本语法:
type 结构体名称 struct {
field1 type
field2 type
...
}
例如:
typt Person struct {
Name string
Age int
Class string
}
##### 字段属性
字段是结构体的组成部分,一般是基本数据类型,数组,同时也可以是引用类型;
注意事项:
1. 字段声明语法同变量一样: 字段名 字段类型
2. 在创建一个结构体变量后,如果没有给字段赋值,每个字段都对应一个默认值,引用类型默认值为nil;
3. 不同结构体变量的字段是独立的,互不影响: 结构体是值类型;
package main

import "fmt"

// 如果结构体里的字段是引用类型的: slice map channel;
// 在使用前需要make分配内存才能使用;
type Person struct {
Name string
Age int
Hobby [3]string
ptr *string
slice []int
Parents map[string]string
}
type Cat struct {
Name string
Age int
}
func main(){
var a1 Person
fmt.Println(a1) //{0 [] nil [] map[]}
if a1.ptr == nil {
fmt.Println("ptr is nil")
}
if a1.slice == nil {
fmt.Println("slice is nil")
}
if a1.Parents == nil {
fmt.Println("parents is nil")
}
// 结构体字段是引用类型的话,使用前需要make
a1.slice = make([]int,10)
a1.slice[0] = 1
a1.slice[1] = 2
a1.slice[2] = 3
a1.Parents = make(map[string]string)
a1.Parents["name"] = "aaaa"
a1.Parents["friendly"] = "father"
fmt.Println(a1) // { 0 [ ] <nil> [1 2 3 0 0 0 0 0 0 0] map[friendly:father name:aaaa]}
// 不同结构体变量间互不影响
var c1 Cat
var c2 Cat
c1.Name = "c1"
c2.Name = "c2"
c1.Age = 1
c2.Age = 2
fmt.Println(c1,c2) //{c1 1} {c2 2}
}

  


---
##### 创建结构变量和访问结构体字段
package main

import "fmt"

type Cat struct {
Name string
Age int
}
func main(){
// 方式1: 先声明,再赋值
var c1 Cat
c1.Name = "c1"
c1.Age = 1
fmt.Println(c1) //{c1 1}
// 方式2: 字面量方式
var c2 Cat = Cat{"c2",2}
fmt.Println(c2) //{c2 2}
// 方式3: 类型推导方式
c3 := Cat{"c3",3}
fmt.Println(c3) //{c3 3}
// 方式4: new 方式
var c4 *Cat = new(Cat)
c4.Name = "c4"
c4.Age = 4
fmt.Println(*c4)
// 方式5: &{} 方式
var c5 *Cat = &Cat{}
c5.Name = "c5"
c5.Age = 5
fmt.Println(*c5)
// 方式4,方式5 返回的都是结构体的指针类型
}

  


1. 第4,5 种方式返回的是***结构体指针***;
2. 结构体指针访问字段的标准方式应该是:(*结构体指针).字段名, 如:(*c4).Name = "c4";
3. Go 做了简化,支持***结构体指针.字段名***,如:c4.Name = "c4",Go 编译器底层自动处理了;
---
##### 结构体使用注意事项
1. 结构体中所有的字段在内存中是连续的;
2. 结构体是用户自定义的类型,在和其它类型转换时需要有完全相同的字段(名称,个数,类型);
3. 结构体进行type 定义,Go 认为是新的数据类型,可以和基本数据类型进行强转;
4. 结构体每个字段上可以写tag,tag 可以通过反射机制获取,常用的场景是序列化和反序列化;
package main

import (
"encoding/json"
"fmt"
) type Person struct {
Name string
Age int
Hobby string
}
type Student struct {
Name string
Age int
Hobby string
}
type Cat struct {
Name string `json:"name"`
Age int `json:"age"`
}
func main(){
var p1 Person
p1.Name = "p1"
p1.Age = 22
p1.Hobby = "run"
// 结构体变量的地址
fmt.Printf("p1 address: %p\n",&p1)
fmt.Printf("p1.Name address: %p\n",&p1.Name) // 0xc0000562d0
fmt.Printf("p1.Age address: %p\n",&p1.Age) // 0xc0000562e0 , 一个string 是16 字节
fmt.Printf("p1.Hobby address: %p\n",&p1.Hobby)//0xc0000562e8 , 一个int 在64 位系统中为8字节
// 类型之间强转
var s1 Student
s1 = Student(p1)
fmt.Println(s1)
fmt.Printf("s1 type is %T\n",s1) // Student
// struct tag
var c1 Cat
c1.Name = "小花"
c1.Age = 12
jsonStr,err := json.Marshal(c1)
if err != nil {
fmt.Println(err)
}
// 输出的是结构体中tag 定义的名称
fmt.Println(string(jsonStr)) // {"name":"小花","age":12}
}

  个人微信公众号上有最新内容,欢迎关注交流学习

最新文章

  1. WinForm跨窗体传值
  2. Apache多站点配置及启动失败解决办法
  3. PHP处理海量样本相似度聚类算法
  4. WCF中常用的binding方式
  5. POJ 1365 Prime Land(数论)
  6. app打包流程
  7. vi编辑器的三种模式
  8. CodeFirst 的编程方式
  9. Struts1.x下使用jquery的Ajax获取后台数据
  10. Java单例模式之饿汉模式与懒汉模式
  11. 处理范例代码Webapi中的Mongodb的Bson中ObjectId反序列化异常
  12. 【模板】Tarjan scc缩点
  13. 洛谷 P1010 幂次方
  14. v-on事件绑定指令
  15. 1、HA Cluster基础原理
  16. [BZOJ2616]SPOJ PERIODNI 树形dp+组合数+逆元
  17. ArcGIS 在高清屏中主界面界面字体和图标显示过小,如何解决?
  18. JavaScript的格式--从格式做起,做最严谨的工程师
  19. OpenSCManager
  20. shell学习1---基本的shell命令

热门文章

  1. Linux(centos)使用nc命令发送测试数据
  2. JAVAWEB项目处理XSS漏洞攻击处理方案
  3. 『与善仁』Appium基础 — 28、webview的操作方式
  4. 【LeetCode】978. Longest Turbulent Subarray 解题报告(C++)
  5. 【LeetCode】210. Course Schedule II 解题报告(Python)
  6. Spring MVC 文件上传、Restful、表单校验框架
  7. [数学]高数部分-Part IV 一元函数积分学
  8. 如何通过Navicat远程访问宝塔面板安装的MySQL数据库
  9. C# 服务器发送邮件失败
  10. ATA考试