網頁

2022/7/2

Golang struct比較是否相等

Go比較兩個struct是否相等的方式如下。


Go的struct所有欄位都是可比較相等的型態時則可直接用==比較是否相等。

例如下面Employee struct的欄位型態皆為可比較型態,所以直接以==比較是否相等。

main.go

package main

import "fmt"

type Employee struct {
    ID   int64
    Name string
    Age  int
}

func main() {
    emp1 := Employee{ID: 1, Name: "John", Age: 33}
    emp2 := Employee{ID: 1, Name: "John", Age: 33}

    fmt.Println(emp1 == emp2) // true
}

但若欄位有一為不可比較相等的型態,例如slice、map或function,則struct則不能用==比較是否相等。

例如下面在Employee增加了slice欄位Phones則以==比較時出現編譯錯誤invalid operation: cannot compare emp1 == emp2 (struct containing []string cannot be compared)

main.go

package main

import "fmt"

type Employee struct {
    ID     int64
    Name   string
    Age    int
    Phones []string
}

func main() {
    emp1 := Employee{ID: 1, Name: "John", Age: 33, Phones: []string{"0912345678"}}
    emp2 := Employee{ID: 2, Name: "John", Age: 33, Phones: []string{"0912345678"}}

    fmt.Println(emp1 == emp2) // invalid operation: cannot compare emp1 == emp2 (struct containing []string cannot be compared)
}

此時可實作一個比較相等的方法來比較,如下面的Employee.Equal()

package main

import "fmt"

type Employee struct {
    ID     int64
    Name   string
    Age    int
    Phones []string
}

func (emp1 *Employee) Equal(emp2 *Employee) bool {
    if emp1 == emp2 {
        return true
    }
    if emp1.ID != emp2.ID || emp1.Name != emp2.Name || emp1.Age != emp2.Age {
        return false
    }

    if len(emp1.Phones) != len(emp2.Phones) {
        return false
    }
    for i, v := range emp1.Phones {
        if v != emp2.Phones[i] {
            return false
        }
    }
    return true
}

func main() {
    emp1 := Employee{ID: 1, Name: "John", Age: 33, Phones: []string{"0912345678"}}
    emp2 := Employee{ID: 1, Name: "John", Age: 33, Phones: []string{"0912345678"}}

    fmt.Println(emp1.Equal(&emp2)) // true
}

或用反射的reflect.DeepEqual(x, y any)比較是否相等,不過要考慮效能問題。

package main

import (
    "fmt"
    "reflect"
)

type Employee struct {
    ID     int64
    Name   string
    Age    int
    Phones []string
}

func main() {
    emp1 := Employee{ID: 1, Name: "John", Age: 33, Phones: []string{"0912345678"}}
    emp2 := Employee{ID: 1, Name: "John", Age: 33, Phones: []string{"0912345678"}}

    fmt.Println(reflect.DeepEqual(emp1, emp2)) // true
}



沒有留言:

張貼留言