這是一個建立於
的文章,其中的資訊可能已經有所發展或是發生改變。
簡介
在Go-Structure對struct做了簡單的介紹,本文參考如下書目繼續豐富本專題。
- 《Web Development with Go》 Chapter 3
- 《The Go Programming Language》4.4 Page99
pointer and nonpointer method receiver
在Go-Structure一文給出的範例程式碼中,使用的都是pointer receiver。事實上,也可以使用nonpointer receiver。事實上,也可以使用nonpointer
樣本:
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.gotest1: {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}
這種文法是Go中非常特殊的一點。這種文法的證據源於《The Go Programming Language》4.4 Page 100,代碼如下:
type Employee struct { ID int Name string Address string DoB time.Time Position string Salary int ManagerID int}
The dot notation also works with a pointer to a struct:
var employeeOfTheMonth *Employee = &dilbertemployeeOfTheMonth.Position += " (proactive team player)"
The last statement is equivalent to
(*employeeOfTheMonth).Position += " (proactive team player)"
Go指標的這種文法可以簡化代碼。
結構自嵌套
一個結構S內部不能有S成員,但可以有指向S的成員(指標 *S).
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}