better way to express a function in Go (Struct methods)

Issue

This is a function to traverse an array of Points. A Point is a struct with elements x and y of type int. The traverse function is called from another function with a value of dir. The if check at the beginning of the loop can be avoided because the dir value, once the function is called, does not change. Is there a better way to express this logic in Go? The struct method returns a Point. I have provided one example of the struct method.

type Point struct {
    x int
    y int
}

func (p Point) next_row() Point {
    nearby := Point{p.x + 1, p.y}
    return nearby
}

func trv_point(p Point, p_list []Point, dir string) int {
    seg_count := 0
    var nearby Point
    for {
        if dir == "up" {
            nearby = p.prev_row()
        }
        if dir == "down" {
            nearby = p.next_row()
        }
        if dir == "left" {
            nearby = p.prev_col()
        }
        if dir == "right" {
            nearby = p.next_col()
        }

        if !check_point_in_slice(p_list, nearby) {
            break
        }
        seg_count++
        p = nearby

    }
    return seg_count
}

Solution

Because the dir is not change here, those if statements are redundent, also you should use if-else statments for this case because just one of the ["up", "down", "left", "right"] could happened.
First look to this example:

type Point struct {
    x int
    y int
}

func (p *Point) next_row() {
    p.x += 1
}

func main() {
    p := Point{0, 0}
    f := p.next_row

    for i := 0; i < 2; i++ {
        fmt.Println(p)
        f()
    }
    fmt.Println(p)
}

the output will be:

{0 0}
{1 0}
{2 0}

Here we change the receiver from (p Point) to (p *Point) because we want to save the effects on x and y.
By this assumption we could rewrite as:

type Point struct {
    x int
    y int
}

func (p *Point) next_row() {
    p.x += 1
}

func get_move(dir string) func() {
    var f func()
    switch dir {
    case "up":
        f = p.prev_row
    case "down":
        f = p.next_row
    case "left":
        f = p.prev_col
    case "right":
        f = p.next_col
    }
    return f
}

func trv_point(p Point, p_list []Point, dir string) int {
    seg_count := 0
    var nearby Point
    f := get_move(dir)
    for check_point_in_slice(p_list, p) {
        f()
        seg_count++
    }
    return seg_count
}

Answered By – S4eed3sm

Answer Checked By – Gilberto Lyons (GoLangFix Admin)

Leave a Reply

Your email address will not be published.