GO入门——6. struct与方法

本文深入探讨了Go语言中的结构体(struct)特性,包括初始化、字段操作、方法(method)定义及调用等核心概念。文章详细解释了结构体的定义、初始化方式、字段访问与修改,以及通过指针传递实现的引用传递。同时,涵盖了Go中方法的定义与使用,包括接收者(receiver)的概念,值与指针调用的区别,以及方法的调用过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1 struct

  • Go 中的struct与C中的struct非常相似,并且Go没有class
  • 使用 type struct{} 定义结构,名称遵循可见性规则
  • 支持指向自身的指针类型成员
  • 支持匿名结构,可用作成员或定义成员变量
  • 匿名结构也可以用于map的值
  • 可以使用字面值对结构进行初始化
  • 允许直接通过指针来读写结构成员
  • 相同类型的成员可进行直接拷贝赋值
  • 支持 == 与 !=比较运算符,但不支持 > 或 <
  • 支持匿名字段,本质上是定义了以某个类型名为名称的字段
  • 嵌入结构作为匿名字段看起来像继承,但不是继承
  • 可以使用匿名字段指针

//声明结构类型
type Person struct {
    Name string
    Age  int
}

//包含匿名结构并作为内部成员变量
type FullPerson struct {
    Name    string
    Age     int
    Contact struct {
        Phone, City string
    }
}

//匿名字段名结构
type NoFiledName struct {
    string
    int
}

//嵌入结构
type in struct {
    A string
}
type out struct {
    in
    Name string
}

func funcStruct() {
    //初始化时可以使用p :=&Person{},实现初始化和获取指针
    //一般采用&Person{}这样做赋值
    per := Person{}
    fmt.Println(per) //{ 0},string默认空字符串,int默认0

    per.Age = 25 //通过.对字段操作

    //无构造函数,初始化可指定字段值
    //Person{"ppjj", 22},可以不写字段名那就必须全部按顺序赋值
    per = Person{
        Name: "pj",
        Age:  24, //结尾都需要逗号
    }
    fmt.Println(per) //{pj 24}

    //struct的函数传入是值传递
    A := func(p Person) {
        p.Age = 10
        fmt.Println(p) //{pj 10}
    }
    A(per)
    fmt.Println(per) //{pj 24},函数中执行的结果并不会修改per
    //使用指针实现对struct的引用传递
    B := func(p *Person) {
        p.Age = 20     //指针struct可以用.直接操作
        fmt.Println(p) //&{pj 20}
    }
    B(&per)
    fmt.Println(per) //{pj 20},函数中传入的是地址,因此此处值也修改了
    //匿名结构
    a := &struct {
        Name string
        Age  int
    }{
        Name: "pj",
        Age:  25,
    }
    fmt.Println(a) //&{pj 25}

    //包含匿名结构的成员变量
    fp := &FullPerson{}
    fmt.Println(fp) //&{ 0 { }}
    fp = &FullPerson{Name: "pj", Age: 25}
    fp.Contact.Phone = "187" //匿名结构成员变量只能通过这种方式进行初始化
    fp.Contact.City = "zz"
    fmt.Println(fp) //&{pj 25 {187 zz}}

    ////匿名字段名结构,初始化时必须按定义的顺序
    nfn := &NoFiledName{"pj", 12}
    fmt.Println(nfn) //&{pj 12}

    //嵌入结构
    o := &out{Name: "pj", in: in{A: "in"}}
    fmt.Println(o) //&{{in} pj}
    o.Name = "ppjj"
    o.A = "in1"
    fmt.Println(o) //&{{in1} ppjj}
    o.in.A = "in2"  
    //两种访问方式,如果两个结构有重名字段则被加入的将被隐藏,只能通过o.in.A这样访问
    fmt.Println(o) //&{{in2} ppjj}
}

2 方法

  • Go 中虽没有class,但依旧有method
  • 通过显示说明receiver来实现与某个类型的组合
  • 只能为同一个包中的类型定义方法
  • Receiver 可以是类型的值或者指针
  • 不存在方法重载
  • 可以使用值或指针来调用方法,编译器会自动完成转换
  • 从某种意义上来说,方法是函数的语法糖,因为receiver其实就是
    方法所接收的第1个参数(Method Value vs. Method Expression)
  • 如果外部结构和嵌入结构存在同名方法,则优先调用外部结构的方法
  • 类型别名不会拥有底层类型所附带的方法
  • 方法可以调用结构中的非公开字段
type AA struct {
    Name string
}
type BB struct {
    Name string
}

//接收者为AA,值传递
func (a AA) Print(name string) {
    a.Name = "ppjj"
    fmt.Println(a.Name + name)

}
//接收者为BB,引用传递
func (a *BB) Print(name string) {
    a.Name = "ppjj"
    fmt.Println(a.Name + name)

}
func funcMethod() {
    //值传递,不能修改字段
    a := AA{Name: "pj"}
    a.Print("test")
    fmt.Println(a)
    //引用传递,可以修改字段
    b := BB{Name: "pj"}
    b.Print("test")
    fmt.Println(b)
}

转载于:https://www.cnblogs.com/suolu/p/6715650.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值