# Go-再论struct

u013344915 · · 863 次点击 · · 开始浏览

# 简介

Go-Structure对struct做了简单的介绍，本文参考如下书目继续丰富本专题。

• 《Web Development with Go》 Chapter 3
• 《The Go Programming Language》4.4 Page99

# pointer and nonpointer method receiver

``````package main

import (
"fmt"
)

type Point struct {
x, y int
}

func (p Point) GetX() int {
return p.x
}

func (p Point) GetY() int {
return p.y
}

func (p *Point) SetX(ix int) {
(*p).x = ix
}

func (p *Point) SetY(iy int) {
(*p).y = iy
}

func (p *Point) SetY2(iy int) {
p.y = iy
}

func (p Point) SetY3(iy int) {
p.y = iy
}

func test1() {
p := Point{1, 2}
fmt.Print(p, "\t")

fmt.Print("x=", p.GetX(), "\t")
fmt.Print("y=", p.GetY(), "\t")

p.SetX(3)
p.SetY(4)
fmt.Print(p, "\t")

(&p).SetX(5)
(&p).SetY(6)
fmt.Print(p, "\t")

fmt.Println()
}

// SetY() -> SetY2()
func test2() {
p := Point{1, 2}
fmt.Print(p, "\t")

fmt.Print("x=", p.GetX(), "\t")
fmt.Print("y=", p.GetY(), "\t")

p.SetX(3)
p.SetY2(4)
fmt.Print(p, "\t")

(&p).SetX(5)
(&p).SetY2(6)
fmt.Print(p, "\t")

fmt.Println()
}

// SetY() -> SetY3()
func test3() {
p := Point{1, 2}
fmt.Print(p, "\t")

fmt.Print("x=", p.GetX(), "\t")
fmt.Print("y=", p.GetY(), "\t")

p.SetX(3)
p.SetY3(4)
fmt.Print(p, "\t")

(&p).SetX(5)
(&p).SetY3(6)
fmt.Print(p, "\t")

fmt.Println()
}

func test4() {
p := &Point{1, 2}
fmt.Print(p, "\t")

fmt.Print("x=", p.GetX(), "\t")
fmt.Print("y=", p.GetY(), "\t")

p.SetX(3)
p.SetY(4)
fmt.Print(p, "\t")

//calling method SetX with receiver &p (type **Point) requires explicit dereference
//(&p).SetX(5)
//(&p).SetY(6)
//fmt.Print(p, "\t")

fmt.Println()
}
/*
D:\examples>go run helloworld.go
test1: {1 2}    x=1     y=2     {3 4}   {5 6}
test2: {1 2}    x=1     y=2     {3 4}   {5 6}
test3: {1 2}    x=1     y=2     {3 2}   {5 2}
test4: &{1 2}   x=1     y=2     &{3 4}

D:\examples>
*/
func main() {
fmt.Print("test1: ")
test1()

fmt.Print("test2: ")
test2()

fmt.Print("test3: ")
test3()

fmt.Print("test4: ")
test4()
}
``````

# 要点

copied from：《Web Development with Go》 Chapter 3, Page 39

If you want to modify the data of a receiver from the method, the receiver must be a pointer

If the struct has a pointer receiver on some its methods, it is better to use it for the rest of the methods because it enables better consistency and predictability for the struct behaviors.

# pointer & dot notation

``````func (p *Point) SetY2(iy int) {
p.y = iy
}
``````

``````func (p *Point) SetY2(iy int) {
(*p).y = iy
}
``````

``````type Employee struct {
ID        int
Name      string
DoB       time.Time
Position  string
Salary    int
ManagerID int
}
``````

The dot notation also works with a pointer to a struct:

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

The last statement is equivalent to

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

Go指针的这种语法可以简化代码。

# 结构自嵌套

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

# 比较结构体对象

Go中不能重载==操作符，对于要比较（同一种）结构体的两个对象，则要求其每个field都是可以比较的。而且在比较的时候，是按照每个field依次比较。也可以自定义比较的函数，比如Equals()。

``````package main

import (
"fmt"
)

type Point struct {
x, y int
}

func (p Point) GetX() int {
return p.x
}

func (p Point) GetY() int {
return p.y
}

func (p *Point) SetX(ix int) {
p.x = ix
}

func (p *Point) SetY(iy int) {
p.y = iy
}

func (p *Point) Equals(point Point) bool {
return p.x == point.x
}

func Equals(p1 Point, p2 Point) bool {
return p1.x == p2.x
}

func main() {
p1 := Point{1, 2}
p2 := Point{x:1, y:2}
p3 := Point{1, 3}

fmt.Println(p1 == p2, p2 == p3) // true, false
fmt.Println(p1.x == p2.x && p1.y == p2.y) // true. Equals to "p1 == p2"
fmt.Println(p1.Equals(p3)) // true
fmt.Println(Equals(p2, p3)) // true
}
``````

0 回复

