Go(结构体)

五、结构体(struct)

5.1 定义

结构体是类型中带有成员的复合类型,结构体的定义格式:

type 类型名 struct{
    字段名1 字段名1 类型
    字段名2 字段名2 类型
    ...
}

type Point struct{
    X int
    Y int 
    //也可以写在一行
    X , Y int
}

type可以将各种基本类型定义为自定义类型,struct{} 标识结构体类型。

5.2 实例化

1.基本的实例化形式

var p Point
p.X = 10
p.Y = 20

2.创建指针类型的结构体

p := new(Point)
p.X = 10
p.Y = 20
//p的类型实际上为 *Point 属于指针,但是依然可以使用“.”调用内部成员变量。这是因为Go做了特殊处理,将 p.X 形式转换为 (*p).X

3.取结构体的地址实例化

p := &Point{}
p.X = 10
p.Y = 20

// 进行“&” 取地址操作相当于对该类型进行一次new的实例化操作。p的类型为*Point

5.3 初始换结构体的成员变量

1.使用键值对初始化,适用于成员变量多的。

p := &Point{
    X : 10
    Y : 20
}

2.使用多个值的列表初始化,适用于成员变量少的。

p := &Point{
    10
    20
}

3.初始化匿名结构体

p := &struct{ //定义
    X int
    y int
}{            //赋值
    10
    20
}

5.4 构造函数

Go语言没有构造函数,自行去创建类似构造函数特性的函数。

5.5 方法

方法是一种作用于特定类型变量的函数。这种特定类型变量叫做接收器(Receiver)。
接收器的类型可以是任何类型,不仅仅是结构体,任何类型都可以拥有方法。

面向过程实现方法 ,其实就是函数:

type Bag struct{ items []int}

//可以为任何类型添加方法
fucn Insert(b *Bag , itemid int){}

func main(){
    bag := new(Bag)
    Insert(bag , 1001)
}

结构体方法:

type Bag struct{ items []int}

//为结构体添加方法
fucn (b *Bag) Insert(itemid int){}

func main(){
    bag := new(Bag)
    bag.Insert(1001)
}

接收器--方法作用的目标

格式:
func (接收器变量 接收器类型) 方法名 (入参列表) (反参列表){函数体}
接收器类型和参数类似,可以是指针类型和非指针类型.
官方建议:接收器中参数变量的命名使用接收器类型的第一个小写字母。

指针类型接收器:
指针类型的接收器是一个结构体的指针组成,调用方法是修改接收器指针的任意成员变量,在方法结束后,修改都是有效的。

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 := new(Property)
    p.SetVlue(1)
    p.Value()
}

非指针类型接收器:
当方法作用于非指针类型接收器,Go语言在代码运行时将接收器的值复制一份。在非指针接收器的方法中可以获取接收器的成员值,但是修改无效。

type Point struct{
    X , Y int
}
//方法类不可以修改p的成员值
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{2,2}
    
    result := p1.Add(p2)
}

使用:
1.小对象由于值复制速度比较快,所以适用非指针类型接收器。
2.大对象因为复制性能较低,所以适合使用指针类型接收器。

为类型添加方法:
Go语言可以对任何类型添加方法,给一种类型添加方法就像给结构体添加方法一样,因为结构体也是这一种类型。

为基本类型添加方法:

//自定义类型
type MyInt int
//为自定义类型添加方法
func (m MyInt) IsZero() bool{}

http包中的类型方法:

package main

import (
    "net/http"
    "fmt"
    "os"
    "strings"
)

func main(){
    client := &http.Client{}
    //创建请求
    req , err := http.NewReuqest("POST","http://www.baidu.com",strings.NewReader("key=value"))
    
    if err != nil{
        os.Exit(1)
        return
    }
    //为表头添加信息
    req.Header.Add("User-Agent" , "myClient")
    //开始请求
    resp ,err := client.Do(req)
    
    if err != nil{
        os.Exit(1)
        return
    }
    //读取服务器返回内容
    data , err := ioutil.ReadAll(resp.Body)
    fmt.Println(string(Data))
    defer resp.Body.Close()
}

5.6 类型内嵌和结构体内嵌

结构体允许其成员字段在声明的时候没有字段名而只有字段类型,这种形式的字段叫类型内嵌或匿名字段。

type Data struct{
    int 
    float32
    bool
}
//一个结构体中同类型的匿名字段只能有一个
ins := &Data{
    int : 10
    float32 : 1.2
    bool : true
}

声明结构体内嵌

type BasicColor struct{
    R, G, B float32
}

type Color struct {
    //将结构体设置为另一个的成员
    Basic BasicColor
    //可省去成员名 写为: BasicColor
    Alpha float32
}

func main(){
    var c Color
    
    c.Basic.R = 1
    //对只有结构体类型类型的成员,可以直接使用其成员
    //c.R = 1   
    c.Alpha = 0
}

结构体内嵌特性:
1.内嵌的结构体可以直接访问其成员变量(c.R)
2.内嵌的结构体的字段名是它的类型名(c.BasicColor.R)

初始化结构体内嵌:

type Wheel struct{
    Size int
}

type Car struct{
    Wheel
}

func main(){
    c := Car{
        Wheel : Wheel{
            Size : 10
        }
    }
}

成员名字冲突:

type A struct {
    a int
}
type B struct {
    a int
}
type C struct {
    A
    B
}

func main(){
    c := C{
        A :A{
            10
        }
        
        B: B{
            10
        }
    }
    //正确使用
    c.A.a
    
    //错误使用,编译器会报错,提示有歧义
    c.a
}

所以建议,尽量不要直接调用结构体内嵌的成员,使用 c.A.a 这种格式比较稳妥。
将数据序列化为JSON:json.Marshal(raw)
JSON反序列化:json.Unmarshal(jsonData , &batteryAndToutch)

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,108评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,699评论 1 296
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,812评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,236评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,583评论 3 288
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,739评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,957评论 2 315
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,704评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,447评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,643评论 2 249
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,133评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,486评论 3 256
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,151评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,108评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,889评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,782评论 2 277
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,681评论 2 272

推荐阅读更多精彩内容

  • 大家好,我是谢伟,是一名程序员。 本专栏的主旨是:梳理 Golang 知识,力求从初级水平提升至中级水平。 同时将...
    谢小路阅读 2,315评论 0 18
  • 简单来讲,Go提供的结构体就是把使用各种数据类型定义的不同变量组合起来的高级数据类型。看例子: 上面我们定义了一个...
    我们都很努力着阅读 1,323评论 0 4
  • 我们花了两年学会说话,却要花上六十年来学会闭嘴。 by 佚名 引用于:http://wufazhuce.com/o...
    喜龙爱慧阅读 5,962评论 0 3
  • 进口橘粉玫瑰20支 蓝色绣球3支 真滇果一扎 黑色观赏彩椒四支 进口红千尘3—4支(大)它的叶材可以做填充冬青或火...
    南湘子阅读 208评论 0 0
  • 泰戈尔说 天空没有翅膀的痕迹 而我已经飞过 天空没有飞过的痕迹 而我心里装着整个天空 飞越天际的旅行 留心欣赏悠然...
    唯悸动阅读 195评论 0 1