Go-再论struct

u013344915 · · 838 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

简介

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.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
}

这种语法是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 = &dilbert
employeeOfTheMonth.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
}

有疑问加站长微信联系(非本文作者)

本文来自:CSDN博客

感谢作者:u013344915

查看原文:Go-再论struct

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

838 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传