The comparison operation of the Go language

Source: Internet
Author: User
Tags comparable
This is a creation in Article, where the information may have evolved or changed.

First distinguish several concepts: variables can be compared, sortable, assignable

can be assigned value

In the specification, the assignment is so defined: https://golang.org/ref/spec#Assignability

A value x is assignable to a variable of type T ("X was assignable to T") in any of the These cases:

  • X ' s type is identical to T.
  • X ' s type V and T has identical underlying types and at least one of V or T are not a defined type.
  • T is an interface type and X implements T.
  • X is a bidirectional channel value, T is a channel type, X ' s type V and T has identical element types, and at least one O F V or T is a defined type.
  • X is the predeclared identifier nil and T is a pointer, function, slice, map, channel, or interface type.
  • X is an untyped constant representable by a value of type T.

It is summed up that their type needs to satisfy a certain condition, or the same type, or the underlying type (underlying types) is the same.

can be compared

In the specification, the comparison operation is defined as: https://golang.org/ref/spec#Comparison_operators

Can be compared and can be divided into two small categories

    1. Comparable, including equality (= =), and unequal (! =)
    2. Sortable, including greater than (>), greater than or equal (>=), less than (>), less than or equal (<=)

Sortable must be comparable, and vice versa, can be compared is not necessarily sortable, for example, the struct type is comparable, but not sortable.

    1. There are three types of data that can be sorted, integer,floating-point, and string
    2. Comparable data types in addition to the above three kinds, there are boolean,complex,pointer,channel,interface,struct, and array
    3. Non-comparable data types include, Slice, Map, and function

The above specifications in the face of what kind of data to compare, how to do the same description, do not elaborate, please refer to the original text.

As for how to define their equal rules, please refer to the above specification document.

Assignable and comparable relationships

That's what the spec says:

In any comparison, the first operand must is assignable to the type of the second operand, or vice versa.

That is, if two variables can be compared, then they must be assignable, or the left variable can be assigned to the right variable, or the right variable can be assigned to the left variable. Conversely, the variable that can be assigned is not necessarily comparable, such as the previously mentioned map type variable.

So two comparable variables must also satisfy them or the same type, or their underlying type (underlying types) is the same.

Whether two variables can be compared this rule is the compiler is responsible for static checking at compile time.

Examples of comparison of struct types

The comparison of basic type variables is straightforward, not in the discussion, here we give a comparison of several struct types to illustrate the comparison of the struct.
Note that this refers to equality comparisons, not sort comparisons, because structs are not sortable.

The rule definition for struct comparison within the specification:

Struct values is comparable if all their fields is comparable. The values of both structs are equal if their corresponding Non-blank fields is equal.

