go 基础 结构体
结构体是类型中带有成员的复合类型。go语言使用结构体和结构体成员来描述真实世界的实体和实体对应的各种属性。
go语言中的类型可以被实例化,使用new和&构造类型实例的类型是类型的指针。
结构体成员是由一系列成员变量构成,成员(字段)有以下属性:
- 字段名称唯一;
- 拥有类型和值;
- 成员的类型可以是结构体,甚至是字段所在结构体的类型。
go不支持”类“的概念,也不支持"继承"面向对象的概念。
go 语言不仅认为结构体能拥有方法,且每种自定义类型也可以有自己的方法。
在函数外部定义结构体,作用域是全局的。
结构体基础
定义结构体
type 结构体名称 struct {
字段名 字段类型
...
}
- 结构体类型名在包内不能重复
示例,表示直角坐标系中的点的坐标
type Point struct {
X int
Y int
}
实例化结构体--为结构体分配内存并初始化
结构体定义只是一种内存布局的描述,只有结构化后才能真正分配内存。
基本的实例化形式
示例,表示直角坐标系中的点的坐标
type Point struct {
X int
Y int
}
var p Point
p.x = 10
p.y = 20
创建指针类型的结构体
使用new关键字对类型进行实例化,会形成指针类型的结构体。
type Player struct {
Name string
HealthPoint int
MagicPoint int
}
tank := new(Player)
tank.name = "Canon"
tank.HealthPoint = 300
go 语言中访问成员变量可以继续使用”.“,go增加了语法糖,将
ins.Name转化为(*ins).Name。
取结构体地址实例化
对结构体进行&取地址,视为对该类型进行一次new实例化操作。
ins := &T{}
- T表示结构体类型
- Ins 为结构体实例,类型是
*T
示例,定义一个命令行指令,指令包含名臣,关联变量和注释
type Command struct {
Name string
Var *int // 此处使用指针,可以随时与绑定的值保持同步
Comment string
}
var version int = 1
cmd := &Command{}
cmd.Name = "version"
cmd.Var = &version
cmd.Comment = "show version"
初始化结构体成员变量
使用基本形式初始化结构体
示例,颜色的RGB值
type Color struct {
R, G, B byte
}
使用键值对初始化结构体
示例,描述家庭任务关联
type People struct {
name string
child *People
}
relationship := &People{
name: "grand father",
child: &People{
name: "Dad",
child: &People{
name: "I",
},
},
}
fmt.Println(relationship.child.child.name)
使用多个值列表初始化结构体
注意
- 必须初始化结构体的所有字段
- 初始值与字段顺序保持一致
- 键值对与值列表的形式不能混用
示例,地址
type Address struct {
Privince string
City string
ZipCode int
PhoneNumber string
}
addr := Address{
"上海",
"上海",
"222300",
"0"
}
构造函数--结构体初始化的函数封装
go语言或者结构体没有构造函数的功能,结构体的初始化的过程可以用函数封装实现。
模拟构造函数重载
示例,根据颜色和名称可以构造不同猫的实例。
type Cat struct {
Name string
COlor string
}
func NewCatByName(name string) *Cat {
return &Cat{
Name: name,
}
}
func NewCatByColor(color string) *Cat {
return &Cat{
Color: color,
}
}
模拟父级构造调用
示例,黑猫是一种猫,猫是黑猫的泛称。
package main
import "fmt"
type Cat struct {
Name string
Color string
}
type BlackCat struct {
Cat // 嵌入Cat,类似于派生
}
func NewCat(name string) *Cat {
return &Cat{
Name: name,
}
}
func NewBlackCat(name string) *BlackCat {
cat := &BlackCat{}
cat.Color = "black"
cat.Name = name
return cat
}
func main() {
cat := NewCat("wow")
fmt.Println(cat)
blackcat := NewBlackCat("hello")
fmt.Println(blackcat)
}
方法
使用背包作为"对象",将物品放入背包的过程称为”方法“。
面向过程的实现方法
面向过程中没有“方法”概念,只能通过结构体和函数,由使用者用函数参数和调用关系来形成接近”方法“的概念。
package main
import "fmt"
type Bag struct {
items []int
}
func Insert(b *Bag, itemid int) {
b.items = append(b.items, itemid)
}
func main() {
bag := &Bag{}
Insert(bag, 100)
fmt.Println(bag.items)
}
Go 语言结构体方法
将背包及放入背包物品中使用go语言的结构体和方法方式编写,为 *Bag创建一个方法。
package main
import "fmt"
type Bag struct {
items []int
}
func (b *Bag) Insert(itemid int) {
b.items = append(b.items, itemid)
}
func main() {
bag := &Bag{}
bag.Insert(100)
fmt.Println(bag.items)
}
Insert(itemid int)的写法与函数一致,(b *Bag)表示接收器,即Insert作用的对象实例。每个方法只能有一个接收器。
接收器--方法作用的目标

