回答

收藏

我如何在 Go 中做一个文字 *int64?

技术问答 技术问答 239 人阅读 | 0 人回复 | 2023-09-12

我有一个带*int结构类型64字段。4 \& y7 ]$ G& g
    type SomeType struct    SomeField *int64}( [: N" M, H6 w4 k7 f. A- ^
在我的代码中的某个时候,我想声明一个词(例如,当我知道值应该是 0或指向 0时,你知道我的意思)
6 h. a+ _9 x. L
    instance := SomeType{    SomeField: &0,}$ C; X( S- u3 q6 \: r$ h
…除了这不起作用4 L$ P/ {9 d% L/ l$ ?
    ./main.go:xx: cannot use &0 (type *int) as type *int64 in field value
    . [/ k: Q3 Y9 k! F- v
所以我试试这个% Y' I* a# Q* }

    % j7 [  s  I: ^  R
  • instance := SomeType{    SomeField: &int64(0)code]…但这也不起作用[code]./main.go:xx: cannot take the address of int64(0)6 b- X& y9 f9 ^3 A" k
我该怎么办?我能想出的唯一解决办法是使用占位符变量/ ]$ R' a' o# l* Z  a# _/ ^8 @
    var placeholder int64placeholder = 0instance := SomeType{    SomeField: &placeholder,}3 B& e. A7 b% n$ H, g
编辑:
( p8 J8 ~. d4 i3 H9 m显然,我的问题很模糊。我正在寻找一种字面说明a 的方法*int64.这可以用于构造函数,或解释文本结构值,甚至作为其他函数的参数。但辅助函数或使用不同类型并不是我正在寻找的解决方案。
, s" y; m* h% P+ R% ^3 M) Z1 S& Y5 z  p                                                                * z' h* }( V2 c8 @) J
    解决方案:                                                               
0 N& ^: m6 a- Z$ Y9 y; z                                                                Go 语言规范(地址操作符)不允许获得数字常量地址(不是无类型常量也不是类型常量)。
( [5 L9 h- K5 M+ j6 Q3 @! ^' |操作数必须是可寻址的,也就是说,变量、指针间接或切片索引操作;或字段选择器可以找到结构操作的数量;或数组索引操作可以找到数组。作为可搜索要求的例外,x[在&x]复合文字也可以在表达式中使用。
9 M; `; `) j9 q你的选择(在Go Playground尝试所有选项:+ j9 f2 M, }9 W  W! @& G# f
1) 与 new()您可以简单地使用内置new()函数分配新的零值int64并获地址:& x- [8 r! R2 |1 N: \
    instance := SomeType{    SomeField: new(int64),}
    # f" x, Z: u) S/ `
但请注意,这只能用于指向任何类型的零值指针的分配和获取。
1 L' D- Y% D. t2) 带辅助变量对于非零元素,最简单和推荐的是使用可获取地址的辅助变量:
* E# }) e: q& P! P5 u* M
    helper := int64(2)instance2 := SomeType{    SomeField: &helper,}
    / M& q7 [& X( D: t% G" g
3) 具有辅助功能注意:在我的github.com/icza/gox库中,gox该包提供辅助函数,用于获取指向非零值的指针,因此您不必将其添加到您需要的所有项目中。: b/ h! C% L) X' j0 R
或者,如果您多次需要此功能,您可以创建一个辅助函数来分配和返回一个函数*int64:) @% l2 p7 }4 t6 z$ j+ n7 E$ K
    func create(x int64) *int64 {    return &x}4 z0 P/ M! s" `% P" j7 |8 }' H( S
并使用它:
* N% t# R9 q  M+ O- |( n4 K  ?
    4 i7 j: }# G1 s0 H; M1 g3 r) g8 K
  • instance3 := SomeType{    SomeField: create(3)code]请注意,我们实际上没有分配任何东西,Go 当我们返回函数参数地址时,编译器就这样做了。Go 编译器进行转义分析,并在堆(而不是堆栈)上分配局部变量(如果可能转义函数)。详细信息,
    8 g/ J7 Y+ I  F( t4 `/ t$ }( @& }
  • 4) 带单行匿名函数[code]instance4 := SomeType{    SomeField: func() *int64 { i := int64(4); return &i}code]或者作为(短)替代方案:
    . u) F+ n" F1 U. v& q" f
  • [code]instance4 := SomeType{    SomeField: func(i int64) *int64 { return &i }code]5) 带切片的字面量、索引和地址如果你想*SomeField要成为别人0,你需要一些可以找到的东西。
    & M, ]7 [% P; N; J
  • 你还能做到,但这很丑:[code]instance5 := SomeType{    SomeField: &[]int64{5}[0]fmt.Println(*instance2.SomeField) // Prints 5
    , x. f) b4 I0 T: x/ b. `
这里发生的是一个[]int64切片是用文字创建的,有一个元素 ( 5)。并且它被索引(第0个元素)并取第0个元素的地址。在后台,一个 的数组[1]int64也将分配并用作切片的后备数组。所以这里有很多样板。! p' g2 H, U1 v5 m# |. a
6) 使用辅助结构文字让我们检查可寻址性要求的例外情况:
/ Y* \2 k/ T$ K2 L$ [. x2 `! \1 {  r' u作为可寻址要求的例外,x[在&x]复合文字也可以在表达式中使用。
/ w* _  n: [+ k, ?' v/ |* {- a! F这意味着使用复合文本的地址,如结构文本。如果我们这样做,我们将分配结构值并获得指向它的指针。但如果是这样,我们可以使用另一个要求:字段选择器可以找到结构操作数。因此,如果结构体的字面量包含 type 字段int我们还可以获得该字段的地址!7 R& Q  n  L2 d7 e
让我们来看看这个选项的实际效果。我们将使用这种包装结构类型:
* ^% u9 q# o- q$ h3 i
    type intwrapper struct    x int64}) c' m' W. z) R2 A: l
现在我们可以这样做了:
. R' e7 H' n9 z7 V  D- U
    instance6 := SomeType{    SomeField: &(&intwrapper{6}).x,}) |% P# F7 C3 @3 J/ A
请注意,这
4 h; u7 n  O9 V0 K7 `9 h6 Z5 X( {
    &(&intwrapper{6}).x; `* F8 q! H3 h5 B; k# a
意思如下:
9 Y% f0 u. t) j- ?2 l! i4 @/ D
    & ( (&intwrapper{6}).x )
    ' h; c$ f) Q* C, n; s" D
但由于地址运算符号,我们可以省略外括号&应用于选择器表达式结果。/ o' _; b' a1 \- G; R2 d
请注意,以下情况会发生在后台(这也是一种有效的语法):
7 {& v# O/ Y  r
    &(*(&intwrapper{6})).x
    4 q6 p: W$ [6 I2 O1 e: o
7) 使用辅助匿名结构文字原理与案例#6 是一样的,但我们也可以使用匿名结构的字面量,所以我们不需要定义帮助器/包装器的结构类型:
5 W* n/ U; x! v% }3 l0 V* @
    instance7 := SomeType{    SomeField: &(&struct{ x int64 }{7}).x,}
    ) ~" H8 ~2 V2 g9 S2 Y% E  k
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则