Example 1: Whether the type is the same problem

  Package Mainimport "FMT" type T1 struct {name string}type T2 struct {name string}func Main () {v11: = T1 {"Foo"} v12: = T1 {"foo"} v21: = T2 {"foo"} v22: = T2 {"foo"} FMT. Printf ("v11 = = V12 is%v\n", v11 = = v12)//output:v11 = V12 is true//fmt.  Printf ("v11 = = V21 is%v\n", v11 = = v21)//Compile error, Invalid operation:v11 = v21 (mismatched types T1 and T2) Fmt.  Printf ("v11 = = V22 is%v\n", v11 = = v22)//Compile error, Invalid operation:v11 = v22 (mismatched types T1 and T2) Fmt.  Printf ("V12 = = V21 is%v\n", v12 = = v21)//Compile error, Invalid OPERATION:V12 = v21 (mismatched types T1 and T2) Fmt.    Printf ("V12 = = V22 is%v\n", v12 = = v22)//Compile error, Invalid OPERATION:V12 = v22 (mismatched types T1 and T2) Fmt. Printf ("v21 = = V22 is%v\n", v21 = = v22)//output:v21 = V22 is true}  

This example shows that when the struct types are different, they are not comparable, and the compiler statically checks the type at compile time, in this case the variables v1x and V2X are of different types, one is T1 and the other is T2, so they cannot be compared, although their internal underlying type, Because the definitions of T1 and T2 are the same, go determines that they are of different types.

Because this violates the first qualifying condition that can be compared, that is, the variable must be assignable; T1 and T2 are not mutually assignable types.

For a question of the same type of judgment, give another example:

package mainimport "fmt" type Int intfunc main() {    var v11 int = 1    var v12 int = 1    var v21 Int = 1    var v22 Int = 1         fmt.Printf("v11 == v12 is %v\n", v11 == v12)    // output: v11 == v12 is true  //fmt.Printf("v11 == v21 is %v\n", v11 == v21)    // compile error, invalid operation: v11 == v21 (mismatched types int and Int)  //fmt.Printf("v11 == v22 is %v\n", v11 == v22)    // compile error, invalid operation: v11 == v22 (mismatched types int and Int)  //fmt.Printf("v12 == v21 is %v\n", v12 == v21)    // compile error, invalid operation: v12 == v21 (mismatched types int and Int)  //fmt.Printf("v12 == v22 is %v\n", v12 == v22)    // compile error, invalid operation: v12 == v22 (mismatched types int and Int)    fmt.Printf("v21 == v22 is %v\n", v21 == v22)    // output: v21 == v22 is true}

In this example, we define a new data type int, although in fact he is int,int just a wrapper,go language of int or think they are different data types.

Example 2: Whether all fields (field) are comparable

package mainimport "fmt"type T1 struct { name string }type T2 struct { name string; attrs map[string]interface{} }func main() {    v11 := T1 { "foo" }    v12 := T1 { "foo" }    v21 := T2 { "foo", make(map[string]interface{}) }    v22 := T2 { "foo", make(map[string]interface{}) }    fmt.Printf("v11 == v12 is %v\n", v11 == v12)    // output: v11 == v12 is true    fmt.Printf("v21 == v22 is %v\n", v21 == v22)    // compile error: invalid operation: v21 == v22 (struct containing map[string]interface {} cannot be compared)}

According to the specification description type T2 can compare all fields that need it, because T2 contains a attrs domain, its type is map, and map is not comparable, so T2 cannot be compared.

Example 3: Include airspace (Blank Field)

package mainimport "fmt"type T1 struct {     i int64    j int32    _ int32}// About blank field:// You cannot set or get a blank field; it cannot be refered.// You can't do it in a composite literal either.// The only use for a blank field in a struct is for padding.func main() {    v11 := T1 { i:10, j:10 }    v12 := T1 { i:10, j:10 }    fmt.Printf("v11 == v12 is %v\n", v11 == v12)    // output: v11 == v12 is true}

This example uses the blank field, which shows that the struct discards the blank field at the time of comparison, regardless of the value of the blank field, and we guess that the logic for comparing the struct type inside the go language is to iterate through all the domains and compare them for each domain separately. Returns True when all recursive fields return True, and returns False when any one returns false; the visible struct is not a comparison object's address, nor is it a comparison of object memory block values, but a recursive comparison of a domain traversal, and blank field cannot be referenced, Thus does not participate in the comparison.

Example 4: Anonymous type comparison

The go language defines two types: named types, and anonymous types.

  Package Mainimport "FMT" import "reflect" type T1 struct {name string}type T2 struct {name string}func main () {v1: = T1 {"foo"} v2: = T2 {"foo"} v3: = struct{name string} {"Foo"} v4: = struct{name string} {"Foo "} FMT. Println ("V1:type=", reflect. TypeOf (v1), "value=", reflect. ValueOf (v1))//v1:type= main. T1 value= {foo} fmt. Println ("V2:type=", reflect. TypeOf (v2), "value=", reflect. ValueOf (v2))//v2:type= main. T2 value= {foo} fmt. Println ("V3:type=", reflect. TypeOf (v3), "value=", reflect. ValueOf (v3))//v3:type= struct {name string} value= {foo} fmt. Println ("V4:type=", reflect. TypeOf (v4), "value=", reflect. ValueOf (v4))//v4:type= struct {name string} value= {foo}//fmt. Println (v1 = = v2)//compiler Error:invalid OPERATION:V1 = v2 (mismatched types T1 and T2) fmt. Println (V1 = = V3)//True, why? Their type is different FMT.    Println (v2 = = V3)//True, why? Fmt. Println (v3 = = v4)//true}  

This place is good to understand is that V1 and V2 are different types, one is the T1 one is T2, the previous we talked about although T1 and T2 the underlying types, but go think they are different types.
Then V3 and V4 understand that their type is the same as the anonymous type.
It is not easy to understand that V1 and v3,v2 and V3 clearly their type is not the same, why output true?

To answer this question, we return to the canonical definition

Struct values is comparable if all their fields is comparable. The values of both structs are equal if their corresponding Non-blank fields is equal.

About whether a struct can be compared, only to see if all of his fields are comparable, in this case, there is only one domain, name string, which is comparable, so this one is sufficient, that is, the struct is comparable.

Look at another definition in the specification, which is defined for a general variable, not just a struct

In any comparison, the first operand must is assignable to the type of the second operand, or vice versa.

Only when this rule can be satisfied, two variables can be compared, in our case V1 and V2 do not satisfy this, all cannot be compared, and V3 and V4 are to satisfy this, all V3 and V4 are comparable.

Summary: Comparison of structs

The comparison of a struct requires only two conditions to be met:

    1. The rule inherited from all comparison operations, that is, two variables must be assignable.
    2. The rules for the struct itself, that is, all the fields of a struct must be comparable; Note that this is not the type of definition of the struct itself.

As long as these two conditions are met, the struct is comparable; it is not possible to see that the type of the two struct must be the same, thus explaining the comparison rule of the named type and the anonymous type struct, that is, it does not control the name, and vice versa, it is the struct type.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.