当前位置:   article > 正文

Struct in Go_structfield.anonymous

structfield.anonymous

Struct

struct 是一种聚合数据类型,将 0 个或多个任意类型的命名值组合成一个单个实体。其中的每个值都称为 field

type Empoloyee struct {
	ID 			int
	Name 		string
	Address 	string
	DoB 		time.Time
	Position 	string
	Salary 		int
	ManagerID 	int
}
var dilbert Employee
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

field 的顺序对于 struct 来说是有意义的,不同的 field 顺序表示不同的 struct 类型。
struct 通常出现在命名类型,比如 Empoloyee,的声明中。

命名结构体类型 S 不能声明一个 S 类型的 field:一个聚合值不能包含它自己。但是 S 可以声明一个类型为 S* 的指针类型 field。

type tree struct {
	value int
	left, right *tree
}

// Sort sorts values in place
func Sort(values []int) {
	var root *tree
	for _, v := range values {
		root = add(root, v)
	}
	appendValues(values[:0], root)
}
// appendValues appends the elements of t to values in order
// and returns the resulting slice
func appendValues(values []int, t *tree) []int {
	if t != nil {
		values = appendValues(values, t.left)
		values = append(values, t.value)
		valuse = appendValues(values, t.right)
	}
	return values
}

func add(t *tree, value int) *tree {
	if t == nil {
		// Equivalent to return &tree{value: value}.
		t = new(tree)
		t.value = value
		return t
	}
	if value < t.value {
		t.left = add(t.left, value)
	}
	else {
		t.right = add(t.right, value)
	}
	return t
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

stuct 的 zero value 是各 field 的 zero value 的组合。

Construct/destruct

struct 类型的值可以由 struct literal 进行写值,struct literal 有两种格式:
第一种格式如下,需要指定按顺序各个 field 的值,结构体定义一旦修改,就必须对应修改。

type Point struct { X, Y int }
p := Point{1, 2} // struct literal
  • 1
  • 2

第二种格式列出 field names 和其对应的值的列表,如下所示:

anim := gif.GIF{LoopCount: nframes}
  • 1

未列出的 field names 使用缺省值(zero value)。

不能被其他 package 访问的 field 不能在其他 package 中进行写值:

package p
type T struct{a, b int} // a and b are not exported
  • 1
  • 2
package q
import "p"

var _ = p.T{a: 1, b: 2}	// compile error: can't reference a, b
var _ = p.T{1, 2}		// complie error: can't reference a, b
  • 1
  • 2
  • 3
  • 4
  • 5

直接构造结构体的指针:

pp := &Point{1, 2}
  • 1

等价于:

pp := new(Point)
*pp = Point{1, 2}
  • 1
  • 2

Member access

使用 dot 符号访问成员:

dilbert.Salary -= 5000
  • 1

或者进行取址通过指针进行访问:

position := &dilbert.Position
*position = "Senior" + *position
  • 1
  • 2

dot 符号对结构体指针依然有效:

var employeeOfTheMonth *Employee = &dilbert
employeeOfTheMonth.Position += "  (proactive team player)"
  • 1
  • 2

最后一句等价于

(*employeeOfTheMonth).Position += "  (proactive team player)"
  • 1

可以将相同类型的连续字段写成一行:

type Emloyee struct {
	ID 				int
	Name, Address 	string
	DoB 			time.Time
	Position 		string
	Salary 			int
	ManagerID 		int
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

首字母大写的 struct field 是可以被外部访问的,小写则不能被外部访问。

type Point {
	X, Y int
}

type Circle struct {
	Point
	Radius int
}

type Wheel struct {
	Circle 
	Spokes int
}
w := Wheel{Circle{Point{8, 8}, 5}, 20}

w := Wheel{
	Circle: Circle{
		Point: Point{X: 8, Y: 8},
		Radius: 5,
	},
	Spokes: 20,	// NOTE: trailing comma neccessary here (and at Radius)
}
fmt.Printf("%#v\n", w)
// Output:
// Wheel{Circle:Circle{Point:Point{X:42, Y:8}, Radius:5}, Spokes:20}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

# 副词使值按类似于 Go 语法的格式输出

Compare

如果 struct 中的所有 field 都是能够进行比较的,那么该 struct 就是能够进行比较的。我们使用 == 和 != 进行该 struct 类型的值或者表达式之间的比较:

type Point struct { X, Y int }
p := Point{1, 2}
q := Point{2, 1}
fmt.Println(p.X == q.X && p.Y == q.Y) 	// "false"
fmt.Println(p == q)						// "false"	
  • 1
  • 2
  • 3
  • 4
  • 5

可比较的 struct 类型可以用作 map 的 key:

type address struct {
	hostname string
	port int
}

hits := make(map[address]int)
hits[address{"golang.org", 443}]++
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

Struct Embedding and Anonymous Fields

Go 使用 struct embedding 机制使一个命名 struct 类型作为另一 struct 类型的 anonymous field,使得简单的 dot 表达式比如 x.f,可以表示 x.d.e.f。

type Point {
	X, Y int
}

type Circle struct {
	Center Point
	Radius int
}

type Wheel struct {
	Circle Circle 
	Spokes int
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

这样访问 Wheel 的 field 可能十分冗长,比如 Wheel{}.Circle.Center.X。
Go 允许我们声名一个 field 的 type 但不声名 name,这被称为 anonymous fields。field 的类型必须是一个命名类型或者是指向命名类型的指针。

type Circle struct {
	Point
	Radius int
}

type Wheel struct {
	Circle
	Spokes int
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

其使用方法如下:

var w Wheel
w.X = 8			// equivalent w.Circle.Point.X
w.Y = 8			// equivalent w.Circle.Point.Y
w.Radius = 5	// equivalent  w.Circle.Radius
w.Spokes = 20
  • 1
  • 2
  • 3
  • 4
  • 5

事实上,anonymous field 的名字是隐式声名的,它的名字就是它的命名类型名,这些名字在 dot 表达式中是可选的,可以显式使用,也可以不显式不使用。Circle 和 Point 都是首字母大写的,显然它们可以在声明它们的 package 之外被访问,但是如果是 circle 和 point 呢?在声明的 package 外,我们依然可以用 w.X = 8 进行访问,但是显式的使用 field name,w.circle.point.X,就不行了,因为 circle 和 point field 式不向外暴露的。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/224411
推荐阅读
  

闽ICP备14008679号