回答

收藏

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

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

我有一个带*int结构类型64字段。0 b! ^' _' o' P' _8 F
    type SomeType struct    SomeField *int64}
    ' @( W, K8 w. t6 o2 A6 j; K# t
在我的代码中的某个时候,我想声明一个词(例如,当我知道值应该是 0或指向 0时,你知道我的意思)
( V# \3 e/ e: F8 [
    instance := SomeType{    SomeField: &0,}
    2 L' Z8 R6 K6 q& ~
…除了这不起作用
3 l; p5 I) v* h5 M- f) v% M
    ./main.go:xx: cannot use &0 (type *int) as type *int64 in field value  _. j! y2 t1 K/ q: l; d
所以我试试这个, u5 ?( ~; ?% V* C9 _

    ( i$ N! i+ C' @& O1 R7 w  j6 F& ]
  • instance := SomeType{    SomeField: &int64(0)code]…但这也不起作用[code]./main.go:xx: cannot take the address of int64(0)0 V  Q' o; k9 T4 E5 Y$ c
我该怎么办?我能想出的唯一解决办法是使用占位符变量
/ E, G* w1 P0 N  h
    var placeholder int64placeholder = 0instance := SomeType{    SomeField: &placeholder,}# m6 d7 \! `) a& {& W
编辑:
4 t* e0 J4 {4 P1 r显然,我的问题很模糊。我正在寻找一种字面说明a 的方法*int64.这可以用于构造函数,或解释文本结构值,甚至作为其他函数的参数。但辅助函数或使用不同类型并不是我正在寻找的解决方案。$ h4 b0 d5 c$ o! c( G0 A% i/ K1 w
                                                                5 j( K& @. O. D" c, Z
    解决方案:                                                               
" _- U& ]3 G$ h                                                                Go 语言规范(地址操作符)不允许获得数字常量地址(不是无类型常量也不是类型常量)。
5 a) _; F0 f# V9 }+ L1 O' G2 C1 f操作数必须是可寻址的,也就是说,变量、指针间接或切片索引操作;或字段选择器可以找到结构操作的数量;或数组索引操作可以找到数组。作为可搜索要求的例外,x[在&x]复合文字也可以在表达式中使用。9 w- H8 I% x, ~/ H, G4 v
你的选择(在Go Playground尝试所有选项:
" u6 M6 u3 [  }2 X1) 与 new()您可以简单地使用内置new()函数分配新的零值int64并获地址:
: Y: Q) s* T. i; X
    instance := SomeType{    SomeField: new(int64),}7 G% a1 y) d# j: D$ n0 _1 q
但请注意,这只能用于指向任何类型的零值指针的分配和获取。2 {3 A) u9 ^0 a) M: Q; M2 D+ j8 B
2) 带辅助变量对于非零元素,最简单和推荐的是使用可获取地址的辅助变量:6 M* b0 X+ H" L( d) F) K6 s
    helper := int64(2)instance2 := SomeType{    SomeField: &helper,}1 t: d) O, _+ e! S3 j" Y; k. @
3) 具有辅助功能注意:在我的github.com/icza/gox库中,gox该包提供辅助函数,用于获取指向非零值的指针,因此您不必将其添加到您需要的所有项目中。
0 G: r! w9 ^9 O* ?& n6 [( v+ v或者,如果您多次需要此功能,您可以创建一个辅助函数来分配和返回一个函数*int64:
5 |- ]7 i7 s& ?# A+ n. a
    func create(x int64) *int64 {    return &x}
    ! }- _$ d  l1 ~
并使用它:+ P6 `7 A8 ]; C6 }' [

    / |* |2 u; F- l6 _9 y3 u  R
  • instance3 := SomeType{    SomeField: create(3)code]请注意,我们实际上没有分配任何东西,Go 当我们返回函数参数地址时,编译器就这样做了。Go 编译器进行转义分析,并在堆(而不是堆栈)上分配局部变量(如果可能转义函数)。详细信息,0 ?& D+ V- C) Z3 l( D4 ]+ x
  • 4) 带单行匿名函数[code]instance4 := SomeType{    SomeField: func() *int64 { i := int64(4); return &i}code]或者作为(短)替代方案:
    2 g8 U# i9 l* s# l& C3 W' e  F0 T3 b
  • [code]instance4 := SomeType{    SomeField: func(i int64) *int64 { return &i }code]5) 带切片的字面量、索引和地址如果你想*SomeField要成为别人0,你需要一些可以找到的东西。  _( N& X% y' v; r% ^2 m
  • 你还能做到,但这很丑:[code]instance5 := SomeType{    SomeField: &[]int64{5}[0]fmt.Println(*instance2.SomeField) // Prints 5
    $ Q% G4 n  Q4 I3 A% ?. j1 h7 t/ J$ s
这里发生的是一个[]int64切片是用文字创建的,有一个元素 ( 5)。并且它被索引(第0个元素)并取第0个元素的地址。在后台,一个 的数组[1]int64也将分配并用作切片的后备数组。所以这里有很多样板。
  I- p3 h" c8 O, D( }% `. b6) 使用辅助结构文字让我们检查可寻址性要求的例外情况:
4 M1 ~9 L3 G/ T( C作为可寻址要求的例外,x[在&x]复合文字也可以在表达式中使用。
1 G- b! x. r; ^* w这意味着使用复合文本的地址,如结构文本。如果我们这样做,我们将分配结构值并获得指向它的指针。但如果是这样,我们可以使用另一个要求:字段选择器可以找到结构操作数。因此,如果结构体的字面量包含 type 字段int我们还可以获得该字段的地址!
% `9 b$ ~1 Y0 x4 P+ O5 G让我们来看看这个选项的实际效果。我们将使用这种包装结构类型:, v! ]$ v1 C  C7 o6 O
    type intwrapper struct    x int64}
    1 ^5 Z: y! X  ~: `3 H8 w! g5 d
现在我们可以这样做了:
) W% E4 ^" ~2 w1 R
    instance6 := SomeType{    SomeField: &(&intwrapper{6}).x,}
    - g5 Y6 D5 F& R
请注意,这2 Y8 q" c. [3 S7 m
    &(&intwrapper{6}).x4 m# u0 V8 ^0 s( D
意思如下:
# E' k& j' ]2 h
    & ( (&intwrapper{6}).x )0 E4 e1 D% F. _+ {
但由于地址运算符号,我们可以省略外括号&应用于选择器表达式结果。  V$ K' D8 H; q3 Q9 v6 Z2 C: C
请注意,以下情况会发生在后台(这也是一种有效的语法):( J3 |/ \& V+ o- i
    &(*(&intwrapper{6})).x+ Q4 ~0 H8 u1 ^& f1 u$ `
7) 使用辅助匿名结构文字原理与案例#6 是一样的,但我们也可以使用匿名结构的字面量,所以我们不需要定义帮助器/包装器的结构类型:
! h1 b" g& ~) ?3 K! W/ o
    instance7 := SomeType{    SomeField: &(&struct{ x int64 }{7}).x,}
    9 _; e% }! S- }% F  s! f( g
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则