If I have this code, it works as expected:
package main
import "strconv"
type text []byte
func main() {
hello := text("hello")
_ = strconv.AppendQuote(hello, " world")
}
but this code fails:
package main
import "strconv"
type text string
func main() {
hello := text("hello")
// cannot use hello (type text) as type string in argument to strconv.Quote
_ = strconv.Quote(hello)
}
Why does one pass and the other fail? I checked the docs [1], but I didnt see anything that explained the difference.
CodePudding user response:
What you are looking for is under Assignability:
https://go.dev/ref/spec#Assignability
In particular:
x's type V and T have identical underlying types and at least one of V or T is not a defined type.
In both cases, the underlying types are equal ([]byte is required and text is passed in case 1, string is required and text is passed in case 2), but []byte is not a defined type and string is, so it works for the first case, but not the second.
CodePudding user response:
You need to piece together several definitions from the language specifications to understand what's going on:
First is Assignability:
x's type V and T have identical underlying types and at least one of V or T is not a defined type.
Then you need to examine your V and T.
In your first code snippet you have type text []byte (the V) and a function AppendQuote whose required argument is []byte (the T).
Do V and T have identical underlying types? Yes. text's underlying type is []byte by your definition, and []byte is a composite type, whose underlying type is itself. From Types:
Each type T has an underlying type: If T is one of the predeclared boolean, numeric, or string types, or a type literal, the corresponding underlying type is T itself
and the paragraph just above that:
Composite types —[...] slice, [...] — may be constructed using type literals.
And, is at least one of V or T not a defined type? Yes, []byte as stated above is a composite type.
Hence a variable of type text is assignable to []byte, including passing arguments to a function.
In your second code snippet you have type text string (the V) and a function Quote whose required argument is string (the T).
Do V and T have identical underlying types? Yes. One by definition, and the other one is the predeclared type string (same quote as above).
Finally, is at least one of V or T not a defined type? No! Both are defined types. text is defined by you and string is defined by the language specs in String types:
The predeclared string type is string; it is a defined type.
So assigning text to string does not meet the conditions for assignability and it gives a compiler error.
CodePudding user response:
AppendQuote accept []byte as argurment and your hello is defined as text type which is a []byte from your type definition, that is why it works.
func strconv.AppendQuote(dst []byte, s string) []byte see source code
while Quote accepts string as argument,
func strconv.Quote(s string) string see source code
And your hello type is []byte, not string. that's why it didn't work. you will either have to use the first case, or change your hello into string. e.g. _ = strconv.Quote("hello") in order for it to work.
