String 对Go中字符串文字的引用
在我的应用程序中,我经常传递对静态字符串的引用。我希望避免为每个调用分配内存,但我无法获取字符串文本的地址 为什么不能获取字符串文本的地址(请参见下面示例中的String 对Go中字符串文字的引用,string,pointers,go,string-literals,String,Pointers,Go,String Literals,在我的应用程序中,我经常传递对静态字符串的引用。我希望避免为每个调用分配内存,但我无法获取字符串文本的地址 为什么不能获取字符串文本的地址(请参见下面示例中的test1())?我是否误解了语法,或者这是由于Go的内部工作造成的限制 如果不可能,最好的解决方案是什么 test2()可以工作,但是每次它都会为var-hej分配内存吗? test3()不会分配任何新内存,但我希望避免函数之外的混乱 package main import "fmt" var konnichiwa = `こんにちは世
test1()
)?我是否误解了语法,或者这是由于Go的内部工作造成的限制
如果不可能,最好的解决方案是什么
test2()
可以工作,但是每次它都会为var-hej
分配内存吗?test3()
不会分配任何新内存,但我希望避免函数之外的混乱
package main
import "fmt"
var konnichiwa = `こんにちは世界`
// Gives the compile error `cannot take the address of "Hello world"`
func test1() (*string) { return &`Hello world` }
// Works fine
func test2() (*string) {
hej := `Hej världen`
return &hej
}
func test3() (*string) { return &konnichiwa }
func main(){
fmt.Println(*test1())
fmt.Println(*test2())
fmt.Println(*test3())
}
谢谢你的帮助 go中的字符串是不可变的,它只是一个指针和一个长度(总长度:2个单词) 因此,您不必使用指针来有效地处理它
只需传递字符串。获取文本(字符串、数字等)的地址是非法的,因为它的语义不明确 你是用实际常数的地址吗?这将允许修改该值(并可能导致运行时错误),还是要分配一个新对象,复制常量并将地址获取到新版本 在
test2
的情况下不存在这种歧义,因为您处理的是一个语义定义明确的现有变量。如果字符串被定义为const
,则相同的操作将不起作用
语言规范通过明确不允许您要求的内容来避免这种歧义。解决方案是test2
。虽然它略为冗长,但它保持了规则的简单和干净
当然,每一条规则都有其例外情况,在Go中,这涉及复合文字:以下内容是合法的,并在规范中定义为:
func f() interface{} {
return &struct {
A int
B int
}{1, 2}
}
v:=&T{1,“foo”}
但不适用于简单的值,如
w:=&1
x:=&“foo”
对于传递“静态”字符串的最佳解决方案的问题
package main
import "fmt"
var konnichiwa = `こんにちは世界`
func test1() *string {
s := `Hello world`
return &s
}
func test2() string {
return `Hej världen`
}
func test3() string {
return konnichiwa
}
func main() {
fmt.Println(*test1())
fmt.Println(test2())
fmt.Println(test3())
}
现在询问编译器:
> go tool 6g -S t.go
(我将程序命名为t.go。)搜索输出以查找对runtime.new的调用。只有一个!我会为你破坏它,它在测试1中
因此,在不偏离太多切线的情况下,对编译器输出的一点观察表明,我们通过使用字符串类型而不是*string来避免分配。我使用接口{}来指示我的字符串有时为零。就我而言,它看起来像:
testCases := []struct {
Values map[string]interface{}
}{
{
Values: map[string]interface{}{"var1": nil},
},
{
Values: map[string]interface{}{"var1": "my_cool_string"},
},
}
稍后在以下代码中(您可能还需要断言检查):
我不仅更好地理解了Go何时决定分配新内存,而且更好(或更糟!)您还教我如何使用
Go工具
自己获取程序集。该死的,现在我将坐在那里分析Go的汇编代码,享受几个小时的乐趣。谢谢(是的,我会坚持你的解决方案)我得到了错误go工具:使用go 1.10时没有这样的工具“6g”
,但这是有效的:go工具编译-S t.go
对于空字符串为有效值的结构,需要什么可选属性?这没有帮助,因为某些API需要向字符串传递指针。
if v != nil {
vv := v.(string)
}