The Go Programming Language Specification says that:
Constants may be typed or untyped
I am having a little doubt in my understanding. Consider this example in the spec:
const l = "hi" // l == "hi" (untyped string constant)
const m = string(k) // m == "x" (type string)
The spec says:
constant may be given a type explicitly by a constant declaration or conversion, or implicitly when used in a variable declaration or an assignment or as an operand in an expression
By this statement, why isn't l
typed since it is clearly a constant declaration?
This behaviour is clearer with another example
type Foo string
func f(a Foo) {}
func main() {
f("sarkozy")
const t = "julie gayet"
f(t)
s := "hollande"
//compile error
// f(s)
f(Foo(s)) // ok
}
Is the reason that f("sarkozy")
compiles be due to this statement on Assignability in the spec?
x is an untyped constant representable by a value of type T.
My argument is the following:
Foo
means I can type coerce like this Foo("sarkozy")
f(s)
fails because s is not untyped.An untyped constant has no limits. When it's used in a context that requires a type, a type will be inferred and a limit applied. const big = 10000000000 // Ok, even though it's too big for an int. const bigger = big * 100 // Still ok. var i int = big / 100 // No problem: the new result fits in an int.
Instead, literals are Untyped string constants. It is a string (more correctly, its default type is string ), but it is not a Go value and therefore has no type until it is assigned or used in a context that is typed.
Untyped Constants They are not given a fixed type yet, like int32 or float64 or string , that would force them to obey Go's strict type rules. Note that, Although the value 1 is untyped, it is an untyped integer. So it can only be used where an integer is allowed.
Unnamed constants are all boolean, numeric and string values. Like unnamed constants, named constants can also be only boolean, numeric and string values. The keyword const is used to declare named constants. The following program contains some constant declarations.
Why isn't l typed since it is clearly a constant declaration?
Yes, it is clearly a constant declaration, as your quote says:
constant may be given a type explicitly by a constant declaration
However, in your case there is no explicitly given type. You can only have an implicitly given type when "used in a variable declaration or an assignment or as an operand in an expression".
Is the reason that f("sarkozy") compiles be due to this statement on Assignability in the spec?
Yes, the reason that f("sarkozy")
compiles is because the untyped constant of "sarkozy" has a type given implicitly when used as an operand in an expression such as in your case.
"sarkozy" is implicitly given the type of Foo
So why doesn't f(s)
compile? (okay, that was not in the question, but the question remains)
Your argument states that: "f(s) fails because s is not untyped."
True that s
is not untyped. s is a variable and not a constant, and variables cannot be untyped.
The Go specs states for Variable Declarations:
If the type is absent and the corresponding expression evaluates to an untyped constant, the type of the declared variable is as described in §Assignments.
And that refers, from what I understand to the following:
the constant is first converted to type bool, rune, int, float64, complex128 or string respectively, depending on whether the value is a boolean, rune, integer, floating-point, complex, or string constant.
So, the following line:
s := "hollande"
will declare the variable (not constant) s
of type string
because the right-hand expression is an untyped string constant. The type is implicitly given during the declaration of the variable, not by analyzing what context it which it later on will be used.
f(s) will then result in a compile error because you try to use a value of type string
where a value of type Foo
is expected.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With