英文:
How does type conversion internally work? What is the memory utilization for the same?
问题
Go语言中的类型转换是通过内部机制实现的。类型转换的内存利用情况取决于具体的类型转换操作。例如,在你提供的代码示例中,类型转换的内存利用情况如下:
var str1 string
str1 = "26MB string data"
byt := []byte(str1)
str2 := string(byt)
在这个示例中,str1
是一个字符串变量,占用的内存空间取决于字符串的长度。byt
是将 str1
转换为字节切片的结果,它将占用与 str1
相同的内存空间。str2
是将 byt
转换回字符串的结果,它将占用与 byt
相同的内存空间。
当你进行类型转换时,并不会额外消耗更多的内存,因为类型转换只是改变了变量的类型,而不会改变变量的值或占用的内存空间。
关于你提到的内存不足错误,这可能是由于其他原因导致的,而不是类型转换本身。例如,在你的代码中,当你尝试将字符串转换为字节切片时,如果字符串的长度非常大,可能会导致内存不足。你可以尝试优化你的代码,例如使用流式处理来减少内存占用。
总结起来,类型转换本身不会额外消耗更多的内存,但是在处理大量数据时,需要注意内存的使用情况,以避免出现内存不足的错误。
英文:
How does Go type conversion internally work?
What is the memory utilisation for a type cast?
For example:
var str1 string
str1 = "26MB string data"
byt := []byte(str1)
str2 := string(byt)
whenever I type convert any variable, will it consume more memory?
I am concerned about this because when I try to unmarshall, I get "fatal error: runtime: out of memory"
err = json.Unmarshal([]byte(str1), &obj)
str1 value comes from HTTP response, but read using ioutils.ReadAll, hence it contains the complete response.
答案1
得分: 6
在Go语言中,将一个值转换为另一种类型称为"conversion"(而不是casting),这在规范:Conversions中有详细说明。
> 针对数值类型之间的(非常量)转换或者与字符串类型之间的转换,有特定的规则。这些转换可能会改变x
的表示并产生运行时开销。其他所有的转换只改变类型而不改变x
的表示。
因此,通常情况下,转换不会创建副本,只是改变类型。但是,转换到/从string
类型通常会创建副本,因为string
值是不可变的。例如,如果将string
转换为[]byte
不创建副本,那么通过修改结果字节切片的元素,就可以改变string
的内容。
请参考相关问题:https://stackoverflow.com/questions/32253768/does-convertion-between-alias-types-in-go-create-copies/32253871#32253871
在某些情况下(编译器优化),转换到/从string
不会创建副本,详细信息请参见https://stackoverflow.com/questions/43470284/golang-bytestring-vs-bytestring/43470344#43470344。
如果你已经将JSON内容作为string
值,并且想要进行解组,你不应该将其转换为[]byte
,只是为了解组。相反,可以使用strings.NewReader()
获取一个从传入的string
值读取的io.Reader
,并将该读取器传递给json.NewDecoder()
,这样你就可以在不复制大型输入JSON字符串的情况下进行解组。
代码示例:
input := "BIG JSON INPUT"
dec := json.NewDecoder(strings.NewReader(input))
var result YourResultType
if err := dec.Decode(&result); err != nil {
// 处理错误
}
还要注意,如果大型JSON字符串是从io.Reader
中读取的,那么这个解决方案可以进一步优化,此时你可以完全省略先读取字符串的步骤,直接将jsonSource
传递给json.NewDecoder()
,例如:
dec := json.NewDecoder(jsonSource)
var result YourResultType
if err := dec.Decode(&result); err != nil {
// 处理错误
}
英文:
It's called conversion in Go (not casting), and this is covered in Spec: Conversions:
> Specific rules apply to (non-constant) conversions between numeric types or to and from a string type. These conversions may change the representation of x
and incur a run-time cost. All other conversions only change the type but not the representation of x
.
So generally converting does not make a copy, only changes the type. Converting to / from string
usually does, as string
values are immutable, and for example if converting a string
to []byte
would not make a copy, you could change the content of the string
by changing elements of the resulting byte slice.
See related question: https://stackoverflow.com/questions/32253768/does-convertion-between-alias-types-in-go-create-copies/32253871#32253871
There are some exceptions (compiler optimizations) when converting to / from string
does not make a copy, for details see https://stackoverflow.com/questions/43470284/golang-bytestring-vs-bytestring/43470344#43470344.
If you already have your JSON content as a string
value which you want to unmarshal, you should not convert it to []byte
just for the sake of unmarshaling. Instead use strings.NewReader()
to obtain an io.Reader
which reads from the passed string
value, and pass this reader to json.NewDecoder()
, so you can unmarshal without having to make a copy of your big input JSON string.
This is how it could look like:
input := "BIG JSON INPUT"
dec := json.NewDecoder(strings.NewReader(input))
var result YourResultType
if err := dec.Decode(&result); err != nil {
// Handle error
}
Also note that this solution can further be optimized if the big JSON string is read from an io.Reader
, in which case you can completely omit reading it first, just pass that to json.NewDecoder()
directly, e.g.:
dec := json.NewDecoder(jsonSource)
var result YourResultType
if err := dec.Decode(&result); err != nil {
// Handle error
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论