定义

结构体定义

// 声明结构体
type Vertex struct {
    // 结构体的属性,同样遵循大写导出,小写私有的原则
    X, Y int
    z bool
}

// 也可以声明匿名/隐式结构体
point := struct {
	X, Y int
}{1, 2}

// 声明空指针
var v *Vertex = new(Vertex)

// 显式声明键
var v = Vertex{X: 1, Y: 2}

// 声明数组
var v = []Vertex{{1,2},{5,2},{5,5}}

// 创建结构体实例
var v = Vertex{1, 2}

// 读取或者设置属性
v.X = 4;

方法的声明也非常简洁,只需要在 func 关键字与函数名之间声明结构体指针即可,该结构体会在不同的方法间进行复制:

func (v Vertex) Abs() float64 {
    return math.Sqrt(v.X*v.X + v.Y*v.Y)
}

// Call method
v.Abs()

对于那些需要修改当前结构体对象的方法,则需要传入指针:

func (v *Vertex) add(n float64) {
    v.X += n
    v.Y += n
}

结构体默认值

//Something is the structure we work with
type Something struct {
     Text string
     DefaultText string
}

// NewSomething create new instance of Something
func NewSomething(text string) Something {
   something := Something{}
   something.Text = text
   something.DefaultText = "default text"
   return something
}

结构体标签

结构体的字段除了名字和类型外,还可以有一个可选的标签(tag):它是一个附属于字段的字符串,可以是文档或其他的重要标记。比如在我们解析 json 或生成 json 文件时,常用到 encoding/json 包,它提供一些默认标签,例如:omitempty 标签可以在序列化的时候忽略 0 值或者空值。而 - 标签的作用是不进行序列化,其效果和和直接将结构体中的字段写成小写的效果一样。

type Info struct {
    Name string
    Age  int `json:"age,omitempty"`
    Sex  string
}

在序列化和反序列化的时候,也支持类型转化等操作:

type Info struct {
	Name string
	// 这样生成的json对象中,age就为字符串
    Age  int   `json:"age,string"`
    Sex  string
}

在 Go 中,我们可以使用 reflect 包来获取自定义的字段信息:

package main

import (
    "fmt"
    "reflect"
)

const tagName = "Testing"

type Info struct {
    Name string `Testing:"-"`
    Age  int    `Testing:"age,min=17,max=60"`
    Sex  string `Testing:"sex,required"`
}

func main() {
    info := Info{
        Name: "benben",
        Age:  23,
        Sex:  "male",
    }

    // 通过反射,我们获取变量的动态类型
    t := reflect.TypeOf(info)
    fmt.Println("Type:", t.Name())
    fmt.Println("Kind:", t.Kind())

    for i := 0; i < t.NumField(); i++ {
        field := t.Field(i) // 获取结构体的每一个字段
        tag := field.Tag.Get(tagName)
        fmt.Printf("%d. %v (%v), tag: '%v'\n", i+1, field.Name, field.Type.Name(), tag)
    }
}

结构体的内存布局

Go 语言中,结构体和它所包含的数据在内存中是以连续块的形式存在的,即使结构体中嵌套有其他的结构体,这在性能上带来了很大的优势。不像 Java 中的引用类型,一个对象和它里面包含的对象可能会在不同的内存空间中,这点和 Go 语言中的指针很像。下面的例子清晰地说明了这些情况:

type Rect1 struct {Min, Max Point }
type Rect2 struct {Min, Max *Point }

结构体的内存布局

下一页