string vs []byte type definition

huangapple go评论82阅读模式
英文:

string vs []byte type definition

问题

如果我有这段代码,它会按预期工作:

package main
import "strconv"

type text []byte

func main() {
   hello := text("hello")
   _ = strconv.AppendQuote(hello, " world")
}

但是这段代码会失败:

package main
import "strconv"

type text string

func main() {
   hello := text("hello")
   // 无法将hello(类型为text)作为strconv.Quote函数的参数类型string使用
   _ = strconv.Quote(hello)
}

为什么一个通过了而另一个失败了?我查看了文档[1],但没有找到解释这个差异的内容。

  1. https://go.dev/ref/spec#Type_definitions
英文:

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.

  1. <https://go.dev/ref/spec#Type_definitions>

答案1

得分: 3

你要找的内容在"Assignability"下面:

https://go.dev/ref/spec#Assignability

具体来说:

x的类型V和T具有相同的底层类型,并且V或T中至少有一个不是定义类型。

在这两种情况下,底层类型是相等的(在情况1中需要[]byte,并且传入的是text,在情况2中需要string,并且传入的是text),但是[]byte不是一个定义类型,而string是,所以它适用于第一种情况,但不适用于第二种情况。

英文:

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.

答案2

得分: 3

你需要从语言规范中整合几个定义来理解发生了什么:

首先是可赋值性

x的类型V和T具有相同的基础类型,并且V或T中至少有一个不是定义类型。

然后你需要检查V和T。

在你的第一个代码片段中,你有type text []byte(V),以及一个需要[]byte(T)作为参数的函数AppendQuote

V和T具有相同的基础类型吗?是的。根据你的定义,text的基础类型是[]byte,而[]byte是一个复合类型,其基础类型是它自身。根据类型

每个类型T都有一个基础类型:如果T是预声明的布尔、数值或字符串类型,或者是一个类型字面量,则相应的基础类型是T本身。

以及上面的段落:

复合类型——[...] 切片,[...]——可以使用类型字面量构造。

而且,V或T中至少有一个不是定义类型吗?是的,如上所述,[]byte是一个复合类型。

因此,text类型的变量可以赋值给[]byte,包括将参数传递给函数。


在你的第二个代码片段中,你有type text string(V),以及一个需要string(T)作为参数的函数Quote

V和T具有相同的基础类型吗?是的。一个是根据定义,另一个是预声明类型string(与上述引用相同)。

最后,V或T中至少有一个不是定义类型吗?**不!**两者都是定义类型。text是你定义的,而string是语言规范中定义的字符串类型

预声明的字符串类型是string;它是一个定义类型。

因此,将text赋值给string不满足可赋值性的条件,会导致编译器错误。

英文:

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.

<hr>

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.

答案3

得分: -2

AppendQuote函数接受[]byte类型的参数,而你的hello变量被定义为text类型,它是从你的类型定义中的[]byte类型得到的,所以它可以工作。

func strconv.AppendQuote(dst []byte, s string) []byte 查看源代码

Quote函数接受字符串作为参数,

func strconv.Quote(s string) string 查看源代码

而你的hello变量是[]byte类型,而不是字符串。这就是为什么它不起作用的原因。要使其工作,你要么使用第一种情况,要么将你的hello变量改为字符串。例如,_ = strconv.Quote("hello")

英文:

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(&quot;hello&quot;) in order for it to work.

huangapple
  • 本文由 发表于 2022年1月11日 00:14:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/70655543.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定