// 编译失败 // Invalid operation: passString == secretId (mismatched types string and Password) var passString = "" if passString == secretId { fmt.Println(passString) } }
funcmain() { testPrint() }
隐式类型转换的规则
查阅了golang spec之后,我们得到几个重要结论:
The only implicit conversion in Go is when an untyped
constant is used in a situation where a type is required.
Except for shift operations, if one operand is an untyped constant and the other
operand is not, the constant is implicitly converted to the type of
the other operand.
// typedValue 表示的是 int 类型,这个类型是由 int 关键词声明的 var typedValue int = 10 // untypedValue 虽然也是 int 类型,但是它是由 type inference 推导出来的 // 根据 golang spec,每个 untyped 类型都会有他的默认类型 // 例如 10 的 默认类型是 int,也就是他默认会被推到为 int 类型 var untypedValue = 10
// const int 类型 const constTypedValue int = 10 // const untyped int const constUntypedValue = 10
funcmain() { var untypedStr = "" var nonConstTypedStr string = "" const constUntypedStr = "" const constTypedStr string = ""
// <1> // Cannot use 'untypedStr' (type string) as the type Password printPassword(untypedStr) // <2> // Cannot use 'nonConstTypedStr' (type string) as the type Password printPassword(nonConstTypedStr) // <3> // 合法 printPassword(constUntypedStr) // <4> // Cannot use 'constTypedStr' (type string) as the type Password printPassword(constTypedStr) }
// DefaultLit on both nodes simultaneously; // if they're both ideal going in they better // get the same type going out. // force means must assign concrete (non-ideal) type. // The results of defaultlit2 MUST be assigned back to l and r, e.g. // // n.Left, n.Right = defaultlit2(n.Left, n.Right, force) funcdefaultlit2(l ir.Node, r ir.Node, force bool) (ir.Node, ir.Node) { // 如果l或者r为nil,则无法进行类型转换 if l.Type() == nil || r.Type() == nil { return l, r }
// 如果 l 和 r 都是非 interface 类型 if !l.Type().IsInterface() && !r.Type().IsInterface() { // 无法转换bool值和非bool值 // 也无法转换string和非string值 if l.Type().IsBoolean() != r.Type().IsBoolean() { return l, r } if l.Type().IsString() != r.Type().IsString() { return l, r } }
// 如果左边的变量有类型,则将右边的变量转换为左边的类型 // var b int // b = 10 // 此时尝试将 10 转换为 b 对应的类型 if !l.Type().IsUntyped() { r = convlit(r, l.Type()) return l, r }
// 如果左边的变量为无类型,并且右边的变量有类型,则将左边的类型转换为右边的类型 // var r int = 10 // var l = r // 此时尝试将 l 转换为 r 对应的类型 if !r.Type().IsUntyped() { l = convlit(l, r.Type()) return l, r }
if !force { return l, r }
// Can't mix nil with anything untyped. if ir.IsNil(l) || ir.IsNil(r) { return l, r } t := defaultType(mixUntyped(l.Type(), r.Type())) l = convlit(l, t) r = convlit(r, t) return l, r }