Kiểu dữ liệu boolean
có thể được đối chiếu giữa những giá trị true
hoặc false
được định nghĩa từ trước (hoặc các biểu thức điều kiện). Lỗi sẽ xảy ra nếu như ta so sánh một giá trị kiểu boolean
với một giá trị là kiểu số.
var a := true
if a != (10 == 20) {
fmt.Println("a not true")
}
// Xảy ra lỗi trong quá trình biên dịch
if a == 1 { ... }
So sánh các giá trị kiểu số hoạt động như thông thường, chúng được hỗ trợ cả hai kiểu so sánh tương đường và so sánh thứ tự.
import (
"fmt"
"math"
)
func main() {
a := 3.1415
if a != math.Pi {
fmt.Println("a is not pi")
}
}
Tuy nhiên, do tính nghiêm ngặt giữa các kiểu dữ liệu trong ngôn ngữ Go, nên một giá trị kiểu số nguyên chỉ có thể so sánh với một giá trị kiểu số nguyên khác, và một giá trị kiểu số động chỉ có thể so sánh với một giá trị kiểu số động khác (hoặc biểu thức tạo chúng). Nếu bạn cố thử so sánh giá trị kiểu số nguyên với giá trị kiểu số động, thì bạn sẽ cần phải chuyển đổi chúng về cùng kiểu nếu không sẽ xảy ra lỗi trong quá trình biên dịch.
func main() {
a := 3.1415
b := 6
if a != b {
fmt.Println("a is not b")
} else if a <= b {
fmt.Println("a is in the right position")
}
}
// Lỗi biên dịch:
// operation: a != b (mismatched types float64 and int)
Trong ví dụ trên, đoạn code này sẽ chỉ được biên dịch thành công nếu cả hai biến được khai báo với kiểu dữ liệu giống nhau hoặc chuyển đổi về cùng kiểu dữ liệu.
func main() {
a := 3.1415
b := 6
if a != float64(b) {
fmt.Println("a is not b")
}
}
Các giá trị số phức cũng có thể được kiểm tra tương đương. Hai số phức tương đương với nhau nếu phần thực và phần ảo tương ứng của chúng bằng nhau.
func main() {
a := complex(-3.25, 2)
b := -3.25 + 2i
if a == b {
fmt.Println("a complex as b")
}
}
Tuy nhiên, do tính chất của số phức, chúng không được hỗ trợ so sánh lớn hơn, nhỏ hơn ở trong Go.
func main() {
a := complex(-3.25, 2)
b := -3.25 + 2i
if a < b {
fmt.Println("a complex as b")
}
}
// Lỗi biên dịch
// invalid operation: a <= b (operator <= not defined on complex128)
Trong Go, các giá trị chuỗi hỗ trợ cả hai kiểu so sánh tương đương và so sánh lớn hơn, nhỏ hơn. Không có các chức năng bổ sung để so sánh các chuỗi. Giá trị có thể được tự động so sánh sử dụng từ điển bằng các toán tử ==
, !=
, <=
, <
, >
, và >=
.
func main() {
cols := []string{
"xanadu", "red", "fulvous",
"white", "green", "blue",
"orange", "black", "almond"
}
for _, col := range cols {
if col >= "red" || col == "black" {
fmt.Println(col)
}
}
}
Hai giá trị struct
có thể được kiểm tra tính tương đương bằng cách so sánh các giá trị riêng lẻ của chúng. Nói chung, hai giá trị struct
được quyết định là tương đương nếu chúng có cùng kiểu và các trường tương ứng của chúng tương đương với nhau.
func main() {
p1 := struct {a string; b int}{"left", 4}
p2 := struct {a string; b int}{a: "left", b: 4}
if p1 == p2 {
fmt.Println("Same position")
}
}
Trong đoạn code phía trên, struct p1
tương đương với struct p2
vì chúng có cùng kiểu dữ liệu và các trường tương ứng của chúng có giá trị giống nhau. Bất kì sự thay đổi nào trong giá trị các trường sẽ gây ra các việc struct không còn tương đương với nhau nữa.
Tuy nhiên, các giá trị struct
không thể so sánh được bằng các toán tử so sánh lớn hơn, nhỏ hơn. Vì vậy đoạn code dưới đây sẽ biên dịch lỗi:
func main() {
p1 := struct {a string; b int}{"left", 4}
p2 := struct {a string; b int}{a: "left", b: 4}
if p1 > p2 {
fmt.Println("Same position")
}
// Lỗi biên dịch
// invalid operation: p1 > p2 (operator > not defined on struct)
}
Các giá trị mảng được so sánh tương đương bằng cách so sánh các phần tử của các loại dữ liệu xác định. Các mảng được quyết định là tương đương nếu như các phần tử tương ứng trong chúng tương đương với nhau.
func main() {
pair1 := [2]int {4, 2}
pair2 := [2]int {2, 4}
if pair1 != pair2 {
fmt.Println("different pair")
}
}
Giống như các giá trị struct
, ta không thể so sánh các mảng bằng các toán tử so sánh lớn hơn, nhỏ hơn <
, <=
, >
, >=
. Nếu cố thử làm điều đó sẽ gây ra lỗi khi biên dịch.
Các giá trị pointer
có thể được so sánh tương đương nhưng so sánh lớn hơn, nhỏ hơn thì không. Hai gá trị pointer
được quyết định là tương đương nếu chúng trỏ đến cùng một giá trị trong bộ nhớ (hoặc nếu chúng cùng là nil
). Ví dụ, &pair
trong đoạn code dưới đây sẽ tương đương với ptr2
, trong khi &pair
và ptr
thì không tương đương.
func main() {
pair := [2]int {4, 2}
ptr := &[2]int {4, 2}
ptr2 := &pair
if &pair != ptr {
fmt.Println("pointing different")
}
if &pair == ptr2 {
fmt.Println("pointing the same")
}
}
Các giá trị interface
không những có thể được so sánh với các giá trị interface
khác, mà còn có thể so sánh với các kiểu dữ liệu implement
chúng.
Hai giá trị interface
được quyết định là bằng nhau nếu các kiểu dữ liệu cụ thể, các giá trị của chúng có thể so sánh được và tương đương với nhau, hoặc cả hai interface
đều là nil
.
Ví dụ, trong đoạn code dưới đây, hai giá trị interface r0
và r2
là tương đương vì chúng implement cùng kiểu dữ liệu cụ thể và cùng giá trị như nhau,
rectangle{l:3, w:6}
. Mặt khác, hai giá trị interface r0
và r1
mặc dù cùng implement interface giống nhau, nhưng các giá trị khác nhau nên chúng sẽ không tương đương, rectangle{3, 6}
vs rectangle{6, 3}
. Tương tự, các biến r1
và s0
không tương đương vì chúng có các giá trị khác nhau mặc dù chùng cùng implement một interface.
type shape interface {
area() int
}
type rectangle struct {
l int
w int
}
func (r rectangle) area() int {
return r.l * r.w
}
type square struct {
l int
}
func (s square) area() int {
return s.l * s.l
}
func main() {
var r0 shape = rectangle{3, 6}
var r1 shape = rectangle{6, 3}
var r2 shape = rectangle{3, 6}
var s0 shape = square{5}
if r0 == r2 {
fmt.Println("r0 and r2 same shapes")
}
fmt.Println("r1 and s0 equal", (r1 == s0))
}
Một điều quan trọng cần chú ý đó là, nếu các kiểu dữ liệu của interface
không thể so sánh mà ta vẫn cố thử so sánh chúng thì sẽ gây ra lỗi trong quá trình runtime.
Các giá trị Chanel
chỉ có thể sử dụng so sánh tương đương. Hai giá trị chanel
được cho là tương đương nhau nếu chúng bắt nguồn từ cùng một câu lệnh make
(nghĩa là chúng cùng tham chiếu đến một giá trị chanel
trong bộ nhớ).
Ví dụ, trong ví dụ sau đây, ch0
sẽ không tương đương với ch1
ngay cả khi chúng có cùng kiểu dữ liệu. Tuy nhiên, ch1
sẽ tương đương với ch2
vì cả hai đều tham chiếu đến cùng một chanel
.
func main() {
ch0 := make(chan int)
ch1 := make(chan int)
ch2 := ch1
fmt.Println("ch0 == ch1", (ch0 == ch1))
fmt.Println("ch1 == ch2", (ch1 == ch2))
}