func (接收器变量 接收器类型) 方法名(参数列表) (返回参数) {}
指针和非指针接收器的使用
在计算机中,小对象由于值复制时的速度较快,适合使用非针接收器。大对象因为复制性能较低,适合使用指针接收器,在接收器和参数间传递 不进行复制, 只是传指针。
指针类型接收器
指针类型接收器由一个结构体指针组成,更接近于面向对象中的this和self。
由于指针的特性,调用方法时,修改接收器成员变量,在方法结束后是有效的。
package main
import "fmt"
type Property struct {
value int
}
func (p *Property) SetValue(value int) {
p.value = value
}
func (p *Property) Value() int {
return p.value
}
func main() {
p := &Property{}
p.SetValue(1)
fmt.Println(p.Value())
}
非指针类型接收器
当方法作用于非指针接收器时,go语言会在代码运行时将接收器的值复制一份。在非指针接收器的方法中可以获取接收器的成员值,但修改后无效。
package main
import "fmt"
type Point struct {
X int
Y int
}
func (p Point) Add(other Point) Point {
return Point{p.X+other.X, p.Y+other.Y}
}
func main() {
p1 := Point{1, 1}
p2 := Point{3, 4}
fmt.Println(p1.Add(p2))
}
示例,time时间的中的Second属性是 Duration,Duration拥有String()方法。
package main
import (
"fmt"
"time"
)
func main() {
fmt.Println(time.Second.String())
}
//const (
// Nanosecond Duration = 1
// Microsecond = 1000 * Nanosecond
// Millisecond = 1000 * Microsecond
// Second = 1000 * Millisecond
// Minute = 60 * Second
// Hour = 60 * Minute
//)
//
//func (d Duration) String() string {
// ...
// return string(buf[w:])
结构体内嵌
结构体允许其成员字段在声明时没有宇段名而只有类型,这种形式的字段被称为类型内嵌。
type Data struct {
int
float32
bool
}
ins : = &Data{
int: 1 0,
float32 : 3 .14,
bool: true
}
结构体类型内嵌比普通类型内嵌的概念复杂 ,下面通过一个实例来理解。
package main
import "fmt"
type BasicColor struct {
R, G, B float32
}
type Color struct {
Basic BasicColor
Alpha float32
}
func main() {
var color Color
color.Basic.R = 1
color.Basic.G = 1
color.Basic.B = 0
color.Alpha = 1
fmt.Printf("%+v", color)
}
将 BasicColor 结构体嵌入Color 结构体中, BasicColor 没有宇段名而只有类型,这种写法就叫做结构体内嵌。
package main
import "fmt"
type BasicColor struct {
R, G, B float32
}
type Color struct {
BasicColor
Alpha float32
}
func main() {
var color Color
color.R = 1
color.G = 1
color.B = 0
color.Alpha = 1
fmt.Printf("%+v", color)
}
初始化结构体内嵌
package main
import "fmt"
type Wheel struct {
Size int
}
type Engine struct {
Power int
Type string
}
type Car struct {
Wheel
Engine
}
func main() {
car := Car{
Wheel: Wheel{
Size: 10,
},
Engine: Engine{
Power: 10,
Type: "Dz",
},
}
fmt.Printf("%+v", car)
}
使用匿名结构体分离json数据
package main
import (
"encoding/json"
"fmt"
)
// 定义屏幕
type Screen struct {
Size float32 // 屏幕尺寸
ResX, ResY int //屏幕水平和垂直分辨率
}
// 定义电池
type Battery struct {
Capacity int // 容量
}
func genJsonData () []byte {
raw := &struct {
Screen
Battery
HasTouchID bool
}{
Screen: Screen{
Size: 5.5,
ResX: 1920,
ResY: 1080,
},
Battery: Battery{
Capacity: 100,
},
HasTouchID: true,
}
jsonData, err := json.Marshal(raw)
if err != nil {
return make([]byte, 0)
} else {
return jsonData
}
}
func main() {
// 生成一段 JSON 数据
jsonData := genJsonData()
fmt.Println(string(jsonData))
// 只需要屏幕和指纹识别信息的结构和实例
screenAndTouch := struct {
Screen
HasTouchID bool
}{}
// 反序列化到 screenAndTouch
err := json.Unmarshal(jsonData, &screenAndTouch)
if err == nil {
fmt.Printf("%+v\n", screenAndTouch)
}
// 只需要电池和指纹识别信息的结构和实例
batteryAndTouch := struct {
Battery
HasTouchID bool
}{}
err = json.Unmarshal(jsonData, &batteryAndTouch)
if err == nil {
fmt.Printf("%+v\n", &batteryAndTouch)
}
}
go 基础 结构体的更多相关文章
- C#语言基础——结构体和枚举类型
结构体和枚举类型 一.结构体(struct) 结构类型是用户自己定义的一种类型,它是由其他类型组合而成的,可包含构造函数.常数.字段.方法.属性.索引器.运算符.事件和嵌套类型的值类型.结构在几个重要 ...
- C#基础——结构体
集合:数组:同一类型,固定长度集合:不同类型,不固定长度 要使用集合,必须先引用命名空间:using System.Collections; 定义:ArrayList arr = new ArrayL ...
- OC基础--结构体 枚举做类成员属性
结构体 枚举作类的成员属性: 定义一个学生类 性别 -- 枚举 生日 入学日期 毕业日期 -- 结构体 代码示例: 声明文件 Student.h: #import <Foundation ...
- C基础--结构体
C语言,结构体语法: 1.定义结构体类型: struct 结构体名称 { 成员类型 成员名称1; 成员类型 成员名称2; ... }; 例:struct Date { int year ; int m ...
- C基础--结构体成员初始化方式
之前在linux内核代码中看到结构体成员成员初始化使用类似于.owner = THIS_MODULE, 不太见过,于是搜了个博客,分享下: 转自:http://www.cnblogs.com/Anke ...
- C语言基础--结构体对齐,位域,联合体
结构体对齐 1--结构体对齐的原因与意义 许多计算机系统对基本数据类型的可允许地址做出了一些限制,要求某种类型的对象的地址必须是某个值K(通常是2,4,8)的倍数,而这个k则被称为该数据类型的对齐模数 ...
- 2017-3-2 C#基础 结构体
1. 结构体:用户自定义类型定义位置:定义在Main函数的外面,类的里面 定义格式:struct 自定义名字{ public 数据类型 名字; public 数据类型 名字; ... ...} 声明实 ...
- 数据结构基础——结构体struct及类型别名typedef的使用
一.结构体的创建 在C语言中,实现数据结构的一种常用方法便是使用结构体(structure)其示例代码如下: struct stu { int num; char ch; }; struct表示创建结 ...
- C语言基础:结构体 分类: iOS学习 c语言基础 2015-06-10 21:47 28人阅读 评论(0) 收藏
结构体:是一种用户自定义的数据类型 结构体定义 struct 结构体名 { 成员类型1 成员变量名1; 成员类型2 成员变量名2; -. }; typedef 原类型 ...
随机推荐
- OpenCV-Python 轮廓:入门 | 二十一
目标 了解轮廓是什么. 学习查找轮廓,绘制轮廓等. 你将看到以下功能:cv.findContours(),cv.drawContours() 什么是轮廓? 轮廓可以简单地解释为连接具有相同颜色或强度的 ...
- 深度学习vs机器学习 | 这些本质区别你知道多少?
目录: 数据相关性 硬件依赖性 特征工程 解决问题方法 执行时间 可解释性 一.数据相关性 深度学习与传统机器学习最重要的区别是,随着数据量的增加,其性能也随之提高.当数据很小的时候,深度学习算法并不 ...
- jQuery操作DOM的相关方法
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8 ...
- coding++:RateLimiter 限流算法之漏桶算法、令牌桶算法--简介
RateLimiter是Guava的concurrent包下的一个用于限制访问频率的类 <dependency> <groupId>com.google.guava</g ...
- iOS 重构AppDelegate
一.Massive AppDelegate AppDelegate 是应用程序的根对象,它连接应用程序和系统,确保应用程序与系统以及其他应用程序正确的交互,通常被认为是每个 iOS 项目的核心. 随着 ...
- 面试官:ThreadLocal的应用场景和注意事项有哪些?
前言 ThreadLocal主要有如下2个作用 保证线程安全 在线程级别传递变量 保证线程安全 最近一个小伙伴把项目中封装的日期工具类用在多线程环境下居然出了问题,来看看怎么回事吧 日期转换的一个工具 ...
- P1345 [USACO5.4]奶牛的电信(点拆边 + 网络最小割)
题目描述 农夫约翰的奶牛们喜欢通过电邮保持联系,于是她们建立了一个奶牛电脑网络,以便互相交流.这些机器用如下的方式发送电邮:如果存在一个由c台电脑组成的序列a1,a2,-,a©,且a1与a2相连,a2 ...
- SQL Server 存储过程分页。
create proc proc_Product@page int, -- 页数@row int -- 一页有几行Asdeclare @newpage int set @newpage = (@ ...
- 浅谈RPC与Http
什么是RPC,RPC原理是什么? 什么是RPC? RPC(Remote Procedure Call)远程过程调用,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议.比如两个 ...
- SpringMVC(五):JSON
本文是按照狂神说的教学视频学习的笔记,强力推荐,教学深入浅出一遍就懂!b站搜索狂神说或点击下面链接 https://space.bilibili.com/95256449?spm_id_from=33 ...