将零int声明为int32

I noticed that Go assertion doesn't work as I expect for zero int. Here is the code:

var i interface{}
i = 0
i32, ok := i.(int32)
fmt.Println(ok)
fmt.Println(i32)

The output is following:

false
0

I can't find an explanation of this behavior. Is it a bug?

No, it's not a bug, it's a well defined behavior.

This line:

i = 0

Is an assignment, and you use the untyped 0 integer constant to assign to i. Since a (concrete) type is needed to carry out the assignment (and is type being interface{} does not define one), the default type of that untyped constant will be used which is int. Read The Go Blog: Constants:

The answer is that an untyped constant has a default type, an implicit type that it transfers to a value if a type is needed where none is provided.

You can verify it if you modify it like this:

i2, ok := i.(int)
fmt.Println(ok)
fmt.Println(i2)

Which outputs:

true
0

If you would use a typed constant:

i = int32(0)

Then yes, the stored value would be of type int32, and you would get the same output:

i = int32(0)
i32, ok := i.(int32)
fmt.Println(ok)
fmt.Println(i32)

Try the examples on the Go Playground.

i doesn't contain an int32, it contains an int, and so the type assertion fails.

Assigning a literal value directly to an interface{} like this or using one in a short variable declaration can be a bit confusing because you don't really get to see what type of value you get; you need to know the rules for the "default type" of a constant. If this gives you trouble, you can explicitly cast it to a type, like i = int32(0), which will ensure that i does in fact contain an int32.