Skip to content

Commit 060877a

Browse files
authored
Merge pull request #670 from devlights:add-nil-isnt-equal-to-nil-example
Add nil_is_not_equal_to_nil example
2 parents fb4a281 + 94a0b4a commit 060877a

File tree

2 files changed

+107
-0
lines changed

2 files changed

+107
-0
lines changed
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# https://taskfile.dev
2+
3+
version: "3"
4+
5+
tasks:
6+
default:
7+
cmds:
8+
- task: run
9+
run:
10+
cmds:
11+
- go run main.go
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
package main
2+
3+
import (
4+
"github.com/devlights/gomy/output"
5+
)
6+
7+
func main() {
8+
if err := run(); err != nil {
9+
panic(err)
10+
}
11+
}
12+
13+
func run() error {
14+
//
15+
// Go では、nil 同士を比較しても同じにならない場合がある
16+
//
17+
// REFERENCES:
18+
// - https://www.calhoun.io/when-nil-isnt-equal-to-nil/
19+
// - https://forum.golangbridge.org/t/a-nil-a-b-b-nil-with-pointers-and-interface/10593
20+
// - https://staticcheck.io/docs/checks#SA4023
21+
// - https://devlights.hatenablog.com/entry/2021/03/31/235948
22+
//
23+
24+
var (
25+
v1 *int // ゼロ値は nil
26+
v2 any // ゼロ値は nil
27+
)
28+
29+
// どちらもnil
30+
output.Stdoutl("[v1 is nil?]", v1 == nil)
31+
output.Stdoutl("[v2 is nil?]", v2 == nil)
32+
33+
// 同じ? (結果は false となる)
34+
//
35+
// staticcheck では以下の警告が出る
36+
// this comparison is never true; the lhs of the comparison has been assigned a concretely typed value (SA4023)
37+
//
38+
output.Stdoutl("[v1 eq v2]", v1 == v2) //lint:ignore SA4023 It's ok because this is just a example.
39+
40+
output.StdoutHr()
41+
42+
//
43+
// v1をv2に設定してみる
44+
// (論理的には nil な変数に nil を設定していることになる)
45+
//
46+
v2 = v1
47+
48+
// 同じ? (結果は true となる)
49+
//
50+
// staticcheckでは今度は v2 == nil の部分で警告が出る
51+
// this comparison is never true; the lhs of the comparison has been assigned a concretely typed value (SA4023)
52+
//
53+
output.Stdoutl("[v2=v1][v1 is nil?]", v1 == nil)
54+
output.Stdoutl("[v2=v1][v2 is nil?]", v2 == nil) //lint:ignore SA4023 It's ok because this is just a example.
55+
output.Stdoutl("[v2=v1][v1 eq v2]", v1 == v2)
56+
57+
output.StdoutHr()
58+
59+
// 大事な点として、Goのすべてのポインタには2つの基本情報があるということ。
60+
// ポインターの型と、ポインターが指す値である。
61+
var (
62+
v3 *int
63+
v4 any
64+
)
65+
66+
output.Stdoutf("[v3]", "(%T,%v)\n", v3, v3) // (*int, <nil>)
67+
output.Stdoutf("[v4]", "(%T,%v)\n", v4, v4) // (<nil>, <nil>)
68+
69+
// v3とv4を (型, 値) として見ると同じではない
70+
// なので、同じかどうかを聞くと同じとならない
71+
output.Stdoutl("[v3 eq v4]", v3 == v4) //lint:ignore SA4023 It's ok because this is just a example.
72+
output.StdoutHr()
73+
74+
// ここで v3 を v4 に設定すると、値はnilのままだが、型が設定されるため同じになる
75+
v4 = v3
76+
output.Stdoutf("[v3]", "(%T,%v)\n", v3, v3) // (*int, <nil>)
77+
output.Stdoutf("[v4]", "(%T,%v)\n", v4, v4) // (*int, <nil>)
78+
output.Stdoutl("[v3 eq v4]", v3 == v4)
79+
output.StdoutHr()
80+
81+
// v4 は any, つまり interface{} である
82+
// Go のインターフェースは 型と値 が、両方 nil の場合に nil となる
83+
// つまり型だけが設定されている場合は nil とならない
84+
output.Stdoutl("[v4 == nil?]", v4 == nil) //lint:ignore SA4023 It's ok because this is just a example.
85+
86+
//
87+
// イディオムとして覚えておくことは、nilを設定したい場合は
88+
// 「nilな変数」を設定するのではなく、明示的に 「nil」 を設定すること
89+
//
90+
v4 = nil
91+
output.Stdoutf("[v4 = nil][v3]", "(%T,%v)\n", v3, v3) // (*int, <nil>)
92+
output.Stdoutf("[v4 = nil][v4]", "(%T,%v)\n", v4, v4) // (*int, <nil>)
93+
output.Stdoutl("[v4 = nil][v3 eq v4]", v3 == v4) //lint:ignore SA4023 It's ok because this is just a example.
94+
95+
return nil
96+
}

0 commit comments

Comments
 (0)