v
can be explicitly converted to type T
, the conversion can be represented as the form (T)(v)
. For most cases, in particular T
is a type name (an identifier), the form can be simplified to T(v)
.
x
can be implicitly converted to a type T
, then it means x
can also be explicitly converted to type T
.
byte
and uint8
can be converted to each other.
rune
and int32
can be converted to each other.
[]byte
and []uint8
can be converted to each other.
x
and a non-interface type T
, assume the type of x
is Tx
,
Tx
and T
share the same underlying type (ignoring struct tags), then x
can be explicitly converted to T
.
Tx
or T
is a unnamed type and their underlying types are identical (considering struct tags), then x
can be implicitly converted to T
.
Tx
and T
have different underlying types, but both Tx
and T
are unnamed pointer types and their base types share the same underlying type (ignoring struct tags), then x
can be explicitly converted to T
.
package main
func main() {
// []int, IntSlice and MySlice share
// the same underlying type: []int
type IntSlice []int
type MySlice []int
type Foo = struct{n int `foo`}
type Bar = struct{n int `bar`}
var s = []int{}
var is = IntSlice{}
var ms = MySlice{}
var x map[Bar]Foo
var y map[Foo]Bar
// The two implicit conversions both doesn't work.
/*
is = ms // error
ms = is // error
*/
// Must use explicit conversions here.
is = IntSlice(ms)
ms = MySlice(is)
x = map[Bar]Foo(y)
y = map[Foo]Bar(x)
// Implicit conversions are okay here.
s = is
is = s
s = ms
ms = s
}
package main
func main() {
type MyInt int
type IntPtr *int
type MyIntPtr *MyInt
var pi = new(int) // the type of pi is *int
// ip and pi have the same underlying type,
// and the type of pi is unnamed, so
// the implicit conversion works.
var ip IntPtr = pi
// var _ *MyInt = pi // can't convert implicitly
var _ = (*MyInt)(pi) // ok, must explicitly
// Values of *int can't be converted to MyIntPtr
// directly, but can indirectly.
/*
var _ MyIntPtr = pi // can't convert implicitly
var _ = MyIntPtr(pi) // can't convert explicitly
*/
var _ MyIntPtr = (*MyInt)(pi) // ok
var _ = MyIntPtr((*MyInt)(pi)) // ok
// Values of IntPtr can't be converted to
// MyIntPtr directly, but can indirectly.
/*
var _ MyIntPtr = ip // can't convert implicitly
var _ = MyIntPtr(ip) // can't convert explicitly
*/
var _ MyIntPtr = (*MyInt)((*int)(ip)) // ok
var _ = MyIntPtr((*MyInt)((*int)(ip))) // ok
}
x
, assume its type Tx
is a bidirectional channel type, T
is also a channel type (bidirectional or not). If Tx
and T
have the identical element type, and either Tx
or T
is an unnamed type, then x
can be implicitly converted to T
.
package main
func main() {
type C chan string
type C1 chan<- string
type C2 <-chan string
var ca C
var cb chan string
cb = ca // ok, same underlying type
ca = cb // ok, same underlying type
// The 4 lines compile okay for this 3rd rule.
var _, _ chan<- string = ca, cb // ok
var _, _ <-chan string = ca, cb // ok
var _ C1 = cb // ok
var _ C2 = cb // ok
// Values of C can't be converted
// to C1 and C2 directly.
/*
var _ = C1(ca) // compile error
var _ = C2(ca) // compile error
*/
// Values of C can be converted
// to C1 and C2 indirectly.
var _ = C1((chan<- string)(ca)) // ok
var _ = C2((<-chan string)(ca)) // ok
var _ C1 = (chan<- string)(ca) // ok
var _ C2 = (<-chan string)(ca) // ok
}
x
and an interface type I
, if the type (or the default type) of x
is Tx
and Tx
implements I
, then x
can be implicitly converted to type I
. The conversion result is an interface value (of type I
), which boxes
x
, if Tx
is a non-interface type;
x
, if Tx
is an interface type.
T
, if the untyped value can represent as values of type T
.
package main
func main() {
var _ []int = nil
var _ map[string]int = nil
var _ chan string = nil
var _ func()() = nil
var _ *bool = nil
var _ interface{} = nil
var _ int = 123.0
var _ float64 = 123
var _ int32 = 1.23e2
var _ int8 = 1 + 0i
}
x
and a basic type T
, if x
is representable as a value of type T
, then x
can be explicitly converted to T
. In particular if x
is an untyped value, then x
can be implicitly converted to T
.
package main
func main() {
// The implicit conversions are all legal.
const I = 123
const I1, I2 int8 = 0x7F, -0x80
const I3, I4 int8 = I, 0.0
const F = 0.123456789
const F32 float32 = F
const F32b float32 = I
const F64 float64 = F
const C1, C2 complex64 = F, I
// const F64b float64 = I3 // doesn't compile
const F64b = float64(I3) // compiles okay
// const I5 int = C2 // doesn't compile
const I5 = int(C2) // compiles okay
}
package main
import "fmt"
func main() {
var a, b = 1.6, -1.6 // both are float64
fmt.Println(int(a), int(b)) // 1 -1
var i, j int16 = 0x7FFF, -0x8000
fmt.Println(int8(i), uint16(j)) // -1 32768
var c1 complex64 = 1 + 2i
var _ = complex128(c1)
}
[]byte
(a.k.a., []uint8
), and vice versa.
[]rune
(a.k.a., []int32
), and vice versa.
unsafe.Pointer
, and vice versa.
unsafe.Pointer
, and vice versa.
nil
identifiers).
package main
// Some variables of incomparable types.
var s []int
var m map[int]int
var f func()()
var t struct {x []int}
var a [5]map[int]int
func main() {
// The following lines fail to compile.
/*
_ = s == s
_ = m == m
_ = f == f
_ = t == t
_ = a == a
_ = nil == nil
_ = s == interface{}(nil)
_ = m == interface{}(nil)
_ = f == interface{}(nil)
*/
// The following lines compile okay.
_ = s == nil
_ = m == nil
_ = f == nil
_ = 123 == interface{}(nil)
_ = true == interface{}(nil)
_ = "abc" == interface{}(nil)
}
T
. (If they have different types, one of them must be implicitly convertible to the type of the other. Here we don't consider the cases in which both the two values are untyped.)
T
is a boolean type, then the two values are equal only if they are both true
or both false
.
T
is an integer type, then the two values are equal only if they have the same representation in memory.
T
is a floating-point type, then the two values are equal only if any of the following conditions is satisfied:
+Inf
.
-Inf
.
-0.0
or +0.0
.
NaN
and they have the same bytes representations in memory.
T
is a complex type, then the two values are equal only if their real parts (as floating-point values) and imaginary parts (as floating-point values) are both equal.
T
is a pointer type (either safe or unsafe), then the two values are equal only if the memory addresses stored in them are equal.
T
is a channel type, the two channel values are equal if they both reference the same underlying internal channel structure value or they are both nil channels.
T
is a struct type, then each pair of the corresponding fields of the two struct values will be compared.
T
is an array type, then each pair of the corresponding elements of the two array values will be compared.
T
is an interface type, please read how two interface values are compared.
T
is a string type, please read how two string values are compared.
package main
func main() {
type T struct {
a interface{}
b int
}
var x interface{} = []int{}
var y = T{a: x}
var z = [3]T{{a: y}}
// Each of the following line can produce a panic.
_ = x == x
_ = y == y
_ = z == z
}
The Go 101 project is hosted on Github. Welcome to improve Go 101 articles by submitting corrections for all kinds of mistakes, such as typos, grammar errors, wording inaccuracies, description flaws, code bugs and broken links.
If you would like to learn some Go details and facts every serveral days, please follow Go 101's official Twitter account @zigo_101.
reflect
standard package.sync
standard package.sync/atomic
standard package.nil
in Go