go语言的学习----结构体与方法

本文详细介绍了Go语言中的结构体,包括结构体的字段、标签、方法、内存布局以及构造方法。强调了结构体在内存中的连续性,以及如何通过工厂方法创建私有结构体实例。此外,还探讨了匿名字段和内嵌结构体的使用,以及结构体方法的定义和调用规则。最后,提到了如何避免方法冲突和结构体变量的初始化方式。
摘要由CSDN通过智能技术生成

结构体

  • 结构体除了字段和类型之外, 还存在一个可选的标签(tag)。一般不会使用,但可以通过包 reflect 获取它
  • 任何类型都可以有方法,甚至可以是函数类型,不仅仅是结构体
  • String()相当于 java中的toString方法
type TagType struct { // tags
    field1 bool   "An important answer"
    field2 string "The name of the thing"
    field3 int    "How much there are"
}

t=new(T)var t T的区别
t=new(T) 变量t是一个指向T的指针
var t T 称为t是类型T的i个实例

在这里插入图片描述

结构体的内存布局
  • Go 语言中,结构体和它所包含的数据在内存中是以连续块的形式存在的,即使结构体中嵌套有其他的结构体,这在性能上带来了很大的优势。不像 Java 中的引用类型,一个对象和它里面包含的对象可能会在不同的内存空间中,这点和 Go 语言中的指针很像
    下面的例子清晰的说明了这个问题:
    在这里插入图片描述
结构体工厂创建实例(构造方法)
func NewFile(fd int, name string) *File {
    if fd < 0 {
        return nil
    }

    return &File{fd, name}
}
  • 如果File是一个结构体类型,那么表达式new(FIle)和&File{}是等价的
强制使用工厂方法
  • 将结构体名写成小写,工厂方法为大写,这样使得类型变为了私有的,从而只能通过工厂方法构造
package main
import "matrix"
...
wrong := new(matrix.matrix)     // 编译失败(matrix 是私有的)
right := matrix.NewMatrix(...)  // 实例化 matrix 的唯一方式
  • 使用make()一个结构体变量,会引起发一个编译错误
匿名字段和内嵌结构体
  • 结构体可以包含一个或多个匿名(内嵌)字段
  • 结构体可以包含内嵌结构体
  • 在Go语言中,相比较于继承,组合更受青睐
type innerS struct {
    in1 int
    in2 int
}

type outerS struct {
    b    int
    c    float32
    int  // anonymous field
    innerS //anonymous field
}

func main() {
    outer := new(outerS)
    outer.b = 6
    outer.c = 7.5
    outer.int = 60
    outer.in1 = 5
    outer.in2 = 10

    fmt.Printf("outer.b is: %d\n", outer.b)
    fmt.Printf("outer.c is: %f\n", outer.c)
    fmt.Printf("outer.int is: %d\n", outer.int)
    fmt.Printf("outer.in1 is: %d\n", outer.in1)
    fmt.Printf("outer.in2 is: %d\n", outer.in2)

    // 使用结构体字面量
    outer2 := outerS{6, 7.5, 60, innerS{5, 10}}
    fmt.Println("outer2 is:", outer2)
}
  • 当元素出现命名冲突:
    1.外层会覆盖内层的,但是俩者的内存都保留
    2.如果俩个命名相同且在同一级,调用时会出错
type A struct {a int}
type B struct {a, b int}

type C struct {A; B}
var c C
type D struct {B; b float32}
var d D
//使用c.a是会出错的,因为不知道是c.A.a还是c.B.a (写成c.A.a正确)
//d.b是外层的float32, d.B.b 则是B中的b
结构体的方法
  • 结构体代码和方法的代码可以不放在一起,但是必须在一个包内
  • golang是不允许方法重载的(为了语法简单,不出错),但是如果这俩个方法属于不同的结构体是允许的
func (recv receiver_type) methodName(parameter_list) (return_value_list) { ... }
// recv 是这个结构体的实例  也可以使用 this 和 self

不能给基本类型创建方法,且结构体的方法必须在本包(所以不能给系统包创建方法)
解决方法:

  1. 给该类型起别名,给该类型定义方法
  2. 将该类型内嵌到一个新的结构体中
    但是这个方法只在这个别名类型上有效
函数和方法的区别

函数将变量作为参数:Function1(recv)
方法在变量上被调用:recv.Method1()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值