เนื่องจากค่า nil ใน Go สามารถเป็นค่าที่กำหนดให้กับหลาย type ได้ ดังนั้นการเปรียบเทียบค่า nil ด้วย operator ==
และ !=
จึงขึ้นอยู่กับ type ด้วยเช่นกัน ถ้าเราเขียนโค้ดแบบนี้
package main
import (
"fmt"
)
func main() {
fmt.Println(nil == nil)
fmt.Println(nil != nil)
}
แล้ว compile ดูเราจะเจอ compile error แบบนี้
# command-line-arguments
./main.go:14:18: invalid operation: nil == nil (operator == not defined on nil)
./main.go:15:18: invalid operation: nil != nil (operator != not defined on nil)
นั่นคือโดยตัวค่า nil
เองนั้นเปรียบเทียบกันไม่ได้ เพราะว่าถ้าเราจับ nil
ไปเปรียบเทียบตัว compiler จะไม่รู้ type ของ nil
เลย
ทีนี้ type ใน Go ที่สามารถมีค่า nil
ได้ประกอบไปด้วย
- pointer ของ type ใดๆ
- slice
- map
- channel
- function
- interface
ทีนี้ถ้าผมเขียนโค้ดแบบนี้เพื่อทดสอบการเปรียบเทียบค่า nil
ของแต่ละ type ด้านบน เริ่มจาก pointer
package main
import (
"fmt"
)
func main() {
var nilValue *string = nil
fmt.Println(nilValue == nilValue)
fmt.Println(nilValue != nilValue)
}
เมื่อ compile จะ compile ได้และ run จะได้
> go run main.go
true
false
นั่นคือ pointer type เดียวกัน ที่มีค่า nil
สามารถเปรียบเทียบกันได้
ต่อไปเป็น slice
package main
import (
"fmt"
)
func main() {
var nilValue []string = nil
fmt.Println(nilValue == nilValue)
fmt.Println(nilValue != nilValue)
}
เมื่อ compile จะ error แบบนี้
> go run main.go
# command-line-arguments
./main.go:9:23: invalid operation: nilValue == nilValue (slice can only be compared to nil)
./main.go:10:23: invalid operation: nilValue != nilValue (slice can only be compared to nil)
นั่นหมายถึงว่าตัวแปรของ type slice ที่มีค่า nil
จะเปรียบเทียบกับตัวแปร type slice อื่นๆไม่ได้ แม้ว่ามันจะเก็บค่า nil
เหมือนกันก็ตาม เห็นโค้ดที่เปรียบเทียบกับตัวมันเองแบบด้านบนก็ไม่ได้ แต่สามารถเปรียบเทียบกับ nil
โดยตรงได้เช่น
package main
import (
"fmt"
)
func main() {
var nilValue []string = nil
fmt.Println(nilValue == nil)
fmt.Println(nilValue != nil)
}
เมื่อ compile และ run แล้วจะได้
> go run main.go
true
false
ต่อไปเป็น map
package main
import (
"fmt"
)
func main() {
var nilValue map[string]string = nil
fmt.Println(nilValue == nilValue)
fmt.Println(nilValue != nilValue)
}
เมื่อ compile จะ error แบบนี้
> go run main.go
# command-line-arguments
./main.go:9:23: invalid operation: nilValue == nilValue (map can only be compared to nil)
./main.go:10:23: invalid operation: nilValue != nilValue (map can only be compared to nil)
นั่นหมายถึงว่าตัวแปรของ type map ที่มีค่า nil
จะเปรียบเทียบกับตัวแปร type map อื่นๆไม่ได้ แม้ว่ามันจะเก็บค่า nil
เหมือนกันก็ตาม เห็นโค้ดที่เปรียบเทียบกับตัวมันเองแบบด้านบนก็ไม่ได้ แต่สามารถเปรียบเทียบกับ nil
โดยตรงได้เช่น
package main
import (
"fmt"
)
func main() {
var nilValue map[string]string = nil
fmt.Println(nilValue == nil)
fmt.Println(nilValue != nil)
}
เมื่อ compile และ run แล้วจะได้
> go run main.go
true
false
ต่อไปเป็น channel
package main
import (
"fmt"
)
func main() {
var nilValue chan string = nil
fmt.Println(nilValue == nilValue)
fmt.Println(nilValue != nilValue)
}
เมื่อ compile และ run แล้วจะได้
> go run main.go
true
false
นั่นคือ channel type เดียวกัน ที่มีค่า nil
สามารถเปรียบเทียบกันได้
ต่อไปเป็น function
package main
import (
"fmt"
)
func main() {
var nilValue func() = nil
fmt.Println(nilValue == nilValue)
fmt.Println(nilValue != nilValue)
}
เมื่อ compile จะ error แบบนี้
> go run main.go
# command-line-arguments
./main.go:9:23: invalid operation: nilValue == nilValue (func can only be compared to nil)
./main.go:10:23: invalid operation: nilValue != nilValue (func can only be compared to nil)
นั่นหมายถึงว่าตัวแปรของ type function ที่มีค่า nil
จะเปรียบเทียบกับตัวแปร type function อื่นๆไม่ได้ แม้ว่ามันจะเก็บค่า nil
เหมือนกันก็ตาม เห็นโค้ดที่เปรียบเทียบกับตัวมันเองแบบด้านบนก็ไม่ได้ แต่สามารถเปรียบเทียบกับ nil
โดยตรงได้เช่น
package main
import (
"fmt"
)
func main() {
var nilValue func() = nil
fmt.Println(nilValue == nil)
fmt.Println(nilValue != nil)
}
เมื่อ compile และ run แล้วจะได้
> go run main.go
true
false
ต่อไปเป็น interface
package main
import (
"fmt"
)
func main() {
var nilValue interface{} = nil
fmt.Println(nilValue == nilValue)
fmt.Println(nilValue != nilValue)
}
เมื่อ compile และ run แล้วจะได้
> go run main.go
true
false
นั่นคือ interface type เดียวกัน ที่มีค่า nil
สามารถเปรียบเทียบกันได้
ถ้าจะสรุปก็คือ จะมีทั้งตัวแปรของ type ที่สามารถมีค่า nil
แล้วสามารถเอาตัวแปรไปเปรียบเทียบกับตัวแปรอื่นที่มีค่า nil
ได้ กับ อีกแบบคือเปรียบเทียบได้แต่กับ nil
โดยตรง เปรียบเทียบกับตัวแปรอื่นไม่ได้
type ที่สามารถเปรียบเทียบตัวแปรที่มีค่า nil
กับตัวแปรอื่นได้ ได้แก่
- pointer
- interface
- channel
type ที่สามารถเปรียบเทียบตัวแปรที่มีค่า nil
กับ nil
โดยตรงได้เท่านั้นได้แก่
- slice
- map
- function
สุดท้ายอีกเรื่องสำหรับ nil
คือ nil
ไม่ใช่ keyword ใน Go แต่เป็นชื่อที่ถูกกำหนดค่าเริ่มต้นเป็นค่าพิเศษค่านึงมาแล้ว ดังนั้น nil
จึงสามารถถูกเอาไปใช้เป็นชื่อของตัวแปรได้ เช่นเราสามารถเขียนโค้ดนี้แล้ว compile และ run ได้
package main
import (
"fmt"
)
func main() {
nil := 0
fmt.Println(nil == nil)
fmt.Println(nil != nil)
}
แต่อย่างไรก็ตาม อย่าเขียนแบบนี้ในโปรแกรมของเราเลยจะดีกว่า เพราะจะชวนให้เพื่อนๆในทีด่าได้ง่ายๆ :D
Top comments (0)