• 请尽量让自己的回复能够对别人有帮助
• 支持 Markdown 格式, **粗体**、~~删除线~~、``单行代码``
• 支持 @ 本站用户；支持表情（输入 : 提示），见 Emoji cheat sheet
• 图片支持拖拽、截图粘贴等方式上传

# 简介

Go-Structure对struct做了简单的介绍，本文参考如下书目继续丰富本专题。

• 《Web Development with Go》 Chapter 3
• 《The Go Programming Language》4.4 Page99

# pointer and nonpointer method receiver

``````package main

import (
"fmt"
)

type Point struct {
x, y int
}

func (p Point) GetX() int {
return p.x
}

func (p Point) GetY() int {
return p.y
}

func (p *Point) SetX(ix int) {
(*p).x = ix
}

func (p *Point) SetY(iy int) {
(*p).y = iy
}

func (p *Point) SetY2(iy int) {
p.y = iy
}

func (p Point) SetY3(iy int) {
p.y = iy
}

func test1() {
p := Point{1, 2}
fmt.Print(p, "\t")

fmt.Print("x=", p.GetX(), "\t")
fmt.Print("y=", p.GetY(), "\t")

p.SetX(3)
p.SetY(4)
fmt.Print(p, "\t")

(&p).SetX(5)
(&p).SetY(6)
fmt.Print(p, "\t")

fmt.Println()
}

// SetY() -> SetY2()
func test2() {
p := Point{1, 2}
fmt.Print(p, "\t")

fmt.Print("x=", p.GetX(), "\t")
fmt.Print("y=", p.GetY(), "\t")

p.SetX(3)
p.SetY2(4)
fmt.Print(p, "\t")

(&p).SetX(5)
(&p).SetY2(6)
fmt.Print(p, "\t")

fmt.Println()
}

// SetY() -> SetY3()
func test3() {
p := Point{1, 2}
fmt.Print(p, "\t")

fmt.Print("x=", p.GetX(), "\t")
fmt.Print("y=", p.GetY(), "\t")

p.SetX(3)
p.SetY3(4)
fmt.Print(p, "\t")

(&p).SetX(5)
(&p).SetY3(6)
fmt.Print(p, "\t")

fmt.Println()
}

func test4() {
p := &Point{1, 2}
fmt.Print(p, "\t")

fmt.Print("x=", p.GetX(), "\t")
fmt.Print("y=", p.GetY(), "\t")

p.SetX(3)
p.SetY(4)
fmt.Print(p, "\t")

//calling method SetX with receiver &p (type **Point) requires explicit dereference
//(&p).SetX(5)
//(&p).SetY(6)
//fmt.Print(p, "\t")

fmt.Println()
}
/*
D:\examples>go run helloworld.go
test1: {1 2}    x=1     y=2     {3 4}   {5 6}
test2: {1 2}    x=1     y=2     {3 4}   {5 6}
test3: {1 2}    x=1     y=2     {3 2}   {5 2}
test4: &{1 2}   x=1     y=2     &{3 4}

D:\examples>
*/
func main() {
fmt.Print("test1: ")
test1()

fmt.Print("test2: ")
test2()

fmt.Print("test3: ")
test3()

fmt.Print("test4: ")
test4()
}
``````

# 要点

copied from：《Web Development with Go》 Chapter 3, Page 39

If you want to modify the data of a receiver from the method, the receiver must be a pointer

If the struct has a pointer receiver on some its methods, it is better to use it for the rest of the methods because it enables better consistency and predictability for the struct behaviors.

# pointer & dot notation

``````func (p *Point) SetY2(iy int) {
p.y = iy
}
``````

``````func (p *Point) SetY2(iy int) {
(*p).y = iy
}
``````

``````type Employee struct {
ID        int
Name      string
DoB       time.Time
Position  string
Salary    int
ManagerID int
}
``````

The dot notation also works with a pointer to a struct:

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

The last statement is equivalent to

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

Go指针的这种语法可以简化代码。

# 结构自嵌套

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

# 比较结构体对象

Go中不能重载==操作符，对于要比较（同一种）结构体的两个对象，则要求其每个field都是可以比较的。而且在比较的时候，是按照每个field依次比较。也可以自定义比较的函数，比如Equals()。

``````package main

import (
"fmt"
)

type Point struct {
x, y int
}

func (p Point) GetX() int {
return p.x
}

func (p Point) GetY() int {
return p.y
}

func (p *Point) SetX(ix int) {
p.x = ix
}

func (p *Point) SetY(iy int) {
p.y = iy
}

func (p *Point) Equals(point Point) bool {
return p.x == point.x
}

func Equals(p1 Point, p2 Point) bool {
return p1.x == p2.x
}

func main() {
p1 := Point{1, 2}
p2 := Point{x:1, y:2}
p3 := Point{1, 3}

fmt.Println(p1 == p2, p2 == p3) // true, false
fmt.Println(p1.x == p2.x && p1.y == p2.y) // true. Equals to "p1 == p2"
fmt.Println(p1.Equals(p3)) // true
fmt.Println(Equals(p2, p3)) // true
}
``````