Skip to content

golang中的struct

Struct是一个用户定义的类型,包含一系列的字段。它通常被作为一个整体组织相关的数据。相对java来说,就类似一个没有继承特性的贫血模型类。

定义struct

type User struct {
    name string
    age  string
    nationality string
}

初始化struct

初始化可以带字段名,可以不带字段名

func TestInit(t *testing.T) {
	u1 := User{}
	u2 := User{"Jack", 30, "Italy"}
	u3 := User{
		name:        "Mark",
		age:         30,
		nationality: "China",
	}
	t.Log(u1) // { 0 }
	t.Log(u2)
	t.Log(u3)
}

匿名struct

func TestAnonymousStruct(t *testing.T) {
	u1 := struct {
		name        string
		nationality string
		age         int
	}{
		name:        "Logan",
		nationality: "China",
		age:         35,
	}
	u2 := struct {
		name        string
		nationality string
		age         int
	}{
		"Logan",
		"China",
		35,
	}
	if u1 != u2 {
		t.Fail()
	} else {
		t.Log("u1 equals u2")
	}
}

嵌套struct

func TestNestedStruct(t *testing.T) {
	type FullName struct {
		first string
		last  string
	}
	type User struct {
		name        FullName
		nationality string
		age         int
	}
	p := User{
		name:        FullName{first: "Logan", last: "Wang"},
		nationality: "French",
		age:         34,
	}

	t.Log(p.name.first)
}

内嵌的结构体的字段可以被promoted

什么意思呢?就像上面的例子,p.name.first可以变成p.first,就像first直接就是User的字段一样。

func TestPromotedField(t *testing.T) {
	// 内嵌的匿名结构体的字段会被promoted,
	// 也就是说,它们可以在不引用内嵌的结构体的情况下访问
	type FullName struct {
		first string
		last  string
	}
	type User struct {
		FullName
		nationality string
		age         int
	}

	u := User{
		FullName: FullName{
			first: "Logan",
			last:  "Wang",
		},
		nationality: "French",
		age:         34,
	}
	t.Log(u.first)
}

struct可以有functions field

func TestFunctionField(t *testing.T) {
	type Age func() int

	type User struct {
		name        string
		nationality string
		birthday    time.Time
		age         Age // 函数字段
	}

	const TIME_LAYOUT = "2006-01-02 15:04:05"
	birth, err := time.Parse(TIME_LAYOUT, "2000-01-01 00:00:00")
	if err != nil {
		t.Fail()
	}
	u := User{
		name:        "Good",
		nationality: "Sweden",
		birthday:    birth,
		age: func() int {
			dur := time.Now().UTC().Sub(birth)
			return int(dur.Hours() / 24 / 365)
		},
	}

	ageInt := u.age()
	t.Log(ageInt)
}

指针

可以通过&操作符或者new关键字创建指向结构体的指针。

func TestStructPoint(t *testing.T) {
	u := User{"Jack", 30, "Italy"}
	// pointer to struct
	pointer_u := &u
	(*pointer_u).age = 40

	pointer_u.name = "New Name"
	t.Log(u)
	// use keyword new to create a pointer to struct
	u2 := new(User)
	u2.name = "Name2"
	u2.age = 20

	t.Log(u2)
}

// 使用构造函数
func TestWithConstruct(t *testing.T) {
	u := newUser("Richard Roe", "Singapore", 44)
	t.Log(u)
}

golang的结构体实际是个值类型

当将一个结构体赋值给一个变量的时候,实际上是分配了一个新的结构体,而不是分配了一个指针。比较两个结构体的时候,会逐层比较值,而不是引用。

func TestAssign(t *testing.T) {
	u := User{"Jack", 30, "Italy"}
	u2 := u
	u2.age = 40
	t.Log(u.age) // 30
	t.Log(u2.age) // 40
}

func TestEqual(t *testing.T) {
	type FullName struct {
		first string
		last  string
	}
	type User struct {
		FullName
		nationality string
		age         int
	}

	u := User{
		FullName: FullName{
			first: "Logan",
			last:  "Wang",
		},
		nationality: "French",
		age:         34,
	}
	u2 := User{
		FullName: FullName{
			first: "Logan",
			last:  "Wang",
		},
		nationality: "French",
		age:         34,
	}
	if u == u2 {
		t.Log("u == u2") // 会走到这里
	} else {
		t.Log("u != u2")
	}
}

Published ingolang

Be First to Comment

Leave a Reply

Your email address will not be published. Required fields are marked *