duanqinjiao5244 2014-09-01 08:33
浏览 83
已采纳

为什么对变量进行内联实例化需要显式地将其地址用作指针方法,而对于现有的var则隐式

Is there a reason for this behaviour? I would like to know what is different in the memory level. The compiler returns "cannot take the address of composite literal" while i can explicitly ask it to do it.

Heres the go playground go playground link

u := User{"john"}
fmt.Println(u.Name()) //implicit

//fmt.Println(User{"john"}.Name()) //Error: cannot call pointer method on composite literal, cannot take the address of composite literal
fmt.Println((&User{"jim"}).Name()) //explicit

type User struct {
    name string
}

func (u *User) Name() string {
    return u.name
}
  • 写回答

2条回答 默认 最新

  • duanhe4155 2014-09-01 08:43
    关注

    Because a composite litteral is not addressable until it's been assigned to a variable:

    The operand must be addressable, that is, either a variable, pointer indirection, or slice indexing operation; or a field selector of an addressable struct operand; or an array indexing operation of an addressable array.
    As an exception to the addressability requirement, x may also be a (possibly parenthesized) composite literal.

    You can take the address to User{"jim"}: (&User{"jim"}) (literal pointer).
    But you cannot directly use the value of User{"jim"} (literal value, not until it is assign to a variable).
    See more in this thread.


    This thread adds to the"Expression isn't addressable" issue:

    Taking the address of something, that up to this hypothetical point was not addressable (an expression that doesn't happen to be rooted to an identifier), is semantically no different then setting the dereferenced value of the destination pointer.
    In other words, the following are equivalent:

    var x *int
    *x = (2 * 3) + 4
    
    var x *int
    x = &((2 * 3) + 4)
    

    Since an expression is thrown away as soon as it's used, the address of its value (which often is entirely register-resident, and thus doesn't actually have an address) is entirely meaningless in any case, and the only benefit from taking it's address is the syntactic convenience of type-inference in variable declarations (saving at most a single line):

    x := &((2 * 3) + 4)
    

    A problem with making arbitrary expressions addressable:

    m := map[int]int{1:2}
    x := &m[1]
    x = 3
    fmt.Println("x is", x, "while m[1] is", m[1])
    // will print `x is 3 while m[1] is 2`
    

    In short: it'll be unclear (and nigh impossible to debug) whether you're taking the address of something you expect to be addressable, or when you're taking the address of an implicit intermediate var (which is very often what you don't want).

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 拓扑学,凸集,紧集。。
  • ¥15 如何扩大AIS数据容量
  • ¥15 单纯型python实现编译报错
  • ¥15 c++2013读写oracle
  • ¥15 c++ gmssl sm2验签demo
  • ¥15 关于模的完全剩余系(关键词-数学方法)
  • ¥15 有没有人懂这个博图程序怎么写,还要跟SFB连接,真的不会,求帮助
  • ¥15 PVE8.2.7无法成功使用a5000的vGPU,什么原因
  • ¥15 keil官网下载psn序列号在哪
  • ¥15 想用adb命令做一个通话软件,播